webcoreui 0.10.1 → 1.1.0-beta.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 (46) hide show
  1. package/README.md +15 -8
  2. package/astro.d.ts +6 -0
  3. package/astro.js +4 -0
  4. package/components/Carousel/Carousel.svelte +18 -15
  5. package/components/OTPInput/OTPInput.astro +96 -0
  6. package/components/OTPInput/OTPInput.svelte +73 -0
  7. package/components/OTPInput/OTPInput.tsx +93 -0
  8. package/components/OTPInput/otpinput.module.scss +85 -0
  9. package/components/OTPInput/otpinput.ts +11 -0
  10. package/components/Pagination/Pagination.svelte +1 -1
  11. package/components/Rating/Rating.svelte +1 -1
  12. package/components/SpeedDial/SpeedDial.astro +106 -0
  13. package/components/SpeedDial/SpeedDial.svelte +102 -0
  14. package/components/SpeedDial/SpeedDial.tsx +106 -0
  15. package/components/SpeedDial/speeddial.module.scss +94 -0
  16. package/components/SpeedDial/speeddial.ts +18 -0
  17. package/components/Switch/Switch.astro +1 -1
  18. package/components/Switch/Switch.svelte +1 -1
  19. package/components/Switch/Switch.tsx +6 -1
  20. package/components/Timeline/timeline.module.scss +11 -0
  21. package/components/Timeline/timeline.ts +1 -1
  22. package/components/TimelineItem/TimelineItem.astro +12 -0
  23. package/components/TimelineItem/TimelineItem.svelte +7 -0
  24. package/components/TimelineItem/TimelineItem.tsx +8 -0
  25. package/components/TimelineItem/timelineitem.module.scss +16 -1
  26. package/components/TimelineItem/timelineitem.ts +3 -0
  27. package/index.d.ts +3 -0
  28. package/index.js +2 -1
  29. package/package.json +17 -17
  30. package/react.d.ts +6 -0
  31. package/react.js +4 -0
  32. package/scss/config/color-palette.scss +1 -1
  33. package/scss/config/css-values.scss +1 -1
  34. package/scss/config/layout.scss +1 -1
  35. package/scss/config/mixins.scss +1 -1
  36. package/scss/config/typography.scss +1 -1
  37. package/scss/config/variables.scss +1 -1
  38. package/scss/config.scss +1 -1
  39. package/scss/global/theme.scss +77 -49
  40. package/scss/resets.scss +10 -1
  41. package/svelte.d.ts +6 -0
  42. package/svelte.js +4 -0
  43. package/utils/getLayoutClasses.ts +1 -1
  44. package/utils/modal.ts +1 -1
  45. package/utils/popover.ts +2 -2
  46. package/utils/webcore.ts +28 -0
@@ -0,0 +1,106 @@
1
+ ---
2
+ import type { SpeedDialProps } from './speeddial'
3
+
4
+ import Button from '../Button/Button.astro'
5
+ import Icon from '../Icon/Icon.astro'
6
+
7
+ import styles from './speeddial.module.scss'
8
+
9
+ interface Props extends SpeedDialProps {}
10
+
11
+ const {
12
+ items,
13
+ position,
14
+ horizontal,
15
+ circular,
16
+ theme,
17
+ icon,
18
+ triggerOnClick,
19
+ className
20
+ } = Astro.props
21
+
22
+ const classes = [
23
+ styles.dial,
24
+ position && styles[position],
25
+ horizontal && styles.horizontal,
26
+ circular && styles.circular,
27
+ className
28
+ ]
29
+
30
+ const getTooltipPosition = () => {
31
+ const positionMap = {
32
+ 'top-left': 'right',
33
+ 'bottom-left': 'right',
34
+ 'horizontal': {
35
+ 'top-left': 'bottom',
36
+ 'top-right': 'bottom'
37
+ }
38
+ }
39
+
40
+ return horizontal
41
+ ? positionMap.horizontal[position as keyof typeof positionMap.horizontal]
42
+ : positionMap[position as keyof typeof positionMap] || 'left'
43
+ }
44
+ ---
45
+
46
+ {!!items?.length && (
47
+ <div class:list={classes} data-id={triggerOnClick ? 'w-speed-dial' : null}>
48
+ <Button className={styles.trigger} {...(theme && { theme })}>
49
+ {icon && (
50
+ <Fragment>
51
+ {icon.startsWith('<svg')
52
+ ? <Fragment set:html={icon} />
53
+ : <Icon type={icon} size={18} />
54
+ }
55
+ </Fragment>
56
+ )}
57
+ {!icon && <span>+</span>}
58
+ </Button>
59
+
60
+ <ul class={styles.list}>
61
+ {items.map(item => (
62
+ <li>
63
+ <Button
64
+ data-tooltip={item.tooltip}
65
+ data-position={getTooltipPosition()}
66
+ href={item.href}
67
+ target={item.target}
68
+ className={styles.button}
69
+ {...(theme && { theme })}
70
+ >
71
+ {item.icon.startsWith('<svg')
72
+ ? <Fragment set:html={item.icon} />
73
+ : <Icon type={item.icon} size={16} />
74
+ }
75
+ </Button>
76
+ </li>
77
+ ))}
78
+ </ul>
79
+ </div>
80
+ )}
81
+
82
+ <script>
83
+ import { get, on } from '../../utils/DOMUtils'
84
+
85
+ const addEventListeners = () => {
86
+ const speedDial = get('[data-id="w-speed-dial"] button') as HTMLButtonElement
87
+ const speedDialContainer = speedDial?.parentElement as HTMLDivElement
88
+
89
+ if (speedDial) {
90
+ on(speedDial, 'click', () => {
91
+ speedDialContainer.dataset.show = speedDialContainer.dataset.show === 'true'
92
+ ? 'false'
93
+ : 'true'
94
+ })
95
+
96
+ on(document, 'click', (event: Event) => {
97
+ if (!speedDial.contains((event.target || event.currentTarget) as HTMLElement)) {
98
+ speedDialContainer.dataset.show = 'false'
99
+ }
100
+ })
101
+ }
102
+ }
103
+
104
+ on(document, 'astro:after-swap', addEventListeners)
105
+ addEventListeners()
106
+ </script>
@@ -0,0 +1,102 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte'
3
+ import type { SpeedDialProps } from './speeddial'
4
+
5
+ import Button from '../Button/Button.svelte'
6
+
7
+ import { classNames } from '../../utils/classNames'
8
+ import { get, on } from '../../utils/DOMUtils'
9
+
10
+ import styles from './speeddial.module.scss'
11
+
12
+ const {
13
+ items,
14
+ position,
15
+ horizontal,
16
+ circular,
17
+ theme,
18
+ icon,
19
+ triggerOnClick,
20
+ className
21
+ }: SpeedDialProps = $props()
22
+
23
+ let show = $state(false)
24
+
25
+ const classes = classNames([
26
+ styles.dial,
27
+ position && styles[position],
28
+ horizontal && styles.horizontal,
29
+ circular && styles.circular,
30
+ className
31
+ ])
32
+
33
+ const getTooltipPosition = () => {
34
+ const positionMap = {
35
+ 'top-left': 'right',
36
+ 'bottom-left': 'right',
37
+ 'horizontal': {
38
+ 'top-left': 'bottom',
39
+ 'top-right': 'bottom'
40
+ }
41
+ }
42
+
43
+ return horizontal
44
+ ? positionMap.horizontal[position as keyof typeof positionMap.horizontal]
45
+ : positionMap[position as keyof typeof positionMap] || 'left'
46
+ }
47
+
48
+ const toggle = () => show = !show
49
+
50
+ onMount(() => {
51
+ const speedDial = get('[data-id="w-speed-dial"] button') as HTMLButtonElement
52
+
53
+ const eventListener = (event: Event) => {
54
+ if (!speedDial.contains((event.target || event.currentTarget) as HTMLElement)) {
55
+ show = false
56
+ }
57
+ }
58
+
59
+ on(document, 'click', eventListener)
60
+
61
+ return () => {
62
+ document.removeEventListener('click', eventListener)
63
+ }
64
+ })
65
+ </script>
66
+
67
+ {#if items?.length}
68
+ <div
69
+ class={classes}
70
+ data-id={triggerOnClick ? 'w-speed-dial' : null}
71
+ data-show={triggerOnClick ? show : null}
72
+ >
73
+ <Button
74
+ className={styles.trigger}
75
+ onClick={triggerOnClick ? toggle : undefined}
76
+ {...(theme && { theme })}
77
+ >
78
+ {#if icon}
79
+ {@html icon}
80
+ {:else}
81
+ <span>+</span>
82
+ {/if}
83
+ </Button>
84
+
85
+ <ul class={styles.list}>
86
+ {#each items as item}
87
+ <li>
88
+ <Button
89
+ data-tooltip={item.tooltip}
90
+ data-position={getTooltipPosition()}
91
+ {...(theme && { theme })}
92
+ href={item.href}
93
+ target={item.target}
94
+ className={styles.button}
95
+ >
96
+ {@html item.icon}
97
+ </Button>
98
+ </li>
99
+ {/each}
100
+ </ul>
101
+ </div>
102
+ {/if}
@@ -0,0 +1,106 @@
1
+ import React, { useEffect, useState } from 'react'
2
+ import type { SpeedDialProps } from './speeddial'
3
+
4
+ import Button from '../Button/Button.tsx'
5
+
6
+ import { classNames } from '../../utils/classNames'
7
+ import { get, on } from '../../utils/DOMUtils'
8
+
9
+ import styles from './speeddial.module.scss'
10
+
11
+ const SpeedDial = ({
12
+ items,
13
+ position,
14
+ horizontal,
15
+ circular,
16
+ theme,
17
+ icon,
18
+ triggerOnClick,
19
+ className
20
+ }: SpeedDialProps) => {
21
+ const [show, setShow] = useState(false)
22
+
23
+ const classes = classNames([
24
+ styles.dial,
25
+ position && styles[position],
26
+ horizontal && styles.horizontal,
27
+ circular && styles.circular,
28
+ className
29
+ ])
30
+
31
+ const getTooltipPosition = () => {
32
+ const positionMap = {
33
+ 'top-left': 'right',
34
+ 'bottom-left': 'right',
35
+ 'horizontal': {
36
+ 'top-left': 'bottom',
37
+ 'top-right': 'bottom'
38
+ }
39
+ }
40
+
41
+ return horizontal
42
+ ? positionMap.horizontal[position as keyof typeof positionMap.horizontal]
43
+ : positionMap[position as keyof typeof positionMap] || 'left'
44
+ }
45
+
46
+ const toggle = () => {
47
+ setShow(!show)
48
+ }
49
+
50
+ useEffect(() => {
51
+ const speedDial = get('[data-id="w-speed-dial"] button') as HTMLButtonElement
52
+
53
+ const eventListener = (event: Event) => {
54
+ if (!speedDial.contains((event.target || event.currentTarget) as HTMLElement)) {
55
+ setShow(false)
56
+ }
57
+ }
58
+
59
+ on(document, 'click', eventListener)
60
+
61
+ return () => {
62
+ document.removeEventListener('click', eventListener)
63
+ }
64
+ }, [])
65
+
66
+ if (!items?.length) {
67
+ return null
68
+ }
69
+
70
+ return (
71
+ <div
72
+ className={classes}
73
+ data-id={triggerOnClick ? 'w-speed-dial' : null}
74
+ data-show={triggerOnClick ? show : null}
75
+ >
76
+ <Button
77
+ className={styles.trigger}
78
+ onClick={triggerOnClick ? toggle : undefined}
79
+ {...(theme && { theme })}
80
+ >
81
+ {icon && (
82
+ <span dangerouslySetInnerHTML={{ __html: icon }} />
83
+ )}
84
+ {!icon && <span>+</span>}
85
+ </Button>
86
+
87
+ <ul className={styles.list}>
88
+ {items.map((item, index) => (
89
+ <li key={index}>
90
+ <Button
91
+ data-tooltip={item.tooltip}
92
+ data-position={getTooltipPosition()}
93
+ href={item.href}
94
+ target={item.target}
95
+ className={styles.button}
96
+ dangerouslySetInnerHTML={{ __html: item.icon }}
97
+ {...(theme && { theme })}
98
+ />
99
+ </li>
100
+ ))}
101
+ </ul>
102
+ </div>
103
+ )
104
+ }
105
+
106
+ export default SpeedDial
@@ -0,0 +1,94 @@
1
+ @use '../../scss/config.scss' as *;
2
+
3
+ body {
4
+ --w-speed-dial-size: 40px;
5
+ }
6
+
7
+ .dial {
8
+ @include layout(flex, column-reverse, center, xs);
9
+ @include position(fixed, b20px, r20px);
10
+
11
+ width: fit-content;
12
+
13
+ &.top-left,
14
+ &.top-right {
15
+ @include position(t20px, bauto);
16
+ @include layout(column);
17
+ }
18
+
19
+ &.top-left,
20
+ &.bottom-left {
21
+ @include position(l20px, rauto);
22
+
23
+ &.horizontal {
24
+ @include layout(row);
25
+ }
26
+ }
27
+
28
+ &.circular {
29
+ .trigger,
30
+ .button {
31
+ @include border-radius(max);
32
+ }
33
+ }
34
+
35
+ &.horizontal {
36
+ @include layout(row-reverse, v-stretch);
37
+
38
+ .list {
39
+ @include layout(row, v-stretch);
40
+ }
41
+ }
42
+
43
+ &:not([data-id]):hover .list,
44
+ &[data-show="true"] .list {
45
+ @include layout(flex);
46
+ }
47
+
48
+ &:not([data-id]):hover .trigger span,
49
+ &[data-show="true"] .trigger span {
50
+ transform: rotate(45deg) translate(1px);
51
+ }
52
+ }
53
+
54
+ .trigger {
55
+ @include layout(flex, column);
56
+ @include typography(bold);
57
+ @include size(var(--w-speed-dial-size));
58
+
59
+ user-select: none;
60
+
61
+ span {
62
+ @include transition(transform);
63
+ }
64
+
65
+ svg {
66
+ @include size(18px);
67
+ }
68
+ }
69
+
70
+ .list {
71
+ @include spacing(0);
72
+ @include layout(flex, column, center, xs);
73
+ @include visibility(none);
74
+
75
+ list-style-type: none;
76
+
77
+ &:hover {
78
+ @include layout(flex);
79
+ }
80
+
81
+ li {
82
+ @include spacing(0);
83
+ @include size('w100%');
84
+ }
85
+
86
+ .button {
87
+ @include layout(flex, column, xs);
88
+ @include size(var(--w-speed-dial-size));
89
+
90
+ svg {
91
+ @include size(16px);
92
+ }
93
+ }
94
+ }
@@ -0,0 +1,18 @@
1
+ import type { ButtonProps } from '../Button/button'
2
+ import type { IconProps } from '../Icon/icon'
3
+
4
+ export type SpeedDialProps = {
5
+ items: {
6
+ icon: IconProps['type'] | string
7
+ href: string
8
+ tooltip?: string
9
+ target?: ButtonProps['target']
10
+ }[]
11
+ position?: 'top-left' | 'top-right' | 'bottom-left'
12
+ horizontal?: boolean
13
+ circular?: boolean
14
+ theme?: ButtonProps['theme']
15
+ icon?: IconProps['type'] | string
16
+ triggerOnClick?: boolean
17
+ className?: string
18
+ }
@@ -38,5 +38,5 @@ const styleVariables = classNames([
38
38
  <label class:list={classes} style={styleVariables}>
39
39
  <input type="checkbox" checked={toggled} disabled={disabled} {...rest} />
40
40
  <span class={styles.toggle}></span>
41
- {label && <span class={styles.label}>{label}</span>}
41
+ {label && <span class={styles.label} set:html={label} />}
42
42
  </label>
@@ -44,6 +44,6 @@
44
44
  />
45
45
  <span class={styles.toggle}></span>
46
46
  {#if label}
47
- <span class={styles.label}>{label}</span>
47
+ <span class={styles.label}>{@html label}</span>
48
48
  {/if}
49
49
  </label>
@@ -42,7 +42,12 @@ const Switch = ({
42
42
  {...rest}
43
43
  />
44
44
  <span className={styles.toggle}></span>
45
- {label && <span className={styles.label}>{label}</span>}
45
+ {label && (
46
+ <span
47
+ className={styles.label}
48
+ dangerouslySetInnerHTML={{ __html: label }}
49
+ />
50
+ )}
46
51
  </label>
47
52
  )
48
53
  }
@@ -67,6 +67,17 @@ body {
67
67
  right: $rightOffset;
68
68
  }
69
69
  }
70
+
71
+ &.icons > li {
72
+ &:nth-child(even) > span:first-child {
73
+ left: 25px;
74
+ }
75
+
76
+ &:nth-child(odd) > span:first-child {
77
+ right: -15px;
78
+ }
79
+ }
80
+
70
81
  }
71
82
 
72
83
  &.centered > li:nth-child(odd) {
@@ -1,7 +1,7 @@
1
1
  import type { Snippet } from 'svelte'
2
2
 
3
3
  export type TimelineProps = {
4
- theme?: 'fill' | 'stroke' | 'stroke fill'
4
+ theme?: 'fill' | 'stroke' | 'stroke fill' | 'icons'
5
5
  alternate?: boolean
6
6
  centered?: boolean
7
7
  color?: string
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  import type { TimelineItemProps } from './timelineitem'
3
3
 
4
+ import Icon from '../Icon/Icon.astro'
5
+
4
6
  import styles from './timelineitem.module.scss'
5
7
 
6
8
  interface Props extends TimelineItemProps {}
@@ -8,11 +10,13 @@ interface Props extends TimelineItemProps {}
8
10
  const {
9
11
  title,
10
12
  titleTag = 'span',
13
+ icon,
11
14
  className
12
15
  } = Astro.props
13
16
 
14
17
  const classes = [
15
18
  styles.item,
19
+ icon && styles['with-icon'],
16
20
  className
17
21
  ]
18
22
 
@@ -20,6 +24,14 @@ const Title = titleTag
20
24
  ---
21
25
 
22
26
  <li class:list={classes}>
27
+ {icon && (
28
+ <span class={styles.icon}>
29
+ {icon.startsWith('<svg')
30
+ ? <Fragment set:html={icon} />
31
+ : <Icon type={icon} size={18} />
32
+ }
33
+ </span>
34
+ )}
23
35
  {title && (
24
36
  <Title class:list={styles.title}>{title}</Title>
25
37
  )}
@@ -8,17 +8,24 @@
8
8
  const {
9
9
  title,
10
10
  titleTag = 'span',
11
+ icon,
11
12
  className,
12
13
  children
13
14
  }: SvelteTimelineItemProps = $props()
14
15
 
15
16
  const classes = classNames([
16
17
  styles.item,
18
+ icon && styles['with-icon'],
17
19
  className
18
20
  ])
19
21
  </script>
20
22
 
21
23
  <li class={classes}>
24
+ {#if icon}
25
+ <span class={styles.icon}>
26
+ {@html icon}
27
+ </span>
28
+ {/if}
22
29
  {#if title}
23
30
  <svelte:element this={titleTag} class={styles.title}>
24
31
  {title}
@@ -8,16 +8,24 @@ import styles from './timelineitem.module.scss'
8
8
  const TimelineItem = ({
9
9
  title,
10
10
  TitleTag = 'span',
11
+ icon,
11
12
  className,
12
13
  children
13
14
  }: ReactTimelineItemProps) => {
14
15
  const classes = classNames([
15
16
  styles.item,
17
+ icon && styles['with-icon'],
16
18
  className
17
19
  ])
18
20
 
19
21
  return (
20
22
  <li className={classes}>
23
+ {icon && (
24
+ <span
25
+ className={styles.icon}
26
+ dangerouslySetInnerHTML={{ __html: icon }}
27
+ />
28
+ )}
21
29
  {title && (
22
30
  <TitleTag className={styles.title}>{title}</TitleTag>
23
31
  )}
@@ -4,7 +4,7 @@
4
4
  @include position(relative);
5
5
  @include spacing(m0);
6
6
 
7
- &::before {
7
+ &:not(.with-icon)::before {
8
8
  @include position(absolute, t-5px);
9
9
  @include size(25px);
10
10
  @include border-radius(max);
@@ -19,6 +19,21 @@
19
19
  margin-left: -40px;
20
20
  }
21
21
 
22
+ .icon {
23
+ @include position(absolute);
24
+ @include background(primary-70);
25
+ @include border(6px, primary-70);
26
+ @include layout(flex);
27
+
28
+ color: var(--w-timeline-text-color);
29
+ margin-left: -40px;
30
+ margin-top: -4px;
31
+
32
+ svg {
33
+ @include size(18px);
34
+ }
35
+ }
36
+
22
37
  .title {
23
38
  @include typography(bold, lg);
24
39
  @include spacing(mb-sm);
@@ -1,8 +1,11 @@
1
1
  import type { Snippet } from 'svelte'
2
2
 
3
+ import type { IconProps } from '../Icon/icon'
4
+
3
5
  export type TimelineItemProps = {
4
6
  title?: string
5
7
  titleTag?: string
8
+ icon?: IconProps['type'] | string
6
9
  className?: string
7
10
  }
8
11
 
package/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
 
2
+ import type { AstroIntegration } from 'astro'
3
+
2
4
  export type Gap = 'none'
3
5
  | 'xxs'
4
6
  | 'xs'
@@ -177,4 +179,5 @@ declare module 'webcoreui' {
177
179
  export const setDefaultTimeout: (time: number) => number
178
180
  export const toast: (config: Toast | string) => void
179
181
  export const hideToast: (element: string) => void
182
+ export const webcore: () => AstroIntegration
180
183
  }
package/index.js CHANGED
@@ -8,4 +8,5 @@ export * from './utils/getLayoutClasses.ts'
8
8
  export * from './utils/interpolate.ts'
9
9
  export * from './utils/modal.ts'
10
10
  export * from './utils/popover.ts'
11
- export * from './utils/toast.ts'
11
+ export * from './utils/toast.ts'
12
+ export * from './utils/webcore.ts'