svelte-toggle-switch 1.0.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.
- package/README.md +54 -0
- package/index.html +13 -0
- package/index.js +3 -0
- package/jsconfig.json +34 -0
- package/package.json +31 -0
- package/public/favicon.ico +0 -0
- package/src/App.svelte +22 -0
- package/src/assets/svelte.png +0 -0
- package/src/lib/Switch.svelte +259 -0
- package/src/main.js +7 -0
- package/src/vite-env.d.ts +2 -0
- package/vite.config.js +7 -0
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Svelte Toggle Switch
|
|
2
|
+
|
|
3
|
+
## Install
|
|
4
|
+
|
|
5
|
+
Install using NPM
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
npm i svelte-toggle-switch
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Install using YARN
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
yarn add svelte-toggle-switch
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## How to use
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
<script>
|
|
21
|
+
import Select from 'svelte-toggle-switch';
|
|
22
|
+
|
|
23
|
+
let switchValue;
|
|
24
|
+
let sliderValue;
|
|
25
|
+
let multiValue;
|
|
26
|
+
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<Switch bind:value={switchValue} label="Enable Toggle" design="inner" />
|
|
30
|
+
<p>
|
|
31
|
+
Switch is {switchValue}
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
<Switch bind:value={sliderValue} label="Enable Toggle" fontSize={24} design="slider" />
|
|
35
|
+
<p>
|
|
36
|
+
Switch is {sliderValue}
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
<Switch bind:value={multiValue} label="Choose an Option" design="multi" options={['true', 'false']} fontSize={12}/>
|
|
40
|
+
<p>
|
|
41
|
+
Switch is {multiValue}
|
|
42
|
+
</p>
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Options
|
|
47
|
+
|
|
48
|
+
| API | Value |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `label` | `Your Text` |
|
|
51
|
+
| `design` | `inner`, `slider`, `multi` |
|
|
52
|
+
| `fontSize` | `16px` |
|
|
53
|
+
| `options` | `['true', 'false']` |
|
|
54
|
+
|
package/index.html
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" href="/favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Svelte + Vite App</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="app"></div>
|
|
11
|
+
<script type="module" src="/src/main.js"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
package/index.js
ADDED
package/jsconfig.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"moduleResolution": "node",
|
|
4
|
+
"target": "esnext",
|
|
5
|
+
"module": "esnext",
|
|
6
|
+
/**
|
|
7
|
+
* svelte-preprocess cannot figure out whether you have
|
|
8
|
+
* a value or a type, so tell TypeScript to enforce using
|
|
9
|
+
* `import type` instead of `import` for Types.
|
|
10
|
+
*/
|
|
11
|
+
"importsNotUsedAsValues": "error",
|
|
12
|
+
"isolatedModules": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
/**
|
|
15
|
+
* To have warnings / errors of the Svelte compiler at the
|
|
16
|
+
* correct position, enable source maps by default.
|
|
17
|
+
*/
|
|
18
|
+
"sourceMap": true,
|
|
19
|
+
"esModuleInterop": true,
|
|
20
|
+
"skipLibCheck": true,
|
|
21
|
+
"forceConsistentCasingInFileNames": true,
|
|
22
|
+
"baseUrl": ".",
|
|
23
|
+
/**
|
|
24
|
+
* Typecheck JS in `.svelte` and `.js` files by default.
|
|
25
|
+
* Disable this if you'd like to use dynamic types.
|
|
26
|
+
*/
|
|
27
|
+
"checkJs": true
|
|
28
|
+
},
|
|
29
|
+
/**
|
|
30
|
+
* Use global.d.ts instead of compilerOptions.types
|
|
31
|
+
* to avoid limiting type declarations.
|
|
32
|
+
*/
|
|
33
|
+
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
|
|
34
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "svelte-toggle-switch",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.30",
|
|
13
|
+
"svelte": "^3.44.0",
|
|
14
|
+
"vite": "^2.9.9"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/ishansasika/svelte-toggle-switch"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"svelte",
|
|
22
|
+
"switch",
|
|
23
|
+
"toggle",
|
|
24
|
+
"svelte switch",
|
|
25
|
+
"toggle switch",
|
|
26
|
+
"svelte-toggle-switch"
|
|
27
|
+
],
|
|
28
|
+
"author": "Ishan Karunaratne <ishansasika@gmail.com> (https://ishansasika.mn.co/)",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"homepage": "https://github.com/ishansasika/svelte-toggle-switch#readme"
|
|
31
|
+
}
|
|
Binary file
|
package/src/App.svelte
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Switch from './lib/Switch.svelte'
|
|
3
|
+
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<main>
|
|
7
|
+
<Switch label="Enable dark mode" fontSize={24} design="slider"/>
|
|
8
|
+
</main>
|
|
9
|
+
|
|
10
|
+
<style>
|
|
11
|
+
:root {
|
|
12
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
|
13
|
+
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
main {
|
|
17
|
+
text-align: center;
|
|
18
|
+
padding: 1em;
|
|
19
|
+
margin: 0 auto;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
</style>
|
|
Binary file
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
|
|
3
|
+
export let label;
|
|
4
|
+
export let design = 'inner label'
|
|
5
|
+
export let options = [];
|
|
6
|
+
export let fontSize = 16;
|
|
7
|
+
export let value = 'on';
|
|
8
|
+
|
|
9
|
+
let checked = true;
|
|
10
|
+
const uniqueID = Math.floor(Math.random() * 100)
|
|
11
|
+
|
|
12
|
+
function handleClick(event){
|
|
13
|
+
const target = event.target
|
|
14
|
+
|
|
15
|
+
const state = target.getAttribute('aria-checked')
|
|
16
|
+
|
|
17
|
+
checked = state === 'true' ? false : true
|
|
18
|
+
|
|
19
|
+
value = checked === true ? 'on' : 'off'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const slugify = (str = "") =>
|
|
23
|
+
str.toLowerCase().replace(/ /g, "-").replace(/\./g, "");
|
|
24
|
+
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
{#if design == 'inner'}
|
|
28
|
+
<div class="s s--inner">
|
|
29
|
+
<span id={`switch-${uniqueID}`}>{label}</span>
|
|
30
|
+
<button
|
|
31
|
+
role="switch"
|
|
32
|
+
aria-checked={checked}
|
|
33
|
+
aria-labelledby={`switch-${uniqueID}`}
|
|
34
|
+
on:click={handleClick}>
|
|
35
|
+
<span>on</span>
|
|
36
|
+
<span>off</span>
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
{:else if design == 'slider'}
|
|
40
|
+
<div class="s s--slider" style="font-size:{fontSize}px">
|
|
41
|
+
<span id={`switch-${uniqueID}`}>{label}</span>
|
|
42
|
+
<button
|
|
43
|
+
role="switch"
|
|
44
|
+
aria-checked={checked}
|
|
45
|
+
aria-labelledby={`switch-${uniqueID}`}
|
|
46
|
+
on:click={handleClick}>
|
|
47
|
+
</button>
|
|
48
|
+
</div>
|
|
49
|
+
{:else}
|
|
50
|
+
<div class="s s--multi">
|
|
51
|
+
<div role='radiogroup'
|
|
52
|
+
class="group-container"
|
|
53
|
+
aria-labelledby={`label-${uniqueID}`}
|
|
54
|
+
style="font-size:{fontSize}px"
|
|
55
|
+
id={`group-${uniqueID}`}>
|
|
56
|
+
<div class='legend' id={`label-${uniqueID}`}>{label}</div>
|
|
57
|
+
{#each options as option}
|
|
58
|
+
<input type="radio" id={`${option}-${uniqueID}`} value={option} bind:group={value}>
|
|
59
|
+
<label for={`${option}-${uniqueID}`}>
|
|
60
|
+
{option}
|
|
61
|
+
</label>
|
|
62
|
+
{/each}
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
{/if}
|
|
67
|
+
|
|
68
|
+
<style>
|
|
69
|
+
:root {
|
|
70
|
+
--accent-color: CornflowerBlue;
|
|
71
|
+
--gray: #ccc;
|
|
72
|
+
}
|
|
73
|
+
/* Inner Design Option */
|
|
74
|
+
.s--inner button {
|
|
75
|
+
padding: 0.5em;
|
|
76
|
+
background-color: #fff;
|
|
77
|
+
border: 1px solid var(--gray);
|
|
78
|
+
}
|
|
79
|
+
[role='switch'][aria-checked='true'] :first-child,
|
|
80
|
+
[role='switch'][aria-checked='false'] :last-child {
|
|
81
|
+
display: none;
|
|
82
|
+
color: #fff;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.s--inner button span {
|
|
86
|
+
user-select: none;
|
|
87
|
+
pointer-events:none;
|
|
88
|
+
padding: 0.25em;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.s--inner button:focus {
|
|
92
|
+
outline: var(--accent-color) solid 1px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Slider Design Option */
|
|
96
|
+
|
|
97
|
+
.s--slider {
|
|
98
|
+
display: flex;
|
|
99
|
+
align-items: center;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.s--slider button {
|
|
103
|
+
width: 3em;
|
|
104
|
+
height: 1.6em;
|
|
105
|
+
position: relative;
|
|
106
|
+
margin: 0 0 0 0.5em;
|
|
107
|
+
background: var(--gray);
|
|
108
|
+
border: none;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.s--slider button::before {
|
|
112
|
+
content: '';
|
|
113
|
+
position: absolute;
|
|
114
|
+
width: 1.3em;
|
|
115
|
+
height: 1.3em;
|
|
116
|
+
background: #fff;
|
|
117
|
+
top: 0.13em;
|
|
118
|
+
right: 1.5em;
|
|
119
|
+
transition: transform 0.3s;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.s--slider button[aria-checked='true']{
|
|
123
|
+
background-color: var(--accent-color)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.s--slider button[aria-checked='true']::before{
|
|
127
|
+
transform: translateX(1.3em);
|
|
128
|
+
transition: transform 0.3s;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.s--slider button:focus {
|
|
132
|
+
box-shadow: 0 0px 0px 1px var(--accent-color);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Multi Design Option */
|
|
136
|
+
|
|
137
|
+
/* Based on suggestions from Sara Soueidan https://www.sarasoueidan.com/blog/toggle-switch-design/
|
|
138
|
+
and this example from Scott O'hara https://codepen.io/scottohara/pen/zLZwNv */
|
|
139
|
+
|
|
140
|
+
.s--multi .group-container {
|
|
141
|
+
border: none;
|
|
142
|
+
padding: 0;
|
|
143
|
+
white-space: nowrap;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* .s--multi legend {
|
|
147
|
+
font-size: 2px;
|
|
148
|
+
opacity: 0;
|
|
149
|
+
position: absolute;
|
|
150
|
+
} */
|
|
151
|
+
|
|
152
|
+
.s--multi label {
|
|
153
|
+
display: inline-block;
|
|
154
|
+
line-height: 1.6;
|
|
155
|
+
position: relative;
|
|
156
|
+
z-index: 2;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.s--multi input {
|
|
160
|
+
opacity: 0;
|
|
161
|
+
position: absolute;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.s--multi label:first-of-type {
|
|
165
|
+
padding-right: 5em;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.s--multi label:last-child {
|
|
169
|
+
margin-left: -5em;
|
|
170
|
+
padding-left: 5em;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.s--multi:focus-within label:first-of-type:after {
|
|
174
|
+
box-shadow: 0 0px 8px var(--accent-color);
|
|
175
|
+
border-radius: 1.5em;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
/* making the switch UI. */
|
|
181
|
+
.s--multi label:first-of-type:before,
|
|
182
|
+
.s--multi label:first-of-type:after {
|
|
183
|
+
content: "";
|
|
184
|
+
height: 1.25em;
|
|
185
|
+
overflow: hidden;
|
|
186
|
+
pointer-events: none;
|
|
187
|
+
position: absolute;
|
|
188
|
+
vertical-align: middle;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.s--multi label:first-of-type:before {
|
|
192
|
+
border-radius: 100%;
|
|
193
|
+
z-index: 2;
|
|
194
|
+
position: absolute;
|
|
195
|
+
width: 1.2em;
|
|
196
|
+
height: 1.2em;
|
|
197
|
+
background: #fff;
|
|
198
|
+
top: 0.2em;
|
|
199
|
+
right: 1.2em;
|
|
200
|
+
transition: transform 0.3s;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.s--multi label:first-of-type:after {
|
|
204
|
+
background: var(--accent-color);
|
|
205
|
+
border-radius: 1em;
|
|
206
|
+
margin: 0 1em;
|
|
207
|
+
transition: background .2s ease-in-out;
|
|
208
|
+
width: 3em;
|
|
209
|
+
height: 1.6em;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.s--multi input:first-of-type:checked ~ label:first-of-type:after {
|
|
213
|
+
background: var(--gray);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.s--multi input:first-of-type:checked ~ label:first-of-type:before {
|
|
217
|
+
transform: translateX(-1.4em);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.s--multi input:last-of-type:checked ~ label:last-of-type {
|
|
221
|
+
z-index: 1;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.s--multi input:focus {
|
|
225
|
+
box-shadow: 0 0px 8px var(--accent-color);
|
|
226
|
+
border-radius: 1.5em;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* gravy */
|
|
230
|
+
|
|
231
|
+
/* Inner Design Option */
|
|
232
|
+
[role='switch'][aria-checked='true'] :first-child,
|
|
233
|
+
[role='switch'][aria-checked='false'] :last-child {
|
|
234
|
+
border-radius: 0.25em;
|
|
235
|
+
background: var(--accent-color);
|
|
236
|
+
display: inline-block;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.s--inner button:focus {
|
|
240
|
+
box-shadow: 0 0px 8px var(--accent-color);
|
|
241
|
+
border-radius: 0.1em;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/* Slider Design Option */
|
|
245
|
+
.s--slider button {
|
|
246
|
+
border-radius: 1.5em;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.s--slider button::before {
|
|
250
|
+
border-radius: 100%;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.s--slider button:focus {
|
|
254
|
+
box-shadow: 0 0px 8px var(--accent-color);
|
|
255
|
+
border-radius: 1.5em;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
</style>
|
package/src/main.js
ADDED