negodesign 0.0.74 → 0.0.76
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/dist/components/pages/security/auth/PageAuth01.svelte +65 -0
- package/dist/components/pages/security/auth/PageAuth01.svelte.d.ts +17 -0
- package/dist/components/pages/security/auth/PageAuth02.svelte +45 -0
- package/dist/components/pages/security/auth/PageAuth02.svelte.d.ts +17 -0
- package/dist/components/pages/security/auth/PageAuth03.svelte +45 -0
- package/dist/components/pages/security/auth/PageAuth03.svelte.d.ts +17 -0
- package/dist/components/pages/security/login/01/ui/PageLogin01.svelte +15 -40
- package/dist/components/pages/security/login/02/ui/LoginCard02.svelte +15 -4
- package/dist/components/pages/security/login/02/ui/PageLogin02.svelte +15 -20
- package/dist/components/pages/security/login/03/ui/LoginCard03.svelte +34 -16
- package/dist/components/pages/security/login/03/ui/PageLogin03.svelte +15 -20
- package/dist/components/pages/security/register/01/ui/PageRegister01.svelte +64 -0
- package/dist/components/pages/security/register/01/ui/PageRegister01.svelte.d.ts +3 -0
- package/dist/components/pages/security/register/01/ui/RegisterCard.svelte +100 -0
- package/dist/components/pages/security/register/01/ui/RegisterCard.svelte.d.ts +12 -0
- package/dist/components/pages/security/register/02/ui/PageRegister02.svelte +76 -0
- package/dist/components/pages/security/register/02/ui/PageRegister02.svelte.d.ts +4 -0
- package/dist/components/pages/security/register/02/ui/RegisterCard02.svelte +98 -0
- package/dist/components/pages/security/register/02/ui/RegisterCard02.svelte.d.ts +12 -0
- package/dist/components/pages/security/register/03/ui/PageRegister03.svelte +76 -0
- package/dist/components/pages/security/register/03/ui/PageRegister03.svelte.d.ts +4 -0
- package/dist/components/pages/security/register/03/ui/RegisterCard03.svelte +103 -0
- package/dist/components/pages/security/register/03/ui/RegisterCard03.svelte.d.ts +12 -0
- package/dist/components/pages/security/register/FormRegister.svelte +120 -0
- package/dist/components/pages/security/register/FormRegister.svelte.d.ts +8 -0
- package/dist/components/pages/security/register/PageRegister.svelte +30 -0
- package/dist/components/pages/security/register/PageRegister.svelte.d.ts +8 -0
- package/dist/components/pages/security/register/types.d.ts +51 -0
- package/dist/components/pages/security/register/types.js +1 -0
- package/dist/components/ui/form/Form.svelte +171 -0
- package/dist/components/ui/form/Form.svelte.d.ts +4 -0
- package/dist/components/ui/form/types.d.ts +78 -0
- package/dist/components/ui/form/types.js +1 -0
- package/dist/components/ui/form/ui/input-badges.svelte +214 -0
- package/dist/components/ui/form/ui/input-badges.svelte.d.ts +14 -0
- package/dist/components/ui/form/ui/input-checkbox.svelte +86 -0
- package/dist/components/ui/form/ui/input-checkbox.svelte.d.ts +17 -0
- package/dist/components/ui/form/ui/input-radio.svelte +82 -0
- package/dist/components/ui/form/ui/input-radio.svelte.d.ts +17 -0
- package/dist/components/ui/form/ui/input-select.svelte +195 -0
- package/dist/components/ui/form/ui/input-select.svelte.d.ts +17 -0
- package/dist/components/ui/form/ui/input-textarea.svelte +61 -0
- package/dist/components/ui/form/ui/input-textarea.svelte.d.ts +13 -0
- package/dist/components/ui/form/ui/input-toggle.svelte +89 -0
- package/dist/components/ui/form/ui/input-toggle.svelte.d.ts +11 -0
- package/dist/components/ui/modal/badge/index.d.ts +3 -0
- package/dist/components/ui/modal/badge/index.js +2 -0
- package/dist/components/ui/modal/badge/types.d.ts +35 -0
- package/dist/components/ui/modal/badge/types.js +1 -0
- package/dist/components/ui/modal/badge/ui/ModalBadgeSelection.svelte +87 -0
- package/dist/components/ui/modal/badge/ui/ModalBadgeSelection.svelte.d.ts +4 -0
- package/dist/components/ui/modal/core/index.d.ts +3 -0
- package/dist/components/ui/modal/core/index.js +2 -0
- package/dist/components/ui/modal/core/types.d.ts +84 -0
- package/dist/components/ui/modal/core/types.js +1 -0
- package/dist/components/ui/modal/core/ui/ModalCore.svelte +132 -0
- package/dist/components/ui/modal/core/ui/ModalCore.svelte.d.ts +4 -0
- package/dist/components/ui/modal/feedback/index.d.ts +3 -0
- package/dist/components/ui/modal/feedback/index.js +2 -0
- package/dist/components/ui/modal/feedback/types.d.ts +32 -0
- package/dist/components/ui/modal/feedback/types.js +1 -0
- package/dist/components/ui/modal/feedback/ui/ModalFeedback.svelte +135 -0
- package/dist/components/ui/modal/feedback/ui/ModalFeedback.svelte.d.ts +4 -0
- package/dist/components/ui/modal/form/index.d.ts +3 -0
- package/dist/components/ui/modal/form/index.js +2 -0
- package/dist/components/ui/modal/form/types.d.ts +38 -0
- package/dist/components/ui/modal/form/types.js +1 -0
- package/dist/components/ui/modal/form/ui/ModalForm.svelte +67 -0
- package/dist/components/ui/modal/form/ui/ModalForm.svelte.d.ts +4 -0
- package/dist/components/ui/modal/grid/index.d.ts +5 -0
- package/dist/components/ui/modal/grid/index.js +4 -0
- package/dist/components/ui/modal/grid/types.d.ts +51 -0
- package/dist/components/ui/modal/grid/types.js +1 -0
- package/dist/components/ui/modal/grid/ui/01/ModalGridSelection01.svelte +83 -0
- package/dist/components/ui/modal/grid/ui/01/ModalGridSelection01.svelte.d.ts +4 -0
- package/dist/components/ui/modal/grid/ui/02/ModalGridSelection02.svelte +146 -0
- package/dist/components/ui/modal/grid/ui/02/ModalGridSelection02.svelte.d.ts +4 -0
- package/dist/components/ui/modal/grid/ui/ModalGridSelection.svelte +60 -0
- package/dist/components/ui/modal/grid/ui/ModalGridSelection.svelte.d.ts +4 -0
- package/dist/components/ui/modal/map/index.d.ts +3 -0
- package/dist/components/ui/modal/map/index.js +2 -0
- package/dist/components/ui/modal/map/types.d.ts +48 -0
- package/dist/components/ui/modal/map/types.js +1 -0
- package/dist/components/ui/modal/map/ui/ModalMap.svelte +187 -0
- package/dist/components/ui/modal/map/ui/ModalMap.svelte.d.ts +4 -0
- package/dist/components/ui/modal/notification/index.d.ts +3 -0
- package/dist/components/ui/modal/notification/index.js +2 -0
- package/dist/components/ui/modal/notification/types.d.ts +26 -0
- package/dist/components/ui/modal/notification/types.js +1 -0
- package/dist/components/ui/modal/notification/ui/ModalNotification.svelte +65 -0
- package/dist/components/ui/modal/notification/ui/ModalNotification.svelte.d.ts +4 -0
- package/dist/components/ui/modal/share/index.d.ts +3 -0
- package/dist/components/ui/modal/share/index.js +2 -0
- package/dist/components/ui/modal/share/types.d.ts +47 -0
- package/dist/components/ui/modal/share/types.js +1 -0
- package/dist/components/ui/modal/share/ui/ModalShareSelection.svelte +156 -0
- package/dist/components/ui/modal/share/ui/ModalShareSelection.svelte.d.ts +4 -0
- package/dist/components/ui/modal/upload/index.d.ts +3 -0
- package/dist/components/ui/modal/upload/index.js +2 -0
- package/dist/components/ui/modal/upload/types.d.ts +79 -0
- package/dist/components/ui/modal/upload/types.js +1 -0
- package/dist/components/ui/modal/upload/ui/ModalUpload.svelte +268 -0
- package/dist/components/ui/modal/upload/ui/ModalUpload.svelte.d.ts +4 -0
- package/dist/components/ui/section/Section01.svelte +90 -0
- package/dist/components/ui/section/Section01.svelte.d.ts +4 -0
- package/dist/components/ui/section/Section02.svelte +68 -0
- package/dist/components/ui/section/Section02.svelte.d.ts +4 -0
- package/dist/components/ui/section/Section03.svelte +52 -0
- package/dist/components/ui/section/Section03.svelte.d.ts +4 -0
- package/dist/components/ui/section/index.d.ts +4 -0
- package/dist/components/ui/section/index.js +3 -0
- package/dist/components/ui/section/types.d.ts +46 -0
- package/dist/components/ui/section/types.js +1 -0
- package/dist/docs/DocsSidebar.svelte +58 -1
- package/dist/docs/components.d.ts +1 -1
- package/dist/docs/components.js +968 -0
- package/dist/globals.css +360 -0
- package/dist/index.d.ts +185 -0
- package/dist/index.js +185 -0
- package/dist/types/index.d.ts +53 -0
- package/package.json +1 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Label } from "../../label";
|
|
3
|
+
import { cn } from "../../../../utils";
|
|
4
|
+
import type { InputLabelProps } from "../data/InputLabel.svelte";
|
|
5
|
+
|
|
6
|
+
type SelectOption = { value: string; label: string };
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
label,
|
|
10
|
+
isLabel = false,
|
|
11
|
+
value = $bindable(""),
|
|
12
|
+
disabled = false,
|
|
13
|
+
required = false,
|
|
14
|
+
placeholder = "Select an option",
|
|
15
|
+
options = [],
|
|
16
|
+
multiple = false,
|
|
17
|
+
class: className,
|
|
18
|
+
...restProps
|
|
19
|
+
}: InputLabelProps & {
|
|
20
|
+
value?: string | string[];
|
|
21
|
+
options?: SelectOption[];
|
|
22
|
+
multiple?: boolean;
|
|
23
|
+
placeholder?: string;
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
required?: boolean;
|
|
26
|
+
class?: string;
|
|
27
|
+
} = $props();
|
|
28
|
+
|
|
29
|
+
let isOpen = $state(false);
|
|
30
|
+
let selectRef = $state<HTMLDivElement | null>(null);
|
|
31
|
+
|
|
32
|
+
function handleSelect(option: SelectOption) {
|
|
33
|
+
if (multiple) {
|
|
34
|
+
const arr = Array.isArray(value) ? value : [];
|
|
35
|
+
const idx = arr.indexOf(option.value);
|
|
36
|
+
if (idx >= 0) {
|
|
37
|
+
value = arr.filter((v) => v !== option.value);
|
|
38
|
+
} else {
|
|
39
|
+
value = [...arr, option.value];
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
value = option.value;
|
|
43
|
+
isOpen = false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function isSelected(option: SelectOption): boolean {
|
|
48
|
+
if (multiple) {
|
|
49
|
+
return Array.isArray(value) && value.includes(option.value);
|
|
50
|
+
}
|
|
51
|
+
return value === option.value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getDisplayText(): string {
|
|
55
|
+
if (multiple) {
|
|
56
|
+
const arr = Array.isArray(value) ? value : [];
|
|
57
|
+
if (arr.length === 0) return placeholder;
|
|
58
|
+
return arr
|
|
59
|
+
.map((v) => options.find((o) => o.value === v)?.label ?? v)
|
|
60
|
+
.join(", ");
|
|
61
|
+
}
|
|
62
|
+
return options.find((o) => o.value === value)?.label ?? placeholder;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function handleClickOutside(e: MouseEvent) {
|
|
66
|
+
if (selectRef && !selectRef.contains(e.target as Node)) {
|
|
67
|
+
isOpen = false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<svelte:window onclick={handleClickOutside} />
|
|
73
|
+
|
|
74
|
+
{#if isLabel}
|
|
75
|
+
<div class="flex w-full flex-col gap-3">
|
|
76
|
+
{#if label}
|
|
77
|
+
<Label>{label}</Label>
|
|
78
|
+
{/if}
|
|
79
|
+
<div bind:this={selectRef} class={cn("relative", className)}>
|
|
80
|
+
<button
|
|
81
|
+
type="button"
|
|
82
|
+
{disabled}
|
|
83
|
+
class="flex h-10 w-full items-center justify-between rounded-md border border-input bg-card px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
|
84
|
+
onclick={() => (isOpen = !isOpen)}
|
|
85
|
+
>
|
|
86
|
+
<span class={cn(!value && "text-muted-foreground")}>
|
|
87
|
+
{getDisplayText()}
|
|
88
|
+
</span>
|
|
89
|
+
<svg
|
|
90
|
+
class={cn("size-4 shrink-0 opacity-50 transition-transform", isOpen && "rotate-180")}
|
|
91
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
92
|
+
viewBox="0 0 24 24"
|
|
93
|
+
fill="none"
|
|
94
|
+
stroke="currentColor"
|
|
95
|
+
stroke-width="2"
|
|
96
|
+
stroke-linecap="round"
|
|
97
|
+
stroke-linejoin="round"
|
|
98
|
+
>
|
|
99
|
+
<path d="m6 9 6 6 6-6" />
|
|
100
|
+
</svg>
|
|
101
|
+
</button>
|
|
102
|
+
|
|
103
|
+
{#if isOpen}
|
|
104
|
+
<div class="absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md border border-border bg-card shadow-md">
|
|
105
|
+
{#each options as option (option.value)}
|
|
106
|
+
<button
|
|
107
|
+
type="button"
|
|
108
|
+
class={cn(
|
|
109
|
+
"flex w-full items-center px-3 py-2 text-sm transition-colors hover:bg-muted",
|
|
110
|
+
isSelected(option) && "bg-muted font-medium"
|
|
111
|
+
)}
|
|
112
|
+
onclick={() => handleSelect(option)}
|
|
113
|
+
>
|
|
114
|
+
{#if multiple}
|
|
115
|
+
<span
|
|
116
|
+
class={cn(
|
|
117
|
+
"mr-2 flex size-4 items-center justify-center rounded border",
|
|
118
|
+
isSelected(option)
|
|
119
|
+
? "border-primary bg-primary text-primary-foreground"
|
|
120
|
+
: "border-input"
|
|
121
|
+
)}
|
|
122
|
+
>
|
|
123
|
+
{#if isSelected(option)}
|
|
124
|
+
<svg class="size-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
|
|
125
|
+
<path d="M20 6 9 17l-5-5" />
|
|
126
|
+
</svg>
|
|
127
|
+
{/if}
|
|
128
|
+
</span>
|
|
129
|
+
{/if}
|
|
130
|
+
{option.label}
|
|
131
|
+
</button>
|
|
132
|
+
{/each}
|
|
133
|
+
</div>
|
|
134
|
+
{/if}
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
{:else}
|
|
138
|
+
<div bind:this={selectRef} class={cn("relative", className)}>
|
|
139
|
+
<button
|
|
140
|
+
type="button"
|
|
141
|
+
{disabled}
|
|
142
|
+
class="flex h-10 w-full items-center justify-between rounded-md border border-input bg-card px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
|
143
|
+
onclick={() => (isOpen = !isOpen)}
|
|
144
|
+
>
|
|
145
|
+
<span class={cn(!value && "text-muted-foreground")}>
|
|
146
|
+
{getDisplayText()}
|
|
147
|
+
</span>
|
|
148
|
+
<svg
|
|
149
|
+
class={cn("size-4 shrink-0 opacity-50 transition-transform", isOpen && "rotate-180")}
|
|
150
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
151
|
+
viewBox="0 0 24 24"
|
|
152
|
+
fill="none"
|
|
153
|
+
stroke="currentColor"
|
|
154
|
+
stroke-width="2"
|
|
155
|
+
stroke-linecap="round"
|
|
156
|
+
stroke-linejoin="round"
|
|
157
|
+
>
|
|
158
|
+
<path d="m6 9 6 6 6-6" />
|
|
159
|
+
</svg>
|
|
160
|
+
</button>
|
|
161
|
+
|
|
162
|
+
{#if isOpen}
|
|
163
|
+
<div class="absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md border border-border bg-card shadow-md">
|
|
164
|
+
{#each options as option (option.value)}
|
|
165
|
+
<button
|
|
166
|
+
type="button"
|
|
167
|
+
class={cn(
|
|
168
|
+
"flex w-full items-center px-3 py-2 text-sm transition-colors hover:bg-muted",
|
|
169
|
+
isSelected(option) && "bg-muted font-medium"
|
|
170
|
+
)}
|
|
171
|
+
onclick={() => handleSelect(option)}
|
|
172
|
+
>
|
|
173
|
+
{#if multiple}
|
|
174
|
+
<span
|
|
175
|
+
class={cn(
|
|
176
|
+
"mr-2 flex size-4 items-center justify-center rounded border",
|
|
177
|
+
isSelected(option)
|
|
178
|
+
? "border-primary bg-primary text-primary-foreground"
|
|
179
|
+
: "border-input"
|
|
180
|
+
)}
|
|
181
|
+
>
|
|
182
|
+
{#if isSelected(option)}
|
|
183
|
+
<svg class="size-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
|
|
184
|
+
<path d="M20 6 9 17l-5-5" />
|
|
185
|
+
</svg>
|
|
186
|
+
{/if}
|
|
187
|
+
</span>
|
|
188
|
+
{/if}
|
|
189
|
+
{option.label}
|
|
190
|
+
</button>
|
|
191
|
+
{/each}
|
|
192
|
+
</div>
|
|
193
|
+
{/if}
|
|
194
|
+
</div>
|
|
195
|
+
{/if}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { InputLabelProps } from "../data/InputLabel.svelte";
|
|
2
|
+
type SelectOption = {
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
};
|
|
6
|
+
type $$ComponentProps = InputLabelProps & {
|
|
7
|
+
value?: string | string[];
|
|
8
|
+
options?: SelectOption[];
|
|
9
|
+
multiple?: boolean;
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
required?: boolean;
|
|
13
|
+
class?: string;
|
|
14
|
+
};
|
|
15
|
+
declare const InputSelect: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
16
|
+
type InputSelect = ReturnType<typeof InputSelect>;
|
|
17
|
+
export default InputSelect;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from "../../../../utils";
|
|
3
|
+
import { Label } from "../../label";
|
|
4
|
+
import type { HTMLTextareaAttributes } from "svelte/elements";
|
|
5
|
+
import type { WithElementRef } from "../../../../utils";
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
ref = $bindable(null),
|
|
9
|
+
value = $bindable(""),
|
|
10
|
+
label,
|
|
11
|
+
isLabel = false,
|
|
12
|
+
placeholder,
|
|
13
|
+
disabled = false,
|
|
14
|
+
required = false,
|
|
15
|
+
rows = 4,
|
|
16
|
+
class: className,
|
|
17
|
+
...restProps
|
|
18
|
+
}: WithElementRef<HTMLTextareaAttributes> & {
|
|
19
|
+
label?: string;
|
|
20
|
+
isLabel?: boolean;
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
required?: boolean;
|
|
24
|
+
rows?: number;
|
|
25
|
+
} = $props();
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
{#if isLabel}
|
|
29
|
+
<div class="flex w-full flex-col gap-2">
|
|
30
|
+
{#if label}
|
|
31
|
+
<Label>{label}</Label>
|
|
32
|
+
{/if}
|
|
33
|
+
<textarea
|
|
34
|
+
bind:this={ref}
|
|
35
|
+
bind:value
|
|
36
|
+
{placeholder}
|
|
37
|
+
{disabled}
|
|
38
|
+
{required}
|
|
39
|
+
{rows}
|
|
40
|
+
class={cn(
|
|
41
|
+
"dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 placeholder:text-muted-foreground flex min-h-[80px] w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm",
|
|
42
|
+
className
|
|
43
|
+
)}
|
|
44
|
+
{...restProps}
|
|
45
|
+
></textarea>
|
|
46
|
+
</div>
|
|
47
|
+
{:else}
|
|
48
|
+
<textarea
|
|
49
|
+
bind:this={ref}
|
|
50
|
+
bind:value
|
|
51
|
+
{placeholder}
|
|
52
|
+
{disabled}
|
|
53
|
+
{required}
|
|
54
|
+
{rows}
|
|
55
|
+
class={cn(
|
|
56
|
+
"dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 placeholder:text-muted-foreground flex min-h-[80px] w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm",
|
|
57
|
+
className
|
|
58
|
+
)}
|
|
59
|
+
{...restProps}
|
|
60
|
+
></textarea>
|
|
61
|
+
{/if}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { HTMLTextareaAttributes } from "svelte/elements";
|
|
2
|
+
import type { WithElementRef } from "../../../../utils";
|
|
3
|
+
type $$ComponentProps = WithElementRef<HTMLTextareaAttributes> & {
|
|
4
|
+
label?: string;
|
|
5
|
+
isLabel?: boolean;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
rows?: number;
|
|
10
|
+
};
|
|
11
|
+
declare const InputTextarea: import("svelte").Component<$$ComponentProps, {}, "ref" | "value">;
|
|
12
|
+
type InputTextarea = ReturnType<typeof InputTextarea>;
|
|
13
|
+
export default InputTextarea;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Label } from "../../label";
|
|
3
|
+
import { cn } from "../../../../utils";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
label,
|
|
7
|
+
isLabel = false,
|
|
8
|
+
value = $bindable(false),
|
|
9
|
+
disabled = false,
|
|
10
|
+
description,
|
|
11
|
+
class: className,
|
|
12
|
+
}: {
|
|
13
|
+
label?: string;
|
|
14
|
+
isLabel?: boolean;
|
|
15
|
+
value?: boolean;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
description?: string;
|
|
18
|
+
class?: string;
|
|
19
|
+
} = $props();
|
|
20
|
+
|
|
21
|
+
function toggle() {
|
|
22
|
+
if (disabled) return;
|
|
23
|
+
value = !value;
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
{#if isLabel}
|
|
28
|
+
<div class={cn("flex w-full flex-col gap-2", className)}>
|
|
29
|
+
<div class="flex items-center justify-between">
|
|
30
|
+
<div class="flex flex-col gap-0.5">
|
|
31
|
+
{#if label}
|
|
32
|
+
<Label>{label}</Label>
|
|
33
|
+
{/if}
|
|
34
|
+
{#if description}
|
|
35
|
+
<p class="text-xs text-muted-foreground">{description}</p>
|
|
36
|
+
{/if}
|
|
37
|
+
</div>
|
|
38
|
+
<button
|
|
39
|
+
type="button"
|
|
40
|
+
role="switch"
|
|
41
|
+
aria-checked={value}
|
|
42
|
+
aria-label={label ?? "Toggle"}
|
|
43
|
+
{disabled}
|
|
44
|
+
class={cn(
|
|
45
|
+
"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50",
|
|
46
|
+
value ? "bg-primary" : "bg-input"
|
|
47
|
+
)}
|
|
48
|
+
onclick={toggle}
|
|
49
|
+
>
|
|
50
|
+
<span
|
|
51
|
+
class={cn(
|
|
52
|
+
"pointer-events-none block size-5 rounded-full bg-background shadow-lg ring-0 transition-transform",
|
|
53
|
+
value ? "translate-x-5" : "translate-x-0"
|
|
54
|
+
)}
|
|
55
|
+
></span>
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
{:else}
|
|
60
|
+
<div class={cn("flex items-center justify-between", className)}>
|
|
61
|
+
<div class="flex flex-col gap-0.5">
|
|
62
|
+
{#if label}
|
|
63
|
+
<Label>{label}</Label>
|
|
64
|
+
{/if}
|
|
65
|
+
{#if description}
|
|
66
|
+
<p class="text-xs text-muted-foreground">{description}</p>
|
|
67
|
+
{/if}
|
|
68
|
+
</div>
|
|
69
|
+
<button
|
|
70
|
+
type="button"
|
|
71
|
+
role="switch"
|
|
72
|
+
aria-checked={value}
|
|
73
|
+
aria-label={label ?? "Toggle"}
|
|
74
|
+
{disabled}
|
|
75
|
+
class={cn(
|
|
76
|
+
"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50",
|
|
77
|
+
value ? "bg-primary" : "bg-input"
|
|
78
|
+
)}
|
|
79
|
+
onclick={toggle}
|
|
80
|
+
>
|
|
81
|
+
<span
|
|
82
|
+
class={cn(
|
|
83
|
+
"pointer-events-none block size-5 rounded-full bg-background shadow-lg ring-0 transition-transform",
|
|
84
|
+
value ? "translate-x-5" : "translate-x-0"
|
|
85
|
+
)}
|
|
86
|
+
></span>
|
|
87
|
+
</button>
|
|
88
|
+
</div>
|
|
89
|
+
{/if}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
label?: string;
|
|
3
|
+
isLabel?: boolean;
|
|
4
|
+
value?: boolean;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
description?: string;
|
|
7
|
+
class?: string;
|
|
8
|
+
};
|
|
9
|
+
declare const InputToggle: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
10
|
+
type InputToggle = ReturnType<typeof InputToggle>;
|
|
11
|
+
export default InputToggle;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ModelBadge } from "../core/types";
|
|
2
|
+
export type { ModelBadge } from "../core/types";
|
|
3
|
+
/**
|
|
4
|
+
* Props do componente ModalBadgeSelection — modal de seleção com badges/pills.
|
|
5
|
+
* Segunda variação do sistema de modais do NegoDesign.
|
|
6
|
+
* @property title - Título principal do modal.
|
|
7
|
+
* @property subtitle - Subtítulo/descrição abaixo do título.
|
|
8
|
+
* @property badges - Lista de badges/pills seleccionáveis.
|
|
9
|
+
* @property selectedBadge - Badge actualmente seleccionado.
|
|
10
|
+
* @property multiple - Permite seleção múltipla de badges.
|
|
11
|
+
* @property totalSteps - Número total de passos (para a progress bar).
|
|
12
|
+
* @property currentStep - Passo actual.
|
|
13
|
+
* @property isOpen - Controla a visibilidade do modal.
|
|
14
|
+
* @property onSelect - Chamado ao seleccionar um badge.
|
|
15
|
+
* @property onBack - Chamado ao clicar no botão "Back".
|
|
16
|
+
* @property onContinue - Chamado ao clicar no botão "Continue".
|
|
17
|
+
* @property onSkip - Chamado ao clicar no "Skip This Step".
|
|
18
|
+
* @property class - Classe CSS extra no container do modal.
|
|
19
|
+
*/
|
|
20
|
+
export type ModalBadgeSelectionProps = {
|
|
21
|
+
title: string;
|
|
22
|
+
subtitle?: string;
|
|
23
|
+
badges: ModelBadge[];
|
|
24
|
+
selectedBadge?: ModelBadge | null;
|
|
25
|
+
selectedBadges?: ModelBadge[];
|
|
26
|
+
multiple?: boolean;
|
|
27
|
+
totalSteps?: number;
|
|
28
|
+
currentStep?: number;
|
|
29
|
+
isOpen?: boolean;
|
|
30
|
+
onSelect?: (badge: ModelBadge) => void;
|
|
31
|
+
onBack?: () => void;
|
|
32
|
+
onContinue?: () => void;
|
|
33
|
+
onSkip?: () => void;
|
|
34
|
+
class?: string;
|
|
35
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from "../../../../../utils";
|
|
3
|
+
import { HugeiconsIcon } from "@hugeicons/svelte";
|
|
4
|
+
import ModalCore from "../../core/ui/ModalCore.svelte";
|
|
5
|
+
import type { ModalBadgeSelectionProps, ModelBadge } from "../types";
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
title,
|
|
9
|
+
subtitle,
|
|
10
|
+
badges = [],
|
|
11
|
+
selectedBadge = $bindable(null),
|
|
12
|
+
selectedBadges = $bindable([]),
|
|
13
|
+
multiple = false,
|
|
14
|
+
totalSteps = 1,
|
|
15
|
+
currentStep = 1,
|
|
16
|
+
isOpen = $bindable(false),
|
|
17
|
+
onSelect,
|
|
18
|
+
onBack,
|
|
19
|
+
onContinue,
|
|
20
|
+
onSkip,
|
|
21
|
+
class: className,
|
|
22
|
+
}: ModalBadgeSelectionProps = $props();
|
|
23
|
+
|
|
24
|
+
function handleSelect(badge: ModelBadge) {
|
|
25
|
+
if (multiple) {
|
|
26
|
+
const exists = selectedBadges.some((b) => b.value === badge.value);
|
|
27
|
+
if (exists) {
|
|
28
|
+
selectedBadges = selectedBadges.filter((b) => b.value !== badge.value);
|
|
29
|
+
} else {
|
|
30
|
+
selectedBadges = [...selectedBadges, badge];
|
|
31
|
+
}
|
|
32
|
+
onSelect?.(badge);
|
|
33
|
+
} else {
|
|
34
|
+
selectedBadge = badge;
|
|
35
|
+
onSelect?.(badge);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isSelected(badge: ModelBadge): boolean {
|
|
40
|
+
if (multiple) {
|
|
41
|
+
return selectedBadges.some((b) => b.value === badge.value);
|
|
42
|
+
}
|
|
43
|
+
return selectedBadge?.value === badge.value;
|
|
44
|
+
}
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<ModalCore
|
|
48
|
+
bind:isOpen
|
|
49
|
+
{title}
|
|
50
|
+
{subtitle}
|
|
51
|
+
{totalSteps}
|
|
52
|
+
{currentStep}
|
|
53
|
+
showProgress={true}
|
|
54
|
+
showBack={false}
|
|
55
|
+
showSkip={true}
|
|
56
|
+
{onBack}
|
|
57
|
+
{onContinue}
|
|
58
|
+
{onSkip}
|
|
59
|
+
class={className}
|
|
60
|
+
>
|
|
61
|
+
{#snippet content()}
|
|
62
|
+
<div class="flex flex-wrap gap-3">
|
|
63
|
+
{#each badges as badge (badge.value)}
|
|
64
|
+
{@const selected = isSelected(badge)}
|
|
65
|
+
<button
|
|
66
|
+
type="button"
|
|
67
|
+
class={cn(
|
|
68
|
+
"inline-flex items-center gap-2 rounded-full border px-5 py-2.5 text-sm font-medium transition-all duration-200",
|
|
69
|
+
selected
|
|
70
|
+
? "border-foreground bg-foreground text-background shadow-md"
|
|
71
|
+
: "border-border bg-card text-foreground hover:border-foreground/50 hover:shadow-sm"
|
|
72
|
+
)}
|
|
73
|
+
onclick={() => handleSelect(badge)}
|
|
74
|
+
>
|
|
75
|
+
{#if badge.icon}
|
|
76
|
+
{#if typeof badge.icon === "string"}
|
|
77
|
+
<i class="{badge.icon} text-sm"></i>
|
|
78
|
+
{:else}
|
|
79
|
+
<HugeiconsIcon icon={badge.icon} class="size-4" />
|
|
80
|
+
{/if}
|
|
81
|
+
{/if}
|
|
82
|
+
{badge.label}
|
|
83
|
+
</button>
|
|
84
|
+
{/each}
|
|
85
|
+
</div>
|
|
86
|
+
{/snippet}
|
|
87
|
+
</ModalCore>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ModalBadgeSelectionProps } from "../types";
|
|
2
|
+
declare const ModalBadgeSelection: import("svelte").Component<ModalBadgeSelectionProps, {}, "isOpen" | "selectedBadge" | "selectedBadges">;
|
|
3
|
+
type ModalBadgeSelection = ReturnType<typeof ModalBadgeSelection>;
|
|
4
|
+
export default ModalBadgeSelection;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { IconSvgElement } from "@hugeicons/svelte";
|
|
3
|
+
/**
|
|
4
|
+
* Props do componente ModalCore — contentor base reutilizável para todos os modais.
|
|
5
|
+
* Fornece overlay, container com gradiente, cabeçalho, rodapé com progress bar e navegação.
|
|
6
|
+
* @property isOpen - Controla a visibilidade do modal (bindable).
|
|
7
|
+
* @property title - Título principal do modal.
|
|
8
|
+
* @property subtitle - Subtítulo/descrição abaixo do título.
|
|
9
|
+
* @property totalSteps - Número total de passos (para a progress bar).
|
|
10
|
+
* @property currentStep - Passo actual (para a progress bar).
|
|
11
|
+
* @property showProgress - Exibe a progress bar.
|
|
12
|
+
* @property showBack - Exibe o botão "Back".
|
|
13
|
+
* @property showSkip - Exibe o botão/link "Skip".
|
|
14
|
+
* @property skipText - Texto do botão/link de skip.
|
|
15
|
+
* @property continueText - Texto do botão "Continue".
|
|
16
|
+
* @property backText - Texto do botão "Back".
|
|
17
|
+
* @property onBack - Chamado ao clicar no botão "Back".
|
|
18
|
+
* @property onContinue - Chamado ao clicar no botão "Continue".
|
|
19
|
+
* @property onSkip - Chamado ao clicar no skip.
|
|
20
|
+
* @property onClose - Chamado ao clicar no overlay (fechar).
|
|
21
|
+
* @property content - Snippet com o conteúdo principal do modal.
|
|
22
|
+
* @property footer - Snippet personalizado para o rodapé (substitui o padrão).
|
|
23
|
+
* @property class - Classe CSS extra no container do modal.
|
|
24
|
+
*/
|
|
25
|
+
export type ModalCoreProps = {
|
|
26
|
+
isOpen: boolean;
|
|
27
|
+
title: string;
|
|
28
|
+
subtitle?: string;
|
|
29
|
+
totalSteps?: number;
|
|
30
|
+
currentStep?: number;
|
|
31
|
+
showProgress?: boolean;
|
|
32
|
+
showBack?: boolean;
|
|
33
|
+
showSkip?: boolean;
|
|
34
|
+
skipText?: string;
|
|
35
|
+
continueText?: string;
|
|
36
|
+
backText?: string;
|
|
37
|
+
onBack?: () => void;
|
|
38
|
+
onContinue?: () => void;
|
|
39
|
+
onSkip?: () => void;
|
|
40
|
+
onClose?: () => void;
|
|
41
|
+
content?: Snippet;
|
|
42
|
+
footer?: Snippet;
|
|
43
|
+
class?: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Modelo de dados para um badge/pill seleccionável dentro do modal.
|
|
47
|
+
* Cada badge representa uma opção simples (ex: "Marketing", "Engineering").
|
|
48
|
+
* @property label - Texto visível do badge.
|
|
49
|
+
* @property value - Valor identificador do badge.
|
|
50
|
+
* @property icon - Ícone opcional exibido antes do label.
|
|
51
|
+
*/
|
|
52
|
+
export type ModelBadge = {
|
|
53
|
+
label: string;
|
|
54
|
+
value: string;
|
|
55
|
+
icon?: string | IconSvgElement;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Modelo de dados para um card seleccionável dentro do grid do modal.
|
|
59
|
+
* Cada card representa uma opção com ícone, título e descrição (ex: "Estudante", "Empresa").
|
|
60
|
+
* @property title - Título visível do card.
|
|
61
|
+
* @property description - Descrição curta exibida abaixo do título.
|
|
62
|
+
* @property icon - Ícone exibido no topo do card (string CSS ou HugeIcons).
|
|
63
|
+
*/
|
|
64
|
+
export type ModelGridCard = {
|
|
65
|
+
title: string;
|
|
66
|
+
description?: string;
|
|
67
|
+
icon: string | IconSvgElement;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Modelo de dados para uma rede social no modal de partilha.
|
|
71
|
+
* Cada item representa uma plataforma de redes sociais para partilhar conteúdo.
|
|
72
|
+
* @property name - Nome da rede social (ex: "Facebook", "Twitter").
|
|
73
|
+
* @property icon - Ícone da rede social (string CSS ou HugeIcons).
|
|
74
|
+
* @property img - URL da imagem/imagem de marca da rede social.
|
|
75
|
+
* @property color - Cor da rede social (hex, rgb, etc.).
|
|
76
|
+
* @property url - URL de partilha da rede social.
|
|
77
|
+
*/
|
|
78
|
+
export type ModelSocialShare = {
|
|
79
|
+
name: string;
|
|
80
|
+
icon?: string | IconSvgElement;
|
|
81
|
+
img?: string;
|
|
82
|
+
color?: string;
|
|
83
|
+
url?: string;
|
|
84
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|