webcoreui 0.6.1 → 0.7.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 +30 -1
  2. package/astro.d.ts +15 -0
  3. package/astro.js +10 -0
  4. package/components/Accordion/Accordion.astro +32 -20
  5. package/components/Accordion/Accordion.svelte +22 -4
  6. package/components/Accordion/Accordion.tsx +29 -7
  7. package/components/Accordion/accordion.module.scss +12 -0
  8. package/components/Accordion/accordion.ts +4 -0
  9. package/components/AspectRatio/AspectRatio.astro +21 -0
  10. package/components/AspectRatio/AspectRatio.svelte +19 -0
  11. package/components/AspectRatio/AspectRatio.tsx +28 -0
  12. package/components/AspectRatio/aspect-ratio.module.scss +10 -0
  13. package/components/AspectRatio/aspectratio.ts +8 -0
  14. package/components/Banner/Banner.astro +56 -0
  15. package/components/Banner/Banner.svelte +47 -0
  16. package/components/Banner/Banner.tsx +54 -0
  17. package/components/Banner/banner.module.scss +57 -0
  18. package/components/Banner/banner.ts +12 -0
  19. package/components/Icon/map.ts +2 -0
  20. package/components/Kbd/Kbd.astro +20 -0
  21. package/components/Kbd/Kbd.svelte +18 -0
  22. package/components/Kbd/Kbd.tsx +27 -0
  23. package/components/Kbd/kbd.module.scss +8 -0
  24. package/components/Kbd/kbd.ts +26 -0
  25. package/components/Kbd/keyMap.ts +21 -0
  26. package/components/Spoiler/Spoiler.astro +50 -0
  27. package/components/Spoiler/Spoiler.svelte +45 -0
  28. package/components/Spoiler/Spoiler.tsx +50 -0
  29. package/components/Spoiler/spoiler.module.scss +40 -0
  30. package/components/Spoiler/spoiler.ts +11 -0
  31. package/components/Stepper/Stepper.astro +61 -0
  32. package/components/Stepper/Stepper.svelte +59 -0
  33. package/components/Stepper/Stepper.tsx +60 -0
  34. package/components/Stepper/stepper.module.scss +102 -0
  35. package/components/Stepper/stepper.ts +17 -0
  36. package/icons/close.svg +1 -1
  37. package/icons/plus.svg +3 -0
  38. package/icons.d.ts +1 -0
  39. package/icons.js +1 -0
  40. package/package.json +4 -4
  41. package/react.d.ts +15 -0
  42. package/react.js +10 -0
  43. package/scss/global/utility.scss +4 -0
  44. package/scss/resets.scss +5 -0
  45. package/svelte.d.ts +15 -0
  46. package/svelte.js +10 -0
@@ -0,0 +1,54 @@
1
+ import React, { useState } from 'react'
2
+ import type { ReactBannerProps } from './banner'
3
+
4
+ import Button from '../Button/Button.tsx'
5
+
6
+ import { classNames } from '../../utils/classNames'
7
+
8
+ import closeIcon from '../../icons/close.svg?raw'
9
+
10
+ import styles from './banner.module.scss'
11
+
12
+ const Banner = ({
13
+ top,
14
+ bottom,
15
+ closeable,
16
+ padded,
17
+ sticky = true,
18
+ className,
19
+ children
20
+ }: ReactBannerProps) => {
21
+ const [visible, setVisible] = useState(true)
22
+
23
+ const classes = classNames([
24
+ styles.banner,
25
+ bottom && styles.bottom,
26
+ padded && styles.padded,
27
+ !sticky && styles.relative,
28
+ className
29
+ ])
30
+
31
+ const style = top
32
+ ? { '--w-banner-top': `${top}px` } as React.CSSProperties
33
+ : undefined
34
+
35
+ if (!visible) {
36
+ return null
37
+ }
38
+
39
+ return (
40
+ <div className={classes} style={style}>
41
+ {children}
42
+ {closeable && (
43
+ <Button
44
+ theme="flat"
45
+ className={styles.close}
46
+ dangerouslySetInnerHTML={{ __html: closeIcon }}
47
+ onClick={() => setVisible(false)}
48
+ />
49
+ )}
50
+ </div>
51
+ )
52
+ }
53
+
54
+ export default Banner
@@ -0,0 +1,57 @@
1
+ @import '../../scss/config.scss';
2
+
3
+ body {
4
+ --w-banner-top: 0;
5
+ }
6
+
7
+ .banner {
8
+ @include background(primary-60);
9
+ @include spacing(p-default);
10
+ @include position(sticky);
11
+ @include layer(top);
12
+ @include typography(center);
13
+
14
+ top: var(--w-banner-top);
15
+
16
+ &.padded {
17
+ @include border-radius();
18
+ @include position(l20px);
19
+
20
+ width: calc(100% - 40px);
21
+ top: calc(var(--w-banner-top) + 20px);
22
+
23
+ &.bottom {
24
+ @include position(l20px, b20px);
25
+ }
26
+ }
27
+
28
+ &.relative {
29
+ @include position(relative);
30
+ top: auto;
31
+ }
32
+
33
+ &.bottom {
34
+ @include position(fixed, b0, l0, r0);
35
+
36
+ top: auto;
37
+ }
38
+
39
+ &.closeable {
40
+ @include spacing(pl-default, pt-default, pb-default, pr-3xl);
41
+ }
42
+
43
+ .close {
44
+ @include position(absolute, v-center, r10px);
45
+ @include spacing(p-xs);
46
+
47
+ svg {
48
+ @include size(10px);
49
+ }
50
+ }
51
+ }
52
+
53
+ @include media(xs) {
54
+ .banner.closeable {
55
+ @include spacing(p-default);
56
+ }
57
+ }
@@ -0,0 +1,12 @@
1
+ export type BannerProps = {
2
+ top?: number
3
+ bottom?: boolean
4
+ closeable?: boolean
5
+ padded?: boolean
6
+ sticky?: boolean
7
+ className?: string
8
+ }
9
+
10
+ export type ReactBannerProps = {
11
+ children: React.ReactNode
12
+ } & BannerProps
@@ -13,6 +13,7 @@ import Home from '../../icons/home.svg?raw'
13
13
  import Info from '../../icons/info.svg?raw'
14
14
  import Moon from '../../icons/moon.svg?raw'
15
15
  import Order from '../../icons/order.svg?raw'
16
+ import Plus from '../../icons/plus.svg?raw'
16
17
  import Search from '../../icons/search.svg?raw'
17
18
  import Sun from '../../icons/sun.svg?raw'
18
19
  import Warning from '../../icons/warning.svg?raw'
@@ -33,6 +34,7 @@ const iconMap = {
33
34
  'info': Info,
34
35
  'moon': Moon,
35
36
  'order': Order,
37
+ 'plus': Plus,
36
38
  'search': Search,
37
39
  'sun': Sun,
38
40
  'warning': Warning
@@ -0,0 +1,20 @@
1
+ ---
2
+ import type { KbdProps } from './kbd'
3
+ import { keyMap } from './keyMap'
4
+
5
+ import styles from './kbd.module.scss'
6
+
7
+ interface Props extends KbdProps {}
8
+
9
+ const {
10
+ keys,
11
+ className
12
+ } = Astro.props
13
+
14
+ const classes = [
15
+ styles.kbd,
16
+ className
17
+ ]
18
+ ---
19
+
20
+ <kbd class:list={classes}>{keys?.map(key => keyMap[key])}<slot /></kbd>
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ import type { KbdProps } from './kbd'
3
+ import { keyMap } from './keyMap'
4
+
5
+ import { classNames } from '../../utils/classNames'
6
+
7
+ import styles from './kbd.module.scss'
8
+
9
+ export let keys: KbdProps['keys'] = []
10
+ export let className: KbdProps['className'] = ''
11
+
12
+ const classes = classNames([
13
+ styles.kbd,
14
+ className
15
+ ])
16
+ </script>
17
+
18
+ <kbd class={classes}>{keys?.map(key => keyMap[key]).join('')}<slot /></kbd>
@@ -0,0 +1,27 @@
1
+ import React from 'react'
2
+ import type { ReactKbdProps } from './kbd'
3
+ import { keyMap } from './keyMap'
4
+
5
+ import { classNames } from '../../utils/classNames'
6
+
7
+ import styles from './kbd.module.scss'
8
+
9
+ const Kbd = ({
10
+ keys,
11
+ className,
12
+ children
13
+ }: ReactKbdProps) => {
14
+ const classes = classNames([
15
+ styles.kbd,
16
+ className
17
+ ])
18
+
19
+ return (
20
+ <kbd className={classes}>
21
+ {keys?.map(key => keyMap[key]).join('')}
22
+ {children}
23
+ </kbd>
24
+ )
25
+ }
26
+
27
+ export default Kbd
@@ -0,0 +1,8 @@
1
+ @import '../../scss/config.scss';
2
+
3
+ .kbd {
4
+ @include background(primary-50);
5
+ @include border-radius(md);
6
+ @include typography(md, regular);
7
+ @include spacing(py-xs, px-xs);
8
+ }
@@ -0,0 +1,26 @@
1
+ export type KbdProps = {
2
+ keys?: ('cmd'
3
+ | 'shift'
4
+ | 'ctrl'
5
+ | 'option'
6
+ | 'enter'
7
+ | 'del'
8
+ | 'esc'
9
+ | 'tab'
10
+ | 'capslock'
11
+ | 'up'
12
+ | 'down'
13
+ | 'left'
14
+ | 'right'
15
+ | 'pageup'
16
+ | 'pagedown'
17
+ | 'home'
18
+ | 'end'
19
+ | 'help'
20
+ | 'space')[]
21
+ className?: string
22
+ }
23
+
24
+ export type ReactKbdProps = {
25
+ children?: React.ReactNode
26
+ } & KbdProps
@@ -0,0 +1,21 @@
1
+ export const keyMap = {
2
+ cmd: '⌘',
3
+ shift: '⇧',
4
+ ctrl: '⌃',
5
+ option: '⌥',
6
+ enter: '↵',
7
+ del: '⌫',
8
+ esc: '⎋',
9
+ tab: '⇥',
10
+ capslock: '⇪',
11
+ up: '↑',
12
+ down: '↓',
13
+ left: '←',
14
+ right: '→',
15
+ pageup: '⇞',
16
+ pagedown: '⇟',
17
+ home: '↖',
18
+ end: '↘',
19
+ help: '?',
20
+ space: '␣'
21
+ }
@@ -0,0 +1,50 @@
1
+ ---
2
+ import type { SpoilerProps } from './spoiler'
3
+
4
+ import styles from './spoiler.module.scss'
5
+
6
+ interface Props extends SpoilerProps {}
7
+
8
+ const {
9
+ color,
10
+ animated = true,
11
+ block,
12
+ tooltip,
13
+ tooltipPosition
14
+ } = Astro.props
15
+
16
+ const classes = [
17
+ styles.spoiler,
18
+ animated && styles.anim,
19
+ block && styles.block
20
+ ]
21
+
22
+ const style = color
23
+ ? `--w-spoiler-color: ${color};`
24
+ : null
25
+ ---
26
+
27
+ <span
28
+ class:list={classes}
29
+ style={style}
30
+ data-tooltip={tooltip}
31
+ data-position={tooltipPosition}
32
+ data-id="w-spoiler"
33
+ role="button"
34
+ tabindex="0"
35
+ >
36
+ <slot />
37
+ </span>
38
+
39
+ <script>
40
+ import { on } from '../../utils/DOMUtils'
41
+
42
+ on('[data-id="w-spoiler"]', 'click', (event: Event) => {
43
+ const target = event.currentTarget as HTMLDivElement
44
+
45
+ target.dataset.visible = 'true'
46
+ target.removeAttribute('data-tooltip')
47
+ target.removeAttribute('role')
48
+ target.removeAttribute('tabindex')
49
+ }, true)
50
+ </script>
@@ -0,0 +1,45 @@
1
+ <script lang="ts">
2
+ import type { SpoilerProps } from './spoiler'
3
+
4
+ import { classNames } from '../../utils/classNames'
5
+
6
+ import styles from './spoiler.module.scss'
7
+
8
+ export let color: SpoilerProps['color'] = ''
9
+ export let animated: SpoilerProps['animated'] = true
10
+ export let block: SpoilerProps['block'] = false
11
+ export let tooltip: SpoilerProps['tooltip'] = ''
12
+ export let tooltipPosition: SpoilerProps['tooltipPosition'] = null
13
+
14
+ const classes = classNames([
15
+ styles.spoiler,
16
+ animated && styles.anim,
17
+ block && styles.block
18
+ ])
19
+
20
+ const style = color
21
+ ? `--w-spoiler-color: ${color};`
22
+ : null
23
+
24
+ const toggle = (event: MouseEvent | KeyboardEvent) => {
25
+ const target = event.currentTarget as HTMLSpanElement
26
+
27
+ target.dataset.visible = 'true'
28
+ target.removeAttribute('data-tooltip')
29
+ target.removeAttribute('role')
30
+ target.removeAttribute('tabindex')
31
+ }
32
+ </script>
33
+
34
+ <span
35
+ class={classes}
36
+ style={style}
37
+ data-tooltip={tooltip || null}
38
+ data-position={tooltipPosition}
39
+ role="button"
40
+ tabindex="0"
41
+ on:click={toggle}
42
+ on:keyup={toggle}
43
+ >
44
+ <slot />
45
+ </span>
@@ -0,0 +1,50 @@
1
+ import React from 'react'
2
+ import type { ReactSpoilerProps } from './spoiler'
3
+
4
+ import { classNames } from '../../utils/classNames'
5
+
6
+ import styles from './spoiler.module.scss'
7
+
8
+ const Spoiler = ({
9
+ color,
10
+ animated = true,
11
+ block,
12
+ tooltip,
13
+ tooltipPosition,
14
+ children
15
+ }: ReactSpoilerProps) => {
16
+ const classes = classNames([
17
+ styles.spoiler,
18
+ animated && styles.anim,
19
+ block && styles.block
20
+ ])
21
+
22
+ const style = color
23
+ ? { '--w-spoiler-color': color } as React.CSSProperties
24
+ : undefined
25
+
26
+ const toggle = (event: React.MouseEvent<HTMLSpanElement>) => {
27
+ const target = event.currentTarget
28
+
29
+ target.dataset.visible = 'true'
30
+ target.removeAttribute('data-tooltip')
31
+ target.removeAttribute('role')
32
+ target.removeAttribute('tabindex')
33
+ }
34
+
35
+ return (
36
+ <span
37
+ className={classes}
38
+ style={style}
39
+ data-tooltip={tooltip}
40
+ data-position={tooltipPosition}
41
+ role="button"
42
+ tabIndex={0}
43
+ onClick={toggle}
44
+ >
45
+ {children}
46
+ </span>
47
+ )
48
+ }
49
+
50
+ export default Spoiler
@@ -0,0 +1,40 @@
1
+ @import '../../scss/config.scss';
2
+
3
+ body {
4
+ --w-spoiler-color: var(--w-color-primary);
5
+ }
6
+
7
+ span.spoiler {
8
+ @include border-radius();
9
+ @include background(var(--w-spoiler-color));
10
+ @include typography(hmd);
11
+ @include visibility(inline);
12
+
13
+ color: transparent;
14
+ user-select: none;
15
+ cursor: pointer;
16
+
17
+ &.anim {
18
+ @include transition();
19
+ }
20
+
21
+ &.block {
22
+ @include visibility(block);
23
+ }
24
+
25
+ code {
26
+ @include border(0);
27
+ }
28
+
29
+ &[data-visible] {
30
+ @include background(transparent);
31
+
32
+ color: inherit;
33
+ user-select: auto;
34
+ cursor: auto;
35
+
36
+ code {
37
+ @include border(primary-50);
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,11 @@
1
+ export type SpoilerProps = {
2
+ color?: string
3
+ animated?: boolean
4
+ block?: boolean
5
+ tooltip?: string
6
+ tooltipPosition?: 'bottom' | null
7
+ }
8
+
9
+ export type ReactSpoilerProps = {
10
+ children: React.ReactNode
11
+ } & SpoilerProps
@@ -0,0 +1,61 @@
1
+ ---
2
+ import type { StepperProps } from './stepper'
3
+
4
+ import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.astro'
5
+ import Icon from '../Icon/Icon.astro'
6
+
7
+ import styles from './stepper.module.scss'
8
+
9
+ import type { IconProps } from '../Icon/icon'
10
+
11
+ interface Props extends StepperProps {}
12
+
13
+ const {
14
+ items,
15
+ color,
16
+ completedColor,
17
+ activeColor,
18
+ borderless,
19
+ vertical,
20
+ className
21
+ } = Astro.props
22
+
23
+ const classes = [
24
+ styles.stepper,
25
+ borderless && styles.borderless,
26
+ vertical && styles.vertical,
27
+ className
28
+ ]
29
+
30
+ const styleVariables = [
31
+ color && `--w-stepper-color-border: ${color}`,
32
+ completedColor && `--w-stepper-color-complete: ${completedColor}`,
33
+ activeColor && `--w-stepper-color-active: ${activeColor}`
34
+ ].filter(Boolean).join(';')
35
+ ---
36
+
37
+ <ol class:list={classes} style={styleVariables}>
38
+ {items?.map((item, index) => (
39
+ <li class:list={[
40
+ index !== 0 && styles.connect,
41
+ item.active && styles.active,
42
+ item.completed && styles.completed
43
+ ]}>
44
+ <span class={styles.number}>
45
+ {item.icon ? (
46
+ <Fragment>
47
+ {item.icon.startsWith('<svg')
48
+ ? <Fragment set:html={item.icon} />
49
+ : <Icon type={item.icon as IconProps['type']} />
50
+ }
51
+ </Fragment>
52
+ ) : index + 1}
53
+ </span>
54
+ <ConditionalWrapper condition={!!(item.title && item.subTitle)}>
55
+ <div slot="wrapper" class={styles.container}>children</div>
56
+ {item.title && <span>{item.title}</span>}
57
+ {item.subTitle && <span class={styles.muted}>{item.subTitle}</span>}
58
+ </ConditionalWrapper>
59
+ </li>
60
+ ))}
61
+ </ol>
@@ -0,0 +1,59 @@
1
+ <script lang="ts">
2
+ import type { StepperProps } from './stepper'
3
+
4
+ import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.svelte'
5
+
6
+ import { classNames } from '../../utils/classNames'
7
+
8
+ import styles from './stepper.module.scss'
9
+
10
+ export let items: StepperProps['items'] = []
11
+ export let color: StepperProps['color'] = ''
12
+ export let completedColor: StepperProps['completedColor'] = ''
13
+ export let activeColor: StepperProps['activeColor'] = ''
14
+ export let borderless: StepperProps['vertical'] = false
15
+ export let vertical: StepperProps['vertical'] = false
16
+ export let className: StepperProps['className'] = ''
17
+
18
+ const classes = classNames([
19
+ styles.stepper,
20
+ borderless && styles.borderless,
21
+ vertical && styles.vertical,
22
+ className
23
+ ])
24
+
25
+ const styleVariables = [
26
+ color && `--w-stepper-color-border: ${color}`,
27
+ completedColor && `--w-stepper-color-complete: ${completedColor}`,
28
+ activeColor && `--w-stepper-color-active: ${activeColor}`
29
+ ].filter(Boolean).join(';')
30
+ </script>
31
+
32
+ <ol class={classes} style={styleVariables || null}>
33
+ {#each items as item, index}
34
+ <li class={classNames([
35
+ index !== 0 && styles.connect,
36
+ item.active && styles.active,
37
+ item.completed && styles.completed
38
+ ])}>
39
+ <span class={styles.number}>
40
+ {#if item.icon}
41
+ {@html item.icon}
42
+ {:else}
43
+ {index + 1}
44
+ {/if}
45
+ </span>
46
+ <ConditionalWrapper
47
+ condition={!!(item.title && item.subTitle)}
48
+ class={styles.container}
49
+ >
50
+ {#if item.title}
51
+ <span>{item.title}</span>
52
+ {/if}
53
+ {#if item.subTitle}
54
+ <span class={styles.muted}>{item.subTitle}</span>
55
+ {/if}
56
+ </ConditionalWrapper>
57
+ </li>
58
+ {/each}
59
+ </ol>
@@ -0,0 +1,60 @@
1
+ import React from 'react'
2
+ import type { StepperProps } from './stepper'
3
+
4
+ import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.tsx'
5
+
6
+ import { classNames } from '../../utils/classNames'
7
+
8
+ import styles from './stepper.module.scss'
9
+
10
+ const Stepper = ({
11
+ items,
12
+ color,
13
+ completedColor,
14
+ activeColor,
15
+ borderless,
16
+ vertical,
17
+ className
18
+ }: StepperProps) => {
19
+ const classes = classNames([
20
+ styles.stepper,
21
+ borderless && styles.borderless,
22
+ vertical && styles.vertical,
23
+ className
24
+ ])
25
+
26
+ const styleVariables = {
27
+ ...(color && { '--w-stepper-color-border': color }),
28
+ ...(completedColor && { '--w-stepper-color-complete': completedColor }),
29
+ ...(activeColor && { '--w-stepper-color-active': activeColor })
30
+ } as React.CSSProperties
31
+
32
+ return (
33
+ <ol className={classes} style={styleVariables}>
34
+ {items?.map((item, index) => (
35
+ <li className={classNames([
36
+ index !== 0 && styles.connect,
37
+ item.active && styles.active,
38
+ item.completed && styles.completed
39
+ ])} key={index}>
40
+ <span
41
+ className={styles.number}
42
+ dangerouslySetInnerHTML={{ __html: item.icon
43
+ ? item.icon
44
+ : index + 1
45
+ }}
46
+ />
47
+ <ConditionalWrapper
48
+ condition={!!(item.title && item.subTitle)}
49
+ wrapper={children => <div className={styles.container}>{children}</div>}
50
+ >
51
+ {item.title && <span>{item.title}</span>}
52
+ {item.subTitle && <span className={styles.muted}>{item.subTitle}</span>}
53
+ </ConditionalWrapper>
54
+ </li>
55
+ ))}
56
+ </ol>
57
+ )
58
+ }
59
+
60
+ export default Stepper