negodesign 0.0.74 → 0.0.75
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/login/02/ui/LoginCard02.svelte +15 -4
- package/dist/components/pages/security/login/03/ui/LoginCard03.svelte +34 -16
- 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 +82 -0
- package/dist/components/ui/modal/core/types.js +1 -0
- package/dist/components/ui/modal/core/ui/ModalCore.svelte +129 -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 +142 -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 +32 -0
- package/dist/components/ui/modal/share/types.js +1 -0
- package/dist/components/ui/modal/share/ui/ModalShareSelection.svelte +103 -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/components.d.ts +1 -1
- package/dist/docs/components.js +882 -0
- package/dist/globals.css +443 -0
- package/dist/index.d.ts +169 -0
- package/dist/index.js +169 -0
- package/dist/types/index.d.ts +46 -0
- package/package.json +1 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Label } from "../../label";
|
|
3
|
+
import { Checkbox } from "../../checkbox";
|
|
4
|
+
import { cn } from "../../../../utils";
|
|
5
|
+
|
|
6
|
+
type CheckboxOption = { value: string; label: string };
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
label,
|
|
10
|
+
isLabel = false,
|
|
11
|
+
value = $bindable([]),
|
|
12
|
+
disabled = false,
|
|
13
|
+
required = false,
|
|
14
|
+
options = [],
|
|
15
|
+
name = "",
|
|
16
|
+
class: className,
|
|
17
|
+
}: {
|
|
18
|
+
label?: string;
|
|
19
|
+
isLabel?: boolean;
|
|
20
|
+
value?: string[];
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
required?: boolean;
|
|
23
|
+
options?: CheckboxOption[];
|
|
24
|
+
name?: string;
|
|
25
|
+
class?: string;
|
|
26
|
+
} = $props();
|
|
27
|
+
|
|
28
|
+
function handleToggle(optionValue: string) {
|
|
29
|
+
if (disabled) return;
|
|
30
|
+
const idx = value.indexOf(optionValue);
|
|
31
|
+
if (idx >= 0) {
|
|
32
|
+
value = value.filter((v) => v !== optionValue);
|
|
33
|
+
} else {
|
|
34
|
+
value = [...value, optionValue];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isChecked(optionValue: string): boolean {
|
|
39
|
+
return value.includes(optionValue);
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
{#if isLabel}
|
|
44
|
+
<div class={cn("flex w-full flex-col gap-2", className)}>
|
|
45
|
+
{#if label}
|
|
46
|
+
<Label>{label}</Label>
|
|
47
|
+
{/if}
|
|
48
|
+
<div class="flex flex-wrap gap-4">
|
|
49
|
+
{#each options as option (option.value)}
|
|
50
|
+
<label
|
|
51
|
+
class={cn(
|
|
52
|
+
"flex cursor-pointer items-center gap-2 text-sm",
|
|
53
|
+
disabled && "cursor-not-allowed opacity-50"
|
|
54
|
+
)}
|
|
55
|
+
>
|
|
56
|
+
<Checkbox
|
|
57
|
+
{disabled}
|
|
58
|
+
{name}
|
|
59
|
+
checked={isChecked(option.value)}
|
|
60
|
+
onCheckedChange={() => handleToggle(option.value)}
|
|
61
|
+
/>
|
|
62
|
+
<span class="text-foreground">{option.label}</span>
|
|
63
|
+
</label>
|
|
64
|
+
{/each}
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
{:else}
|
|
68
|
+
<div class={cn("flex flex-wrap gap-4", className)}>
|
|
69
|
+
{#each options as option (option.value)}
|
|
70
|
+
<label
|
|
71
|
+
class={cn(
|
|
72
|
+
"flex cursor-pointer items-center gap-2 text-sm",
|
|
73
|
+
disabled && "cursor-not-allowed opacity-50"
|
|
74
|
+
)}
|
|
75
|
+
>
|
|
76
|
+
<Checkbox
|
|
77
|
+
{disabled}
|
|
78
|
+
{name}
|
|
79
|
+
checked={isChecked(option.value)}
|
|
80
|
+
onCheckedChange={() => handleToggle(option.value)}
|
|
81
|
+
/>
|
|
82
|
+
<span class="text-foreground">{option.label}</span>
|
|
83
|
+
</label>
|
|
84
|
+
{/each}
|
|
85
|
+
</div>
|
|
86
|
+
{/if}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type CheckboxOption = {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
};
|
|
5
|
+
type $$ComponentProps = {
|
|
6
|
+
label?: string;
|
|
7
|
+
isLabel?: boolean;
|
|
8
|
+
value?: string[];
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
required?: boolean;
|
|
11
|
+
options?: CheckboxOption[];
|
|
12
|
+
name?: string;
|
|
13
|
+
class?: string;
|
|
14
|
+
};
|
|
15
|
+
declare const InputCheckbox: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
16
|
+
type InputCheckbox = ReturnType<typeof InputCheckbox>;
|
|
17
|
+
export default InputCheckbox;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Label } from "../../label";
|
|
3
|
+
import { cn } from "../../../../utils";
|
|
4
|
+
|
|
5
|
+
type RadioOption = { value: string; label: string };
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
label,
|
|
9
|
+
isLabel = false,
|
|
10
|
+
value = $bindable(""),
|
|
11
|
+
disabled = false,
|
|
12
|
+
required = false,
|
|
13
|
+
options = [],
|
|
14
|
+
name = "",
|
|
15
|
+
class: className,
|
|
16
|
+
}: {
|
|
17
|
+
label?: string;
|
|
18
|
+
isLabel?: boolean;
|
|
19
|
+
value?: string;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
required?: boolean;
|
|
22
|
+
options?: RadioOption[];
|
|
23
|
+
name?: string;
|
|
24
|
+
class?: string;
|
|
25
|
+
} = $props();
|
|
26
|
+
|
|
27
|
+
function handleSelect(option: RadioOption) {
|
|
28
|
+
if (disabled) return;
|
|
29
|
+
value = option.value;
|
|
30
|
+
}
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
{#if isLabel}
|
|
34
|
+
<div class={cn("flex w-full flex-col gap-2", className)}>
|
|
35
|
+
{#if label}
|
|
36
|
+
<Label>{label}</Label>
|
|
37
|
+
{/if}
|
|
38
|
+
<div class="flex flex-wrap gap-4">
|
|
39
|
+
{#each options as option (option.value)}
|
|
40
|
+
<label
|
|
41
|
+
class={cn(
|
|
42
|
+
"flex cursor-pointer items-center gap-2 text-sm",
|
|
43
|
+
disabled && "cursor-not-allowed opacity-50"
|
|
44
|
+
)}
|
|
45
|
+
>
|
|
46
|
+
<input
|
|
47
|
+
type="radio"
|
|
48
|
+
{name}
|
|
49
|
+
{disabled}
|
|
50
|
+
{required}
|
|
51
|
+
checked={value === option.value}
|
|
52
|
+
onchange={() => handleSelect(option)}
|
|
53
|
+
class="size-4 border-input text-primary accent-primary"
|
|
54
|
+
/>
|
|
55
|
+
<span class="text-foreground">{option.label}</span>
|
|
56
|
+
</label>
|
|
57
|
+
{/each}
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
{:else}
|
|
61
|
+
<div class={cn("flex flex-wrap gap-4", className)}>
|
|
62
|
+
{#each options as option (option.value)}
|
|
63
|
+
<label
|
|
64
|
+
class={cn(
|
|
65
|
+
"flex cursor-pointer items-center gap-2 text-sm",
|
|
66
|
+
disabled && "cursor-not-allowed opacity-50"
|
|
67
|
+
)}
|
|
68
|
+
>
|
|
69
|
+
<input
|
|
70
|
+
type="radio"
|
|
71
|
+
{name}
|
|
72
|
+
{disabled}
|
|
73
|
+
{required}
|
|
74
|
+
checked={value === option.value}
|
|
75
|
+
onchange={() => handleSelect(option)}
|
|
76
|
+
class="size-4 border-input text-primary accent-primary"
|
|
77
|
+
/>
|
|
78
|
+
<span class="text-foreground">{option.label}</span>
|
|
79
|
+
</label>
|
|
80
|
+
{/each}
|
|
81
|
+
</div>
|
|
82
|
+
{/if}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type RadioOption = {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
};
|
|
5
|
+
type $$ComponentProps = {
|
|
6
|
+
label?: string;
|
|
7
|
+
isLabel?: boolean;
|
|
8
|
+
value?: string;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
required?: boolean;
|
|
11
|
+
options?: RadioOption[];
|
|
12
|
+
name?: string;
|
|
13
|
+
class?: string;
|
|
14
|
+
};
|
|
15
|
+
declare const InputRadio: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
16
|
+
type InputRadio = ReturnType<typeof InputRadio>;
|
|
17
|
+
export default InputRadio;
|
|
@@ -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 {};
|