@tuspe/components 1.6.26
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.
- package/README.md +203 -0
- package/dist/Breadcrumbs.svelte +81 -0
- package/dist/Breadcrumbs.svelte.d.ts +9 -0
- package/dist/Button.svelte +266 -0
- package/dist/Button.svelte.d.ts +36 -0
- package/dist/ButtonArrow.svelte +21 -0
- package/dist/ButtonArrow.svelte.d.ts +9 -0
- package/dist/ButtonClose.svelte +25 -0
- package/dist/ButtonClose.svelte.d.ts +6 -0
- package/dist/ButtonMenu.svelte +51 -0
- package/dist/ButtonMenu.svelte.d.ts +12 -0
- package/dist/Checkbox.svelte +55 -0
- package/dist/Checkbox.svelte.d.ts +13 -0
- package/dist/Image.svelte +89 -0
- package/dist/Image.svelte.d.ts +15 -0
- package/dist/Input.svelte +170 -0
- package/dist/Input.svelte.d.ts +21 -0
- package/dist/Modal.svelte +78 -0
- package/dist/Modal.svelte.d.ts +11 -0
- package/dist/Select.svelte +60 -0
- package/dist/Select.svelte.d.ts +15 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +105 -0
- package/package.json +81 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Button from './Button.svelte'
|
|
3
|
+
interface Props {
|
|
4
|
+
onclick?: () => any
|
|
5
|
+
ariaControls: string
|
|
6
|
+
ariaLabel: string
|
|
7
|
+
color?: 'black' | 'white'
|
|
8
|
+
extraClass?: string
|
|
9
|
+
hidden?: boolean
|
|
10
|
+
open: boolean
|
|
11
|
+
}
|
|
12
|
+
let {ariaControls, ariaLabel, color = 'white', extraClass, hidden = false, open = $bindable()}: Props = $props()
|
|
13
|
+
const handleOpen = () => {
|
|
14
|
+
open = !open
|
|
15
|
+
}
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<div id="menu-button" class={extraClass} class:hidden>
|
|
19
|
+
<Button onclick={handleOpen} {ariaControls} ariaPopup="menu" ariaExpanded={open} {ariaLabel} {color} control fill>
|
|
20
|
+
<svg
|
|
21
|
+
fill={color}
|
|
22
|
+
clip-rule="evenodd"
|
|
23
|
+
fill-rule="evenodd"
|
|
24
|
+
stroke-linejoin="round"
|
|
25
|
+
stroke-miterlimit="2"
|
|
26
|
+
height="32"
|
|
27
|
+
width="32"
|
|
28
|
+
viewBox="0 0 24 24"
|
|
29
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
30
|
+
>
|
|
31
|
+
<title>{open ? 'Close' : 'Open'} menu</title>
|
|
32
|
+
{#if !open}
|
|
33
|
+
<path
|
|
34
|
+
d="m22 16.75c0-.414-.336-.75-.75-.75h-18.5c-.414 0-.75.336-.75.75s.336.75.75.75h18.5c.414 0 .75-.336.75-.75zm0-5c0-.414-.336-.75-.75-.75h-18.5c-.414 0-.75.336-.75.75s.336.75.75.75h18.5c.414 0 .75-.336.75-.75zm0-5c0-.414-.336-.75-.75-.75h-18.5c-.414 0-.75.336-.75.75s.336.75.75.75h18.5c.414 0 .75-.336.75-.75z"
|
|
35
|
+
fill-rule="nonzero"
|
|
36
|
+
/>
|
|
37
|
+
{:else}
|
|
38
|
+
<path
|
|
39
|
+
d="m12 10.93 5.719-5.72c.146-.146.339-.219.531-.219.404 0 .75.324.75.749 0 .193-.073.385-.219.532l-5.72 5.719 5.719 5.719c.147.147.22.339.22.531 0 .427-.349.75-.75.75-.192 0-.385-.073-.531-.219l-5.719-5.719-5.719 5.719c-.146.146-.339.219-.531.219-.401 0-.75-.323-.75-.75 0-.192.073-.384.22-.531l5.719-5.719-5.72-5.719c-.146-.147-.219-.339-.219-.532 0-.425.346-.749.75-.749.192 0 .385.073.531.219z"
|
|
40
|
+
/>
|
|
41
|
+
{/if}
|
|
42
|
+
</svg>
|
|
43
|
+
</Button>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<style scoped>
|
|
47
|
+
#menu-button {
|
|
48
|
+
height: 48px;
|
|
49
|
+
width: 48px;
|
|
50
|
+
}
|
|
51
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
onclick?: () => any;
|
|
3
|
+
ariaControls: string;
|
|
4
|
+
ariaLabel: string;
|
|
5
|
+
color?: 'black' | 'white';
|
|
6
|
+
extraClass?: string;
|
|
7
|
+
hidden?: boolean;
|
|
8
|
+
open: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const ButtonMenu: import("svelte").Component<Props, {}, "open">;
|
|
11
|
+
type ButtonMenu = ReturnType<typeof ButtonMenu>;
|
|
12
|
+
export default ButtonMenu;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {loading} from './'
|
|
3
|
+
import type {Snippet} from 'svelte'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
children: Snippet
|
|
7
|
+
onchange?: () => void
|
|
8
|
+
checked?: boolean
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
id?: string
|
|
11
|
+
outerClass?: string
|
|
12
|
+
value?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let {children, onchange, checked = $bindable(false), disabled, id, outerClass, value}: Props = $props()
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<label class={outerClass}>
|
|
19
|
+
<input bind:checked disabled={disabled || $loading} {id} {onchange} type="checkbox" {value} />
|
|
20
|
+
<span>{@render children?.()}</span>
|
|
21
|
+
</label>
|
|
22
|
+
|
|
23
|
+
<style scoped>
|
|
24
|
+
input {
|
|
25
|
+
accent-color: var(--color-primary);
|
|
26
|
+
border: 1px solid var(--color-border);
|
|
27
|
+
height: 20px;
|
|
28
|
+
margin-right: 10px;
|
|
29
|
+
outline: none;
|
|
30
|
+
vertical-align: middle;
|
|
31
|
+
width: 20px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
input:disabled {
|
|
35
|
+
cursor: not-allowed;
|
|
36
|
+
opacity: 0.6;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
input,
|
|
40
|
+
label {
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
label {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
line-height: 1.25;
|
|
49
|
+
font-size: 1rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
span {
|
|
53
|
+
margin-top: 1px;
|
|
54
|
+
}
|
|
55
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
children: Snippet;
|
|
4
|
+
onchange?: () => void;
|
|
5
|
+
checked?: boolean;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
id?: string;
|
|
8
|
+
outerClass?: string;
|
|
9
|
+
value?: string;
|
|
10
|
+
}
|
|
11
|
+
declare const Checkbox: import("svelte").Component<Props, {}, "checked">;
|
|
12
|
+
type Checkbox = ReturnType<typeof Checkbox>;
|
|
13
|
+
export default Checkbox;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {ImageData} from './'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
aspect?: '3:4' | '4:3' | 'square' | 'video'
|
|
6
|
+
ball?: boolean
|
|
7
|
+
border?: boolean
|
|
8
|
+
center?: boolean
|
|
9
|
+
extraClasses?: string
|
|
10
|
+
fullWidth?: boolean
|
|
11
|
+
image: ImageData
|
|
12
|
+
loading?: 'eager' | 'lazy'
|
|
13
|
+
objectFit?: 'contain' | 'cover'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {aspect, ball = false, border, center = false, extraClasses, fullWidth, image, loading = 'lazy', objectFit}: Props = $props()
|
|
17
|
+
|
|
18
|
+
let classes = $state('')
|
|
19
|
+
if (aspect) {
|
|
20
|
+
classes += `aspect-${aspect}`
|
|
21
|
+
}
|
|
22
|
+
if (objectFit) {
|
|
23
|
+
classes += ' ' + objectFit
|
|
24
|
+
}
|
|
25
|
+
if (ball) {
|
|
26
|
+
classes += ' radius-full'
|
|
27
|
+
}
|
|
28
|
+
if (border) {
|
|
29
|
+
classes += ' border-full'
|
|
30
|
+
}
|
|
31
|
+
if (center) {
|
|
32
|
+
classes += ' mx-auto'
|
|
33
|
+
}
|
|
34
|
+
if (fullWidth) {
|
|
35
|
+
classes += ' full'
|
|
36
|
+
}
|
|
37
|
+
if (extraClasses) {
|
|
38
|
+
classes += ' ' + extraClasses
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
{#if image?.src}
|
|
43
|
+
<img alt={image.alt} class={classes} decoding="async" height={image.height} {loading} src={image.src} width={image.width} />
|
|
44
|
+
{/if}
|
|
45
|
+
|
|
46
|
+
<style scoped>
|
|
47
|
+
img {
|
|
48
|
+
display: inline-block;
|
|
49
|
+
}
|
|
50
|
+
img:not(.cover) {
|
|
51
|
+
height: auto;
|
|
52
|
+
max-width: 100%;
|
|
53
|
+
}
|
|
54
|
+
.aspect-4\:3 {
|
|
55
|
+
aspect-ratio: 4 / 3;
|
|
56
|
+
}
|
|
57
|
+
.aspect-3\:4 {
|
|
58
|
+
aspect-ratio: 3 / 4;
|
|
59
|
+
}
|
|
60
|
+
.aspect-square {
|
|
61
|
+
aspect-ratio: 1 / 1;
|
|
62
|
+
}
|
|
63
|
+
.aspect-video {
|
|
64
|
+
aspect-ratio: 16 / 9;
|
|
65
|
+
}
|
|
66
|
+
.border-full {
|
|
67
|
+
border: 1px solid var(--color-content);
|
|
68
|
+
}
|
|
69
|
+
.contain {
|
|
70
|
+
object-fit: contain;
|
|
71
|
+
max-height: 100%;
|
|
72
|
+
}
|
|
73
|
+
.cover {
|
|
74
|
+
object-fit: cover;
|
|
75
|
+
object-position: top;
|
|
76
|
+
}
|
|
77
|
+
.cover,
|
|
78
|
+
.full:not(.contain) {
|
|
79
|
+
width: 100%;
|
|
80
|
+
}
|
|
81
|
+
.mx-auto {
|
|
82
|
+
margin-left: auto;
|
|
83
|
+
margin-right: auto;
|
|
84
|
+
}
|
|
85
|
+
.radius-full {
|
|
86
|
+
border-radius: 50%;
|
|
87
|
+
overflow: hidden;
|
|
88
|
+
}
|
|
89
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ImageData } from './';
|
|
2
|
+
interface Props {
|
|
3
|
+
aspect?: '3:4' | '4:3' | 'square' | 'video';
|
|
4
|
+
ball?: boolean;
|
|
5
|
+
border?: boolean;
|
|
6
|
+
center?: boolean;
|
|
7
|
+
extraClasses?: string;
|
|
8
|
+
fullWidth?: boolean;
|
|
9
|
+
image: ImageData;
|
|
10
|
+
loading?: 'eager' | 'lazy';
|
|
11
|
+
objectFit?: 'contain' | 'cover';
|
|
12
|
+
}
|
|
13
|
+
declare const Image: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
type Image = ReturnType<typeof Image>;
|
|
15
|
+
export default Image;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {loading} from './'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
onchange?: () => void
|
|
6
|
+
onclick?: () => void
|
|
7
|
+
borderColor?: 'content' | 'default' | 'primary' | 'none'
|
|
8
|
+
bgColor?: 'transparent' | 'white' | 'none'
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
id?: string
|
|
11
|
+
inputClass?: string
|
|
12
|
+
label: string
|
|
13
|
+
max?: number | string
|
|
14
|
+
min?: number | string
|
|
15
|
+
outerClass?: string
|
|
16
|
+
placeholder?: string
|
|
17
|
+
required?: boolean
|
|
18
|
+
step?: number
|
|
19
|
+
type?: 'email' | 'date' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'textarea' | 'time' | 'url'
|
|
20
|
+
value: string | number
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let {
|
|
24
|
+
bgColor = 'transparent',
|
|
25
|
+
borderColor = 'default',
|
|
26
|
+
disabled,
|
|
27
|
+
id,
|
|
28
|
+
inputClass,
|
|
29
|
+
label,
|
|
30
|
+
max,
|
|
31
|
+
min,
|
|
32
|
+
onchange,
|
|
33
|
+
outerClass,
|
|
34
|
+
placeholder,
|
|
35
|
+
required = false,
|
|
36
|
+
step,
|
|
37
|
+
type = 'text',
|
|
38
|
+
value = $bindable()
|
|
39
|
+
}: Props = $props()
|
|
40
|
+
|
|
41
|
+
let isDisabled = $state(disabled || $loading)
|
|
42
|
+
|
|
43
|
+
let classes = $state('')
|
|
44
|
+
if (inputClass) {
|
|
45
|
+
classes = inputClass
|
|
46
|
+
}
|
|
47
|
+
if (bgColor && bgColor !== 'none') {
|
|
48
|
+
classes += ` bg-${bgColor}`
|
|
49
|
+
}
|
|
50
|
+
if (borderColor && borderColor !== 'none') {
|
|
51
|
+
classes += ` border-color-${borderColor}`
|
|
52
|
+
}
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<label class={outerClass}>
|
|
56
|
+
{label}{#if required}<sup>*</sup>{/if}
|
|
57
|
+
|
|
58
|
+
{#if type === 'textarea'}
|
|
59
|
+
<textarea bind:value class={classes} disabled={isDisabled} {id} maxlength={max ? Number(max) : undefined} {required} {placeholder} rows={4}
|
|
60
|
+
></textarea>
|
|
61
|
+
{:else if ['date', 'number'].includes(type)}
|
|
62
|
+
<input bind:value class={classes} disabled={isDisabled} lang="fi-FI" {max} {min} {onchange} {required} {step} {type} {placeholder} />
|
|
63
|
+
{:else}
|
|
64
|
+
<input
|
|
65
|
+
bind:value
|
|
66
|
+
{id}
|
|
67
|
+
{placeholder}
|
|
68
|
+
{required}
|
|
69
|
+
{type}
|
|
70
|
+
class={classes}
|
|
71
|
+
disabled={isDisabled}
|
|
72
|
+
maxlength={max ? Number(max) : undefined}
|
|
73
|
+
minlength={min ? Number(min) : undefined}
|
|
74
|
+
onkeyup={onchange}
|
|
75
|
+
/>
|
|
76
|
+
{#if type === 'search'}
|
|
77
|
+
<svg
|
|
78
|
+
clip-rule="evenodd"
|
|
79
|
+
fill-rule="evenodd"
|
|
80
|
+
stroke-linejoin="round"
|
|
81
|
+
stroke-miterlimit="2"
|
|
82
|
+
viewBox="0 0 24 24"
|
|
83
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
84
|
+
height="20"
|
|
85
|
+
width="20"
|
|
86
|
+
>
|
|
87
|
+
<path
|
|
88
|
+
d="m15.97 17.031c-1.479 1.238-3.384 1.985-5.461 1.985-4.697 0-8.509-3.812-8.509-8.508s3.812-8.508 8.509-8.508c4.695 0 8.508 3.812 8.508 8.508 0 2.078-.747 3.984-1.985 5.461l4.749 4.75c.146.146.219.338.219.531 0 .587-.537.75-.75.75-.192 0-.384-.073-.531-.22zm-5.461-13.53c-3.868 0-7.007 3.14-7.007 7.007s3.139 7.007 7.007 7.007c3.866 0 7.007-3.14 7.007-7.007s-3.141-7.007-7.007-7.007z"
|
|
89
|
+
fill-rule="nonzero"
|
|
90
|
+
/>
|
|
91
|
+
</svg>
|
|
92
|
+
{/if}
|
|
93
|
+
{/if}
|
|
94
|
+
</label>
|
|
95
|
+
|
|
96
|
+
<style scoped>
|
|
97
|
+
input {
|
|
98
|
+
height: 48px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
input,
|
|
102
|
+
textarea {
|
|
103
|
+
border-radius: 0.375rem;
|
|
104
|
+
border-style: solid;
|
|
105
|
+
border-width: 1px;
|
|
106
|
+
color: var(--color-content);
|
|
107
|
+
display: block;
|
|
108
|
+
font-size: 1rem;
|
|
109
|
+
margin-top: 0.25rem;
|
|
110
|
+
padding-left: 0.5rem;
|
|
111
|
+
padding-right: 0.5rem;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
input,
|
|
115
|
+
label,
|
|
116
|
+
textarea {
|
|
117
|
+
width: 100%;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
input:disabled,
|
|
121
|
+
textarea:disabled {
|
|
122
|
+
cursor: not-allowed;
|
|
123
|
+
opacity: 0.6;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
label {
|
|
127
|
+
display: inline-block;
|
|
128
|
+
position: relative;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
label.filter {
|
|
132
|
+
font-size: var(--text-sm);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
label svg {
|
|
136
|
+
bottom: 15px;
|
|
137
|
+
position: absolute;
|
|
138
|
+
right: 8px;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
sup {
|
|
142
|
+
color: darkred;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
textarea {
|
|
146
|
+
height: 150px;
|
|
147
|
+
padding-bottom: 0.25rem;
|
|
148
|
+
padding-top: 0.25rem;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.bg-transparent {
|
|
152
|
+
background-color: transparent;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.bg-white {
|
|
156
|
+
background-color: white;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.border-color-default {
|
|
160
|
+
border-color: var(--color-border);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.border-color-primary {
|
|
164
|
+
border-color: var(--color-primary);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.border-color-content {
|
|
168
|
+
border-color: var(--color-content);
|
|
169
|
+
}
|
|
170
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
onchange?: () => void;
|
|
3
|
+
onclick?: () => void;
|
|
4
|
+
borderColor?: 'content' | 'default' | 'primary' | 'none';
|
|
5
|
+
bgColor?: 'transparent' | 'white' | 'none';
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
id?: string;
|
|
8
|
+
inputClass?: string;
|
|
9
|
+
label: string;
|
|
10
|
+
max?: number | string;
|
|
11
|
+
min?: number | string;
|
|
12
|
+
outerClass?: string;
|
|
13
|
+
placeholder?: string;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
step?: number;
|
|
16
|
+
type?: 'email' | 'date' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'textarea' | 'time' | 'url';
|
|
17
|
+
value: string | number;
|
|
18
|
+
}
|
|
19
|
+
declare const Input: import("svelte").Component<Props, {}, "value">;
|
|
20
|
+
type Input = ReturnType<typeof Input>;
|
|
21
|
+
export default Input;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {Snippet} from 'svelte'
|
|
3
|
+
import ButtonClose from './ButtonClose.svelte'
|
|
4
|
+
interface Props {
|
|
5
|
+
children: Snippet
|
|
6
|
+
innerClass?: string
|
|
7
|
+
open?: boolean
|
|
8
|
+
outerClass?: string
|
|
9
|
+
title?: string
|
|
10
|
+
}
|
|
11
|
+
let {children, innerClass, open = $bindable(), outerClass, title}: Props = $props()
|
|
12
|
+
const handleClose = () => {
|
|
13
|
+
open = false
|
|
14
|
+
}
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<div id="modal" class:hidden={!open}>
|
|
18
|
+
<div id="modal-content" class={outerClass}>
|
|
19
|
+
<header>
|
|
20
|
+
{#if title}
|
|
21
|
+
<h2>{title}</h2>
|
|
22
|
+
{/if}
|
|
23
|
+
<ButtonClose color="black" onclick={handleClose} />
|
|
24
|
+
</header>
|
|
25
|
+
<div id="modal-body" class={innerClass}>
|
|
26
|
+
{@render children?.()}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<style scoped>
|
|
32
|
+
#modal {
|
|
33
|
+
align-items: center;
|
|
34
|
+
background-color: rgba(0, 0, 0, 0.6);
|
|
35
|
+
height: 100vh;
|
|
36
|
+
justify-content: center;
|
|
37
|
+
left: 0;
|
|
38
|
+
position: fixed;
|
|
39
|
+
top: 0;
|
|
40
|
+
width: 100vw;
|
|
41
|
+
z-index: 200;
|
|
42
|
+
}
|
|
43
|
+
#modal:not(.hidden) {
|
|
44
|
+
display: flex;
|
|
45
|
+
}
|
|
46
|
+
#modal.hidden {
|
|
47
|
+
display: none;
|
|
48
|
+
visibility: hidden;
|
|
49
|
+
}
|
|
50
|
+
#modal-content {
|
|
51
|
+
background-color: #fff;
|
|
52
|
+
border-radius: 1rem;
|
|
53
|
+
border: 2px solid var(--color-primary);
|
|
54
|
+
box-shadow: var(--shadow-md);
|
|
55
|
+
margin-left: auto;
|
|
56
|
+
margin-right: auto;
|
|
57
|
+
max-height: 85vh;
|
|
58
|
+
max-width: 95vw;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
overscroll-behavior: contain;
|
|
61
|
+
position: relative;
|
|
62
|
+
}
|
|
63
|
+
#modal-body {
|
|
64
|
+
max-height: 45vh;
|
|
65
|
+
overflow-x: hidden;
|
|
66
|
+
overflow-y: auto;
|
|
67
|
+
padding: 1rem;
|
|
68
|
+
}
|
|
69
|
+
header {
|
|
70
|
+
border-bottom: 1px solid var(--color-border);
|
|
71
|
+
padding: 1rem;
|
|
72
|
+
}
|
|
73
|
+
h2 {
|
|
74
|
+
font-size: 1.6rem;
|
|
75
|
+
line-height: 1;
|
|
76
|
+
margin: 0;
|
|
77
|
+
}
|
|
78
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
children: Snippet;
|
|
4
|
+
innerClass?: string;
|
|
5
|
+
open?: boolean;
|
|
6
|
+
outerClass?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
}
|
|
9
|
+
declare const Modal: import("svelte").Component<Props, {}, "open">;
|
|
10
|
+
type Modal = ReturnType<typeof Modal>;
|
|
11
|
+
export default Modal;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {loading, type SelectItem} from './'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
onchange?: () => void
|
|
6
|
+
disabled?: boolean
|
|
7
|
+
outerClass?: string
|
|
8
|
+
id?: string
|
|
9
|
+
label: string
|
|
10
|
+
placeholder?: string
|
|
11
|
+
required?: boolean
|
|
12
|
+
value: string | number
|
|
13
|
+
values: SelectItem[]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {onchange, disabled, outerClass, id, label, placeholder, required = false, value = $bindable(), values}: Props = $props()
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<label class={outerClass}>
|
|
20
|
+
{label}
|
|
21
|
+
{#if required}<sup>*</sup>{/if}
|
|
22
|
+
<select bind:value {onchange} disabled={disabled || $loading} {id} {placeholder} {required}>
|
|
23
|
+
{#each values as item}
|
|
24
|
+
<option value={item.value}>{item.name}</option>
|
|
25
|
+
{/each}
|
|
26
|
+
</select>
|
|
27
|
+
</label>
|
|
28
|
+
|
|
29
|
+
<style scoped>
|
|
30
|
+
select {
|
|
31
|
+
background-color: transparent;
|
|
32
|
+
border-radius: 0.375rem;
|
|
33
|
+
border: 1px solid var(--color-border);
|
|
34
|
+
color: var(--color-content);
|
|
35
|
+
font-size: 1rem;
|
|
36
|
+
height: 48px;
|
|
37
|
+
margin-top: 0.25rem;
|
|
38
|
+
padding: 0 0.5rem;
|
|
39
|
+
width: 100%;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
select:disabled {
|
|
43
|
+
cursor: not-allowed;
|
|
44
|
+
opacity: 0.6;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
label,
|
|
48
|
+
select {
|
|
49
|
+
display: block;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
label.filter {
|
|
53
|
+
position: relative;
|
|
54
|
+
font-size: var(--text-sm);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
sup {
|
|
58
|
+
color: darkred;
|
|
59
|
+
}
|
|
60
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type SelectItem } from './';
|
|
2
|
+
interface Props {
|
|
3
|
+
onchange?: () => void;
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
outerClass?: string;
|
|
6
|
+
id?: string;
|
|
7
|
+
label: string;
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
value: string | number;
|
|
11
|
+
values: SelectItem[];
|
|
12
|
+
}
|
|
13
|
+
declare const Select: import("svelte").Component<Props, {}, "value">;
|
|
14
|
+
type Select = ReturnType<typeof Select>;
|
|
15
|
+
export default Select;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import Breadcrumbs from './Breadcrumbs.svelte';
|
|
2
|
+
import Button from './Button.svelte';
|
|
3
|
+
import ButtonArrow from './ButtonArrow.svelte';
|
|
4
|
+
import ButtonClose from './ButtonClose.svelte';
|
|
5
|
+
import ButtonMenu from './ButtonMenu.svelte';
|
|
6
|
+
import Checkbox from './Checkbox.svelte';
|
|
7
|
+
import Image from './Image.svelte';
|
|
8
|
+
import Input from './Input.svelte';
|
|
9
|
+
import Modal from './Modal.svelte';
|
|
10
|
+
import Select from './Select.svelte';
|
|
11
|
+
export { Breadcrumbs, Button, ButtonArrow, ButtonClose, ButtonMenu, Checkbox, Image, Input, Modal, Select };
|
|
12
|
+
export interface Breadcrumb {
|
|
13
|
+
'@type'?: string;
|
|
14
|
+
item: string;
|
|
15
|
+
name: string;
|
|
16
|
+
position?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ImageData {
|
|
19
|
+
alt: string;
|
|
20
|
+
height: number;
|
|
21
|
+
src: string;
|
|
22
|
+
width: number;
|
|
23
|
+
}
|
|
24
|
+
export interface SelectItem {
|
|
25
|
+
name: string;
|
|
26
|
+
value: number | string;
|
|
27
|
+
}
|
|
28
|
+
export declare const loading: import("svelte/store").Writable<number>;
|
|
29
|
+
/**
|
|
30
|
+
* PRICES AND NUMBERS
|
|
31
|
+
*/
|
|
32
|
+
export declare const formatPrice: (value: number | string, comma?: boolean, currency?: string) => string;
|
|
33
|
+
export declare const fixNumber: (value: number | string) => number;
|
|
34
|
+
export declare const calculateTax: (total: number, vatPercentage?: number) => number;
|
|
35
|
+
export declare const calculatePreTax: (total: number, vatPercentage?: number) => number;
|
|
36
|
+
/**
|
|
37
|
+
* STRING VALIDATIONS
|
|
38
|
+
*/
|
|
39
|
+
export declare const slugify: (value: string) => string;
|
|
40
|
+
export declare const validateSlug: (value: string) => boolean;
|
|
41
|
+
export declare const validateEmail: (email: string) => boolean;
|
|
42
|
+
export declare const validateString: (value: string) => boolean;
|
|
43
|
+
/**
|
|
44
|
+
* ARRAY VALIDATIONS
|
|
45
|
+
*/
|
|
46
|
+
export declare const validateArray: (value: any, items?: number) => boolean;
|
|
47
|
+
/**
|
|
48
|
+
* CACHE
|
|
49
|
+
*/
|
|
50
|
+
export declare const cacheValues: import("svelte/store").Writable<{
|
|
51
|
+
[key: string]: any;
|
|
52
|
+
}>;
|
|
53
|
+
export declare const handleCache: (key: string, value?: any) => any;
|
|
54
|
+
/**
|
|
55
|
+
* PREVENT DEFAULT
|
|
56
|
+
*/
|
|
57
|
+
export declare const preventDefault: (fn: Function) => (this: any, event: any) => void;
|