webcoreui 1.2.0 → 1.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 (82) hide show
  1. package/README.md +14 -6
  2. package/astro.d.ts +9 -0
  3. package/astro.js +6 -0
  4. package/components/Accordion/Accordion.astro +1 -0
  5. package/components/Accordion/Accordion.svelte +1 -1
  6. package/components/Accordion/Accordion.tsx +1 -1
  7. package/components/Accordion/accordion.ts +1 -0
  8. package/components/Avatar/Avatar.astro +4 -2
  9. package/components/Avatar/Avatar.svelte +6 -4
  10. package/components/Avatar/Avatar.tsx +4 -2
  11. package/components/Badge/Badge.astro +2 -0
  12. package/components/Badge/Badge.svelte +2 -0
  13. package/components/Badge/Badge.tsx +2 -0
  14. package/components/Badge/badge.module.scss +26 -0
  15. package/components/Badge/badge.ts +1 -0
  16. package/components/Checkbox/Checkbox.svelte +2 -0
  17. package/components/Checkbox/Checkbox.tsx +0 -2
  18. package/components/Checkbox/checkbox.ts +3 -1
  19. package/components/Collapsible/collapsible.ts +1 -1
  20. package/components/Counter/Counter.astro +164 -0
  21. package/components/Counter/Counter.svelte +141 -0
  22. package/components/Counter/Counter.tsx +161 -0
  23. package/components/Counter/counter.module.scss +155 -0
  24. package/components/Counter/counter.ts +21 -0
  25. package/components/DataTable/DataTable.astro +4 -4
  26. package/components/DataTable/DataTable.svelte +1 -1
  27. package/components/DataTable/DataTable.tsx +2 -2
  28. package/components/Icon/map.ts +2 -0
  29. package/components/Image/Image.astro +45 -0
  30. package/components/Image/Image.svelte +51 -0
  31. package/components/Image/Image.tsx +52 -0
  32. package/components/Image/image.module.scss +47 -0
  33. package/components/Image/image.ts +13 -0
  34. package/components/ImageLoader/ImageLoader.astro +82 -0
  35. package/components/ImageLoader/ImageLoader.svelte +72 -0
  36. package/components/ImageLoader/ImageLoader.tsx +82 -0
  37. package/components/ImageLoader/imageloader.module.scss +13 -0
  38. package/components/ImageLoader/imageloader.ts +6 -0
  39. package/components/Input/input.ts +2 -2
  40. package/components/List/List.astro +3 -0
  41. package/components/List/List.svelte +12 -9
  42. package/components/List/List.tsx +3 -0
  43. package/components/List/list.module.scss +5 -0
  44. package/components/List/list.ts +40 -39
  45. package/components/Menu/Menu.tsx +1 -1
  46. package/components/Pagination/Pagination.tsx +1 -1
  47. package/components/Pagination/pagination.module.scss +1 -0
  48. package/components/Popover/Popover.astro +28 -26
  49. package/components/Popover/Popover.svelte +2 -0
  50. package/components/Popover/Popover.tsx +2 -0
  51. package/components/Popover/popover.module.scss +10 -2
  52. package/components/Popover/popover.ts +17 -16
  53. package/components/Progress/Progress.astro +6 -2
  54. package/components/Progress/Progress.svelte +6 -2
  55. package/components/Progress/Progress.tsx +6 -2
  56. package/components/Progress/progress.module.scss +15 -0
  57. package/components/Progress/progress.ts +1 -0
  58. package/components/RangeSlider/RangeSlider.astro +5 -0
  59. package/components/RangeSlider/RangeSlider.svelte +3 -3
  60. package/components/RangeSlider/RangeSlider.tsx +1 -1
  61. package/components/RangeSlider/rangeslider.ts +1 -0
  62. package/components/Switch/Switch.svelte +2 -0
  63. package/components/Switch/Switch.tsx +0 -2
  64. package/components/Switch/switch.module.scss +1 -0
  65. package/components/Switch/switch.ts +3 -1
  66. package/components/Textarea/Textarea.svelte +2 -0
  67. package/components/Textarea/textarea.ts +7 -6
  68. package/components/ThemeSwitcher/themeswitcher.module.scss +1 -0
  69. package/components/ThemeSwitcher/themeswitcher.ts +1 -0
  70. package/icons/minus.svg +3 -0
  71. package/icons.d.ts +1 -0
  72. package/icons.js +1 -0
  73. package/index.d.ts +12 -5
  74. package/package.json +111 -109
  75. package/react.d.ts +9 -0
  76. package/react.js +6 -0
  77. package/scss/resets.scss +2 -0
  78. package/svelte.d.ts +9 -0
  79. package/svelte.js +6 -0
  80. package/utils/DOMUtils.ts +3 -3
  81. package/utils/modal.ts +2 -2
  82. package/utils/popover.ts +87 -46
@@ -0,0 +1,52 @@
1
+ import React from 'react'
2
+ import type { ImageProps } from './image'
3
+
4
+ import AspectRatio from '../AspectRatio/AspectRatio.tsx'
5
+ import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.tsx'
6
+
7
+ import { classNames } from '../../utils/classNames'
8
+
9
+ import styles from './image.module.scss'
10
+
11
+ const Image = ({
12
+ src,
13
+ alt,
14
+ width,
15
+ height,
16
+ lazy,
17
+ ratio,
18
+ center,
19
+ full,
20
+ rounded,
21
+ className,
22
+ ...rest
23
+ }: ImageProps) => {
24
+ const classes = classNames([
25
+ styles.img,
26
+ center && styles.center,
27
+ full && styles[full],
28
+ rounded && styles[rounded],
29
+ className
30
+ ])
31
+
32
+ return (
33
+ <ConditionalWrapper
34
+ condition={!!ratio}
35
+ wrapper={children => (
36
+ <AspectRatio ratio={ratio || ''}>{children}</AspectRatio>
37
+ )}
38
+ >
39
+ <img
40
+ {...rest}
41
+ src={src}
42
+ alt={alt || ''}
43
+ width={width}
44
+ height={height}
45
+ loading={lazy ? 'lazy' : undefined}
46
+ className={classes}
47
+ />
48
+ </ConditionalWrapper>
49
+ )
50
+ }
51
+
52
+ export default Image
@@ -0,0 +1,47 @@
1
+ @use '../../scss/config.scss' as *;
2
+
3
+ .img {
4
+ &.center {
5
+ @include spacing(auto-none);
6
+ }
7
+
8
+ &.width {
9
+ @include size('w100%');
10
+ }
11
+
12
+ &.height {
13
+ @include size('h100%');
14
+ }
15
+
16
+ &.both {
17
+ @include size(100%);
18
+ }
19
+
20
+ &.top {
21
+ @include border-radius(top);
22
+ }
23
+
24
+ &.bottom {
25
+ @include border-radius(bottom);
26
+ }
27
+
28
+ &.left {
29
+ @include border-radius(left);
30
+ }
31
+
32
+ &.right {
33
+ @include border-radius(right);
34
+ }
35
+
36
+ &.diagonal {
37
+ @include border-radius(diagonal);
38
+ }
39
+
40
+ &.reverse-diagonal {
41
+ @include border-radius(reverse-diagonal);
42
+ }
43
+
44
+ &.none {
45
+ @include border-radius(none);
46
+ }
47
+ }
@@ -0,0 +1,13 @@
1
+ export type ImageProps = {
2
+ src: string
3
+ alt: string
4
+ width: number | string
5
+ height: number | string
6
+ lazy?: boolean
7
+ ratio?: string
8
+ center?: boolean
9
+ full?: 'width' | 'height' | 'both'
10
+ rounded?: 'top' | 'bottom' | 'left' | 'right' | 'diagonal' | 'reverse-diagonal' | 'none'
11
+ className?: string
12
+ [key: string]: any
13
+ }
@@ -0,0 +1,82 @@
1
+ ---
2
+ import type { ImageLoaderProps } from './imageloader'
3
+
4
+ import Image from '../Image/Image.astro'
5
+ import Skeleton from '../Skeleton/Skeleton.astro'
6
+
7
+ import { classNames } from '../../utils/classNames'
8
+
9
+ import styles from './imageloader.module.scss'
10
+
11
+ interface Props extends ImageLoaderProps {}
12
+
13
+ const {
14
+ fallback,
15
+ animate,
16
+ type,
17
+ width,
18
+ height,
19
+ color,
20
+ waveColor,
21
+ className,
22
+ ...rest
23
+ } = Astro.props
24
+
25
+ const styleVariables = classNames([
26
+ `width: ${width}px;`,
27
+ `height: ${height}px;`
28
+ ])
29
+ ---
30
+
31
+ <div data-id="w-image-loader" class={styles.loader} style={styleVariables}>
32
+ <Skeleton
33
+ animate={animate}
34
+ type={type}
35
+ width={Number(width)}
36
+ height={Number(height)}
37
+ color={color}
38
+ waveColor={waveColor}
39
+ className={className}
40
+ />
41
+ <Image
42
+ width={width}
43
+ height={height}
44
+ className={className}
45
+ data-fallback={fallback}
46
+ {...rest}
47
+ />
48
+ </div>
49
+
50
+ <script>
51
+ import { get, on } from '../../utils/DOMUtils'
52
+
53
+ const addEventListeners = () => {
54
+ const images = get<HTMLImageElement>('[data-id="w-image-loader"] img', true)
55
+
56
+ if (!images || !(images instanceof NodeList)) {
57
+ return
58
+ }
59
+
60
+ images.forEach(img => {
61
+ const container = img.parentElement as HTMLDivElement
62
+ const skeleton = container.firstElementChild as HTMLDivElement
63
+
64
+ const handleError = () => {
65
+ img.src = img.dataset.fallback || img.src
66
+ skeleton?.remove()
67
+ }
68
+
69
+ if (img.complete) {
70
+ img.naturalWidth === 0 ? handleError() : skeleton?.remove()
71
+
72
+ return
73
+ }
74
+
75
+ img.addEventListener('load', () => skeleton?.remove(), { once: true })
76
+ img.addEventListener('error', () => handleError(), { once: true })
77
+ })
78
+ }
79
+
80
+ on(document, 'astro:after-swap', addEventListeners)
81
+ addEventListeners()
82
+ </script>
@@ -0,0 +1,72 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte'
3
+ import type { ImageLoaderProps } from './imageloader'
4
+
5
+ import Image from '../Image/Image.svelte'
6
+ import Skeleton from '../Skeleton/Skeleton.svelte'
7
+
8
+ import { classNames } from '../../utils/classNames'
9
+
10
+ import styles from './imageloader.module.scss'
11
+
12
+ const {
13
+ fallback,
14
+ animate,
15
+ type,
16
+ width,
17
+ height,
18
+ color,
19
+ waveColor,
20
+ className,
21
+ ...rest
22
+ }: ImageLoaderProps = $props()
23
+
24
+ let container: HTMLDivElement
25
+
26
+ const styleVariables = classNames([
27
+ `width: ${width}px;`,
28
+ `height: ${height}px;`
29
+ ])
30
+
31
+ onMount(() => {
32
+ const img = container.querySelector<HTMLImageElement>('img')
33
+ const skeleton = container.querySelector<HTMLDivElement>('div')
34
+
35
+ if (!img) {
36
+ return
37
+ }
38
+
39
+ const handleError = () => {
40
+ img.src = img.dataset.fallback || img.src
41
+ skeleton?.remove()
42
+ }
43
+
44
+ if (img.complete) {
45
+ img.naturalWidth === 0 ? handleError() : skeleton?.remove()
46
+
47
+ return
48
+ }
49
+
50
+ img.addEventListener('load', () => skeleton?.remove(), { once: true })
51
+ img.addEventListener('error', handleError, { once: true })
52
+ })
53
+ </script>
54
+
55
+ <div class={styles.loader} style={styleVariables} bind:this={container}>
56
+ <Skeleton
57
+ animate={animate}
58
+ type={type}
59
+ width={Number(width)}
60
+ height={Number(height)}
61
+ color={color}
62
+ waveColor={waveColor}
63
+ className={className}
64
+ />
65
+ <Image
66
+ width={width}
67
+ height={height}
68
+ className={className}
69
+ data-fallback={fallback}
70
+ {...rest}
71
+ />
72
+ </div>
@@ -0,0 +1,82 @@
1
+ import React, { useEffect, useRef } from 'react'
2
+ import type { ImageLoaderProps } from './imageloader'
3
+
4
+ import Image from '../Image/Image.tsx'
5
+ import Skeleton from '../Skeleton/Skeleton.tsx'
6
+
7
+ import styles from './imageloader.module.scss'
8
+
9
+ const ImageLoader = ({
10
+ fallback,
11
+ animate,
12
+ type,
13
+ width,
14
+ height,
15
+ color,
16
+ waveColor,
17
+ className,
18
+ ...rest
19
+ }: ImageLoaderProps) => {
20
+ const containerRef = useRef<HTMLDivElement>(null)
21
+ const styleVariables = {
22
+ width,
23
+ height
24
+ }
25
+
26
+ useEffect(() => {
27
+ if (!containerRef.current) {
28
+ return
29
+ }
30
+
31
+ const img = containerRef.current.querySelector<HTMLImageElement>('img')
32
+ const skeleton = containerRef.current.querySelector<HTMLDivElement>('div')
33
+
34
+ if (!img) {
35
+ return
36
+ }
37
+
38
+ const removeSkeleton = () => skeleton?.remove()
39
+
40
+ const handleError = () => {
41
+ img.src = img.dataset.fallback || img.src
42
+ removeSkeleton()
43
+ }
44
+
45
+ if (img.complete) {
46
+ img.naturalWidth === 0 ? handleError() : removeSkeleton()
47
+
48
+ return
49
+ }
50
+
51
+ img.addEventListener('load', removeSkeleton, { once: true })
52
+ img.addEventListener('error', handleError, { once: true })
53
+
54
+ return () => {
55
+ img.removeEventListener('load', removeSkeleton)
56
+ img.removeEventListener('error', handleError)
57
+ }
58
+ }, [containerRef])
59
+
60
+ return (
61
+ <div className={styles.loader} style={styleVariables} ref={containerRef}>
62
+ <Skeleton
63
+ animate={animate}
64
+ type={type}
65
+ width={Number(width)}
66
+ height={Number(height)}
67
+ color={color}
68
+ waveColor={waveColor}
69
+ className={className}
70
+ />
71
+ <Image
72
+ width={width}
73
+ height={height}
74
+ className={className}
75
+ data-fallback={fallback}
76
+ {...rest}
77
+ />
78
+ </div>
79
+ )
80
+ }
81
+
82
+ export default ImageLoader
@@ -0,0 +1,13 @@
1
+ @use '../../scss/config.scss' as *;
2
+
3
+ .loader {
4
+ @include position(relative);
5
+
6
+ div + img {
7
+ @include visibility(0);
8
+ }
9
+
10
+ img {
11
+ @include position(absolute, t0, l0);
12
+ }
13
+ }
@@ -0,0 +1,6 @@
1
+ import type { ImageProps } from '../Image/image'
2
+ import type { SkeletonProps } from '../Skeleton/skeleton'
3
+
4
+ export type ImageLoaderProps = {
5
+ fallback?: string
6
+ } & ImageProps & Omit<SkeletonProps, 'width' | 'height'>
@@ -48,7 +48,7 @@ export type InputProps = {
48
48
  export type SvelteInputProps = {
49
49
  onChange?: (event: Event & InputTarget) => void
50
50
  onKeyUp?: (event: KeyboardEvent & InputTarget) => void
51
- onInput?: (event: any) => void
51
+ onInput?: (event: Event & InputTarget) => void
52
52
  onClick?: (event: MouseEvent & InputTarget) => void
53
53
  children?: Snippet
54
54
  } & InputProps
@@ -56,7 +56,7 @@ export type SvelteInputProps = {
56
56
  export type ReactInputProps = {
57
57
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
58
58
  onKeyUp?: (event: React.KeyboardEvent<HTMLInputElement>) => void
59
- onInput?: (event: React.FormEvent<HTMLInputElement>) => void
59
+ onInput?: (event: React.InputEvent<HTMLInputElement>) => void
60
60
  onClick?: (event: React.MouseEvent<HTMLInputElement>) => void
61
61
  children?: React.ReactNode
62
62
  } & InputProps
@@ -19,17 +19,20 @@ const {
19
19
  id,
20
20
  className,
21
21
  wrapperClassName,
22
+ secondary,
22
23
  itemGroups
23
24
  } = Astro.props
24
25
 
25
26
  const classes = [
26
27
  styles.list,
28
+ (secondary && !showSearchBar) && styles.secondary,
27
29
  !showSearchBar && styles.container,
28
30
  className
29
31
  ]
30
32
 
31
33
  const wrapperClasses = [
32
34
  styles.container,
35
+ secondary && styles.secondary,
33
36
  wrapperClassName
34
37
  ]
35
38
  ---
@@ -19,6 +19,7 @@
19
19
  id,
20
20
  className,
21
21
  wrapperClassName,
22
+ secondary,
22
23
  itemGroups = $bindable([]),
23
24
  onSelect
24
25
  }: SvelteListProps = $props()
@@ -28,12 +29,14 @@
28
29
 
29
30
  const classes = classNames([
30
31
  styles.list,
32
+ (secondary && !showSearchBar) && styles.secondary,
31
33
  !showSearchBar && styles.container,
32
34
  className
33
35
  ])
34
36
 
35
37
  const wrapperClasses = classNames([
36
38
  styles.container,
39
+ secondary && styles.secondary,
37
40
  wrapperClassName
38
41
  ])
39
42
 
@@ -81,15 +84,15 @@
81
84
  class={wrapperClasses}
82
85
  >
83
86
  {#if showSearchBar}
84
- <Input
85
- type="search"
86
- placeholder={searchBarPlaceholder}
87
- onInput={search}
88
- >
89
- {#if showSearchBarIcon}
90
- {@html searchIcon}
91
- {/if}
92
- </Input>
87
+ {#if showSearchBarIcon}
88
+ <Input type="search" placeholder={searchBarPlaceholder} onInput={search}>
89
+ {#if showSearchBarIcon}
90
+ {@html searchIcon}
91
+ {/if}
92
+ </Input>
93
+ {:else}
94
+ <Input type="search" placeholder={searchBarPlaceholder} onInput={search} />
95
+ {/if}
93
96
  {/if}
94
97
  <ul
95
98
  class={classes}
@@ -19,6 +19,7 @@ const List = ({
19
19
  id,
20
20
  className,
21
21
  wrapperClassName,
22
+ secondary,
22
23
  itemGroups,
23
24
  onSelect
24
25
  }: ReactListProps) => {
@@ -28,12 +29,14 @@ const List = ({
28
29
 
29
30
  const classes = classNames([
30
31
  styles.list,
32
+ (secondary && !showSearchBar) && styles.secondary,
31
33
  !showSearchBar && styles.container,
32
34
  className
33
35
  ])
34
36
 
35
37
  const wrapperClasses = classNames([
36
38
  styles.container,
39
+ secondary && styles.secondary,
37
40
  wrapperClassName
38
41
  ])
39
42
 
@@ -85,6 +85,11 @@
85
85
  .container {
86
86
  @include border-radius(md);
87
87
  @include border(primary-50);
88
+ @include background(primary-70);
89
+
90
+ &.secondary {
91
+ @include background(primary-60);
92
+ }
88
93
 
89
94
  input {
90
95
  @include border(top, 0);
@@ -1,39 +1,40 @@
1
- import type { ButtonProps } from '../Button/button'
2
-
3
- export type ListEventType = {
4
- value: string
5
- name: string
6
- list: HTMLUListElement
7
- }
8
-
9
- export type ListProps = {
10
- showSearchBar?: boolean
11
- showSearchBarIcon?: boolean
12
- searchBarPlaceholder?: string
13
- noResultsLabel?: string
14
- maxHeight?: string
15
- id?: string
16
- className?: string
17
- wrapperClassName?: string
18
- itemGroups: {
19
- title?: string
20
- items: {
21
- name: string
22
- value?: string
23
- href?: string
24
- target?: ButtonProps['target']
25
- selected?: boolean
26
- disabled?: boolean
27
- icon?: string
28
- subText?: string
29
- }[]
30
- }[]
31
- }
32
-
33
- export type SvelteListProps = {
34
- onSelect?: (event: ListEventType) => void
35
- } & ListProps
36
-
37
- export type ReactListProps = {
38
- onSelect?: (event: ListEventType) => void
39
- } & ListProps
1
+ import type { ButtonProps } from '../Button/button'
2
+
3
+ export type ListEventType = {
4
+ value: string
5
+ name: string
6
+ list: HTMLUListElement
7
+ }
8
+
9
+ export type ListProps = {
10
+ showSearchBar?: boolean
11
+ showSearchBarIcon?: boolean
12
+ searchBarPlaceholder?: string
13
+ noResultsLabel?: string
14
+ maxHeight?: string
15
+ id?: string
16
+ className?: string
17
+ wrapperClassName?: string
18
+ secondary?: boolean
19
+ itemGroups: {
20
+ title?: string
21
+ items: {
22
+ name: string
23
+ value?: string
24
+ href?: string
25
+ target?: ButtonProps['target']
26
+ selected?: boolean
27
+ disabled?: boolean
28
+ icon?: string
29
+ subText?: string
30
+ }[]
31
+ }[]
32
+ }
33
+
34
+ export type SvelteListProps = {
35
+ onSelect?: (event: ListEventType) => void
36
+ } & ListProps
37
+
38
+ export type ReactListProps = {
39
+ onSelect?: (event: ListEventType) => void
40
+ } & ListProps
@@ -7,7 +7,6 @@ import { classNames } from '../../utils/classNames'
7
7
 
8
8
  import styles from './menu.module.scss'
9
9
 
10
- // eslint-disable-next-line complexity
11
10
  const Menu = ({
12
11
  items,
13
12
  logo,
@@ -15,6 +14,7 @@ const Menu = ({
15
14
  className,
16
15
  wrapperClassName,
17
16
  children
17
+ // eslint-disable-next-line complexity
18
18
  }: ReactMenuProps) => {
19
19
  const [active, setActive] = useState(false)
20
20
 
@@ -10,7 +10,6 @@ import ChevronRight from '../../icons/chevron-right.svg?raw'
10
10
 
11
11
  import styles from './pagination.module.scss'
12
12
 
13
- // eslint-disable-next-line complexity
14
13
  const Pagination = ({
15
14
  type,
16
15
  showChevrons,
@@ -27,6 +26,7 @@ const Pagination = ({
27
26
  currentPage,
28
27
  onChange,
29
28
  className
29
+ // eslint-disable-next-line complexity
30
30
  }: ReactPaginationProps) => {
31
31
  const [calculatedCurrentPage, setCalculatedCurrentPage] = useState(
32
32
  currentPage
@@ -5,6 +5,7 @@
5
5
  @include spacing(0);
6
6
 
7
7
  list-style-type: none;
8
+ user-select: none;
8
9
 
9
10
  &.primary [data-active="true"] {
10
11
  @include typography(primary-70);
@@ -1,26 +1,28 @@
1
- ---
2
- import type { PopoverProps } from './popover'
3
-
4
- import styles from './popover.module.scss'
5
-
6
- interface Props extends PopoverProps {}
7
-
8
- const {
9
- id,
10
- className,
11
- ...rest
12
- } = Astro.props
13
-
14
- const classes = [
15
- styles.popover,
16
- className
17
- ]
18
- ---
19
-
20
- <dialog
21
- class:list={classes}
22
- id={id}
23
- {...rest}
24
- >
25
- <slot />
26
- </dialog>
1
+ ---
2
+ import type { PopoverProps } from './popover'
3
+
4
+ import styles from './popover.module.scss'
5
+
6
+ interface Props extends PopoverProps {}
7
+
8
+ const {
9
+ id,
10
+ className,
11
+ transparent,
12
+ ...rest
13
+ } = Astro.props
14
+
15
+ const classes = [
16
+ styles.popover,
17
+ transparent && styles.transparent,
18
+ className
19
+ ]
20
+ ---
21
+
22
+ <dialog
23
+ class:list={classes}
24
+ id={id}
25
+ {...rest}
26
+ >
27
+ <slot />
28
+ </dialog>
@@ -8,12 +8,14 @@
8
8
  const {
9
9
  id,
10
10
  className,
11
+ transparent,
11
12
  children,
12
13
  ...rest
13
14
  }: SveltePopoverProps = $props()
14
15
 
15
16
  const classes = classNames([
16
17
  styles.popover,
18
+ transparent && styles.transparent,
17
19
  className
18
20
  ])
19
21
  </script>