@sierra-95/svelte-scaffold 1.1.1 → 1.1.3

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.
@@ -0,0 +1,85 @@
1
+ <script lang="ts">
2
+ const {
3
+ minLength = 8,
4
+ new_password = $bindable(""),
5
+ confirm_password = $bindable("")
6
+ }=$props();
7
+
8
+ type PasswordStrengthResult = {
9
+ strength: "Weak" | "Medium" | "Strong";
10
+ suggestions: string[];
11
+ score: number;
12
+ }
13
+
14
+ let results: PasswordStrengthResult = $state({
15
+ strength: "Weak",
16
+ suggestions: [],
17
+ score: 0
18
+ })
19
+
20
+ const strengthColors = {
21
+ Weak: "var(--error-bg)",
22
+ Medium: "var(--warning-bg)",
23
+ Strong: "var(--primary-bg)"
24
+ } as const;
25
+
26
+ function passwordStrength(password: string): PasswordStrengthResult {
27
+ let suggestions: string[] = [];
28
+ let score = 0;
29
+
30
+ if (password.length >= minLength) score++;
31
+ else suggestions.push(`Use at least ${minLength} characters`);
32
+
33
+ if (/[a-z]/.test(password)) score++;
34
+ else suggestions.push("Add lowercase letters");
35
+
36
+ if (/[A-Z]/.test(password)) score++;
37
+ else suggestions.push("Add uppercase letters");
38
+
39
+ if (/[0-9]/.test(password)) score++;
40
+ else suggestions.push("Include numbers");
41
+
42
+ if (/[^A-Za-z0-9]/.test(password)) score++;
43
+ else suggestions.push("Use special characters");
44
+
45
+ let strength: PasswordStrengthResult["strength"] =
46
+ score <= 2 ? "Weak" :
47
+ score <= 4 ? "Medium" :
48
+ "Strong";
49
+ return { strength, suggestions, score };
50
+ }
51
+
52
+ function passwordsMatch() {
53
+ return new_password && confirm_password && new_password === confirm_password;
54
+ }
55
+ $effect(()=>{
56
+ if (new_password) {
57
+ const { strength, suggestions, score } = passwordStrength(new_password);
58
+ results = { strength, suggestions, score };
59
+ }
60
+ })
61
+ </script>
62
+ {#if new_password}
63
+ <p>
64
+ <span style="font-weight: bold;">Score: </span>
65
+ <span style="color: {strengthColors[results.strength]}">{results.score}</span><span style="color: var(--text-secondary);">/5</span>
66
+ <span style="color: {strengthColors[results.strength]}">{results.strength}</span>
67
+ </p>
68
+
69
+ {#if results.suggestions.length}
70
+ <p>
71
+ <span style="font-weight: bold;">Suggestions: </span>
72
+ <span style="color: var(--text-secondary);">
73
+ {#each results.suggestions as tip, index}
74
+ {tip}{index < results.suggestions.length - 1 ? ", " : ""}
75
+ {/each}
76
+ </span>
77
+ </p>
78
+ {/if}
79
+ {/if}
80
+
81
+ {#if confirm_password}
82
+ {#if !passwordsMatch()}
83
+ <p style="color: var(--error-bg);">Passwords do not match</p>
84
+ {/if}
85
+ {/if}
@@ -0,0 +1,7 @@
1
+ declare const PasswordStrength: import("svelte").Component<{
2
+ minLength?: number;
3
+ new_password?: string;
4
+ confirm_password?: string;
5
+ }, {}, "new_password" | "confirm_password">;
6
+ type PasswordStrength = ReturnType<typeof PasswordStrength>;
7
+ export default PasswordStrength;
@@ -24,6 +24,7 @@
24
24
  <div style="display: flex;">
25
25
  {#each tabs as tab}
26
26
  <button
27
+ type="button"
27
28
  class="tab {active === tab.key ? 'active' : ''}"
28
29
  onclick={() => active = tab.key}
29
30
  >
@@ -46,6 +46,7 @@
46
46
 
47
47
  {#snippet Color(color:string)}
48
48
  <button
49
+ type="button"
49
50
  aria-label={`Select color: ${color}`}
50
51
  class="color-swatch"
51
52
  style="background-color: {color};"
@@ -43,7 +43,7 @@
43
43
  {$modalStore.confirmText}
44
44
  </Button>
45
45
  {#if $modalStore.cancelText}
46
- <button onclick={close}
46
+ <button type="button" onclick={close}
47
47
  >{$modalStore.cancelText}
48
48
  </button>
49
49
  {/if}
@@ -82,6 +82,6 @@
82
82
  <Input underline label="Edit link URL" id="link-url" bind:value={url}/>
83
83
  {/snippet}
84
84
 
85
- <button aria-label="Link Button" on:click={ editor.isActive('link')? updateLink : newLink} title="Add/Edit Link">
85
+ <button type="button" aria-label="Link Button" on:click={ editor.isActive('link')? updateLink : newLink} title="Add/Edit Link">
86
86
  <i class="fa fa-link"></i>
87
87
  </button>
@@ -20,6 +20,7 @@
20
20
  <div style="display: flex; gap: 0.5rem">
21
21
  {#each actions as { name, icon }}
22
22
  <button
23
+ type="button"
23
24
  aria-label="Text Formatting: {name}"
24
25
  title={name.charAt(0).toUpperCase() + name.slice(1)}
25
26
  on:click={() => runToggle(name)}
@@ -38,7 +38,7 @@
38
38
  {#if editor}
39
39
  <DropdownContainer bind:open>
40
40
  {#snippet dropdownTrigger()}
41
- <button aria-label="Heading Options" on:click={() => (open = !open)} style="display: flex; align-items: center; gap: 4px;">
41
+ <button type="button" aria-label="Heading Options" on:click={() => (open = !open)} style="display: flex; align-items: center; gap: 4px;">
42
42
  <h5 style="font-weight: bold;">H{editor.getAttributes('heading').level}</h5>
43
43
  <i class="fa fa-chevron-down {open ? 'active' : ''}"></i>
44
44
  </button>
@@ -12,10 +12,10 @@
12
12
  }
13
13
  </script>
14
14
 
15
- <button on:click={undo} aria-label="Undo" title="Undo" disabled={!editor.can().undo()}>
15
+ <button type="button" on:click={undo} aria-label="Undo" title="Undo" disabled={!editor.can().undo()}>
16
16
  <i class="fa fa-undo"></i>
17
17
  </button>
18
18
 
19
- <button on:click={redo} aria-label="Redo" title="Redo" disabled={!editor.can().redo()}>
19
+ <button type="button" on:click={redo} aria-label="Redo" title="Redo" disabled={!editor.can().redo()}>
20
20
  <i class="fa fa-redo"></i>
21
21
  </button>
@@ -89,7 +89,7 @@
89
89
  {/snippet}
90
90
  <DropdownContainer bind:open={openDropdown} width="150px">
91
91
  {#snippet dropdownTrigger()}
92
- <button aria-label="Insert Image" title="Insert File" on:click={() => openDropdown = !openDropdown}>
92
+ <button type="button" aria-label="Insert Image" title="Insert File" on:click={() => openDropdown = !openDropdown}>
93
93
  <i class="fa fa-file"></i>
94
94
  </button>
95
95
  {/snippet}
@@ -13,6 +13,7 @@
13
13
 
14
14
  <div style="display: flex; gap: 0.5rem">
15
15
  <button
16
+ type="button"
16
17
  aria-label="Bullet List"
17
18
  title="Bullet List"
18
19
  on:click={toggleBullet}
@@ -21,6 +22,7 @@
21
22
  </button>
22
23
 
23
24
  <button
25
+ type="button"
24
26
  aria-label="Ordered List"
25
27
  title="Ordered List"
26
28
  on:click={toggleOrdered}
@@ -35,7 +35,7 @@
35
35
  {#if editor}
36
36
  <DropdownContainer bind:open>
37
37
  {#snippet dropdownTrigger()}
38
- <button aria-label="Text Align Options" on:click={() => (open = !open)}>
38
+ <button type="button" aria-label="Text Align Options" on:click={() => (open = !open)}>
39
39
  <i class="fa-solid fa-align-{currentAlignment.value}"></i>
40
40
  </button>
41
41
  {/snippet}
@@ -33,7 +33,7 @@
33
33
 
34
34
  <main id="editor-text-color" style="display: flex; gap: 0.5rem; align-items: center;">
35
35
  {#snippet TriggerText()}
36
- <button aria-label="Text Color" title="Color" onclick={() => textColorDropdown = !textColorDropdown}>
36
+ <button type="button" aria-label="Text Color" title="Color" onclick={() => textColorDropdown = !textColorDropdown}>
37
37
  <i class="fa fa-font"></i>
38
38
  <div bind:this={textColor} style="height: 3px; border-radius: 0.3125rem;"></div>
39
39
  </button>
@@ -42,6 +42,7 @@
42
42
 
43
43
  <div style="display: flex;">
44
44
  <button
45
+ type="button"
45
46
  aria-label="Highlight"
46
47
  title="Highlight"
47
48
  class="{editor.isActive('highlight') ? 'active' : ''}"
@@ -51,7 +52,7 @@
51
52
  <i class="fa fa-font"></i>
52
53
  </button>
53
54
  {#snippet TriggerHighlight()}
54
- <button id="color-picker-trigger" aria-label="Highlight Color" onclick={() => highlightDropdown = !highlightDropdown}>
55
+ <button type="button" id="color-picker-trigger" aria-label="Highlight Color" onclick={() => highlightDropdown = !highlightDropdown}>
55
56
  <i class="fa fa-chevron-down {highlightDropdown ? 'active' : ''}"></i>
56
57
  </button>
57
58
  {/snippet}
@@ -30,6 +30,7 @@
30
30
  {/snippet}
31
31
 
32
32
  <button
33
+ type="button"
33
34
  aria-label="Youtube URL"
34
35
  on:click={() => triggerModal()}
35
36
  title="Insert YouTube video">
package/dist/index.d.ts CHANGED
@@ -18,6 +18,7 @@ export { default as SearchBar } from './Core/components/Form/Input/SearchBar/sea
18
18
  export { default as TextArea } from './Core/components/Form/Input/TextArea/textarea.svelte';
19
19
  export { default as DateInput } from './Core/components/Form/Input/Date/date.svelte';
20
20
  export { default as TimeInput } from './Core/components/Form/Input/Time/time.svelte';
21
+ export { default as PasswordStrength } from './Core/components/Form/Input/PasswordStrength/passwordStrength.svelte';
21
22
  export { default as PreviewAudio } from './Core/components/others/Previews/Audio/audio.svelte';
22
23
  export { default as PreviewImage } from './Core/components/others/Previews/Image/image.svelte';
23
24
  export { default as PreviewVideo } from './Core/components/others/Previews/Video/video.svelte';
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ export { default as SearchBar } from './Core/components/Form/Input/SearchBar/sea
22
22
  export { default as TextArea } from './Core/components/Form/Input/TextArea/textarea.svelte';
23
23
  export { default as DateInput } from './Core/components/Form/Input/Date/date.svelte';
24
24
  export { default as TimeInput } from './Core/components/Form/Input/Time/time.svelte';
25
+ export { default as PasswordStrength } from './Core/components/Form/Input/PasswordStrength/passwordStrength.svelte';
25
26
  //Previews
26
27
  export { default as PreviewAudio } from './Core/components/others/Previews/Audio/audio.svelte';
27
28
  export { default as PreviewImage } from './Core/components/others/Previews/Image/image.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sierra-95/svelte-scaffold",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",