@ibis-design/svelte 0.2.0 → 0.6.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 +12 -2
- package/dist/components/buttons/Button.svelte +106 -0
- package/dist/components/buttons/Button.svelte.d.ts +69 -0
- package/dist/components/buttons/DropdownButton.svelte +91 -0
- package/dist/components/buttons/DropdownButton.svelte.d.ts +33 -0
- package/dist/components/buttons/PillTab.svelte +84 -0
- package/dist/components/buttons/PillTab.svelte.d.ts +55 -0
- package/dist/components/buttons/button.css +193 -0
- package/dist/components/buttons/dropdownButton.css +82 -0
- package/dist/components/buttons/pillTab.css +59 -0
- package/dist/components/containers/Banner.svelte +73 -0
- package/dist/components/containers/Banner.svelte.d.ts +16 -0
- package/dist/components/containers/Card.svelte +34 -0
- package/dist/components/containers/Card.svelte.d.ts +14 -0
- package/dist/components/containers/PillTabs.svelte +22 -0
- package/dist/components/containers/PillTabs.svelte.d.ts +6 -0
- package/dist/components/containers/TipIndicator.svelte +78 -0
- package/dist/components/containers/TipIndicator.svelte.d.ts +28 -0
- package/dist/components/containers/Toaster.svelte +75 -0
- package/dist/components/containers/Toaster.svelte.d.ts +16 -0
- package/dist/components/containers/Tooltip.svelte.d.ts +26 -0
- package/dist/components/containers/banner.css +155 -0
- package/dist/components/containers/tipIndicator.css +79 -0
- package/dist/components/containers/toaster.css +137 -0
- package/dist/components/containers/tooltip.css +0 -0
- package/dist/components/inputs/.gitkeep +0 -0
- package/dist/components/inputs/Checkbox.svelte +95 -0
- package/dist/components/inputs/Checkbox.svelte.d.ts +33 -0
- package/dist/components/inputs/Chips.svelte +104 -0
- package/dist/components/inputs/Chips.svelte.d.ts +48 -0
- package/dist/components/inputs/Dropdown.svelte +83 -0
- package/dist/components/inputs/Dropdown.svelte.d.ts +15 -0
- package/dist/components/inputs/Radio.svelte +109 -0
- package/dist/components/inputs/Radio.svelte.d.ts +49 -0
- package/dist/components/inputs/Switch.svelte +45 -0
- package/dist/components/inputs/Switch.svelte.d.ts +21 -0
- package/dist/components/inputs/TextArea.svelte +65 -0
- package/dist/components/inputs/TextArea.svelte.d.ts +14 -0
- package/dist/components/inputs/TextInput.svelte +273 -0
- package/dist/components/inputs/TextInput.svelte.d.ts +140 -0
- package/dist/components/inputs/TextLink.svelte +102 -0
- package/dist/components/inputs/TextLink.svelte.d.ts +21 -0
- package/dist/components/inputs/checkbox.css +103 -0
- package/dist/components/inputs/chips.css +76 -0
- package/dist/components/inputs/dropdown.css +106 -0
- package/dist/components/inputs/radio.css +108 -0
- package/dist/components/inputs/switch.css +68 -0
- package/dist/components/inputs/textInput.css +152 -0
- package/dist/components/inputs/textarea.css +91 -0
- package/dist/components/inputs/textlink.css +163 -0
- package/dist/index.d.ts +21 -8
- package/dist/index.js +36 -2000
- package/dist/layouts/AppLayout.svelte +83 -0
- package/dist/layouts/AppLayout.svelte.d.ts +20 -0
- package/dist/layouts/AuthLayout.svelte +63 -0
- package/dist/layouts/AuthLayout.svelte.d.ts +18 -0
- package/dist/layouts/DashboardLayout.svelte +88 -0
- package/dist/layouts/DashboardLayout.svelte.d.ts +20 -0
- package/dist/types/button.js +5 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +5 -0
- package/dist/types/layout.d.ts +1 -1
- package/dist/types/layout.js +1 -0
- package/package.json +49 -44
- package/dist/index.css +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/components/buttons/Button.svelte.d.ts +0 -1
- package/dist/lib/components/buttons/DropdownButton.svelte.d.ts +0 -1
- package/dist/lib/components/containers/Card.svelte.d.ts +0 -1
- package/dist/lib/layouts/AppLayout.svelte.d.ts +0 -1
- package/dist/lib/layouts/AuthLayout.svelte.d.ts +0 -1
- package/dist/lib/layouts/DashboardLayout.svelte.d.ts +0 -1
- /package/dist/{types/input.d.ts → components/containers/Tooltip.svelte} +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
.ibis-tip-indicator {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: inline-flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
cursor: pointer;
|
|
7
|
+
color: var(--color-neutral-400);
|
|
8
|
+
transition: color var(--transition-duration-fast) var(--transition-timing-default);
|
|
9
|
+
outline: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.ibis-tip-indicator:hover,
|
|
13
|
+
.ibis-tip-indicator:focus-visible {
|
|
14
|
+
color: var(--color-primary-500);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.ibis-tip-indicator__icon {
|
|
18
|
+
width: 1em;
|
|
19
|
+
height: 1em;
|
|
20
|
+
display: block;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* Tooltip box */
|
|
24
|
+
.ibis-tip {
|
|
25
|
+
position: absolute;
|
|
26
|
+
z-index: 100;
|
|
27
|
+
background-color: var(--color-neutral-600);
|
|
28
|
+
color: var(--color-white);
|
|
29
|
+
font-size: var(--font-size-normal-text-sm);
|
|
30
|
+
font-family: var(--font-family-sans);
|
|
31
|
+
padding: var(--spacing-2) var(--spacing-4);
|
|
32
|
+
border-radius: var(--border-radius-full);
|
|
33
|
+
pointer-events: none;
|
|
34
|
+
white-space: nowrap;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Width variants */
|
|
38
|
+
.ibis-tip--width-auto {
|
|
39
|
+
white-space: nowrap;
|
|
40
|
+
width: auto;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.ibis-tip--width-240 {
|
|
44
|
+
width: 240px;
|
|
45
|
+
white-space: normal;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.ibis-tip--width-360 {
|
|
49
|
+
width: 360px;
|
|
50
|
+
white-space: normal;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Top */
|
|
54
|
+
.ibis-tip--top {
|
|
55
|
+
bottom: calc(100% + 8px);
|
|
56
|
+
left: 50%;
|
|
57
|
+
transform: translateX(-50%);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Bottom */
|
|
61
|
+
.ibis-tip--bottom {
|
|
62
|
+
top: calc(100% + 8px);
|
|
63
|
+
left: 50%;
|
|
64
|
+
transform: translateX(-50%);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Left */
|
|
68
|
+
.ibis-tip--left {
|
|
69
|
+
right: calc(100% + 8px);
|
|
70
|
+
top: 50%;
|
|
71
|
+
transform: translateY(-50%);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Right */
|
|
75
|
+
.ibis-tip--right {
|
|
76
|
+
left: calc(100% + 8px);
|
|
77
|
+
top: 50%;
|
|
78
|
+
transform: translateY(-50%);
|
|
79
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
.ibis-toaster {
|
|
2
|
+
font-family: var(--font-family-sans);
|
|
3
|
+
display: flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
gap: 8px; /*hardcoded*/
|
|
6
|
+
padding: 8px 16px;
|
|
7
|
+
border-radius: 16px; /*hardcoded*/
|
|
8
|
+
border: var(--border-width-default) solid var(--color-neutral-200);
|
|
9
|
+
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.08);
|
|
10
|
+
|
|
11
|
+
max-width: 200px;
|
|
12
|
+
position: relative;
|
|
13
|
+
margin-bottom: 2px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* ICON */
|
|
17
|
+
.ibis-toaster__icon {
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
|
|
22
|
+
width: 20px;
|
|
23
|
+
height: 20px;
|
|
24
|
+
top: 2px;
|
|
25
|
+
left: 2px;
|
|
26
|
+
|
|
27
|
+
flex-shrink: 0;
|
|
28
|
+
|
|
29
|
+
margin-top: 2px;
|
|
30
|
+
color: var(--color-white);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.ibis-toaster__icon :global(svg) {
|
|
34
|
+
width: 100%;
|
|
35
|
+
height: 100%;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.ibis-toaster__content {
|
|
39
|
+
flex: 1;
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
justify-content: center;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.ibis-toaster__title {
|
|
46
|
+
font-weight: var(--font-weight-medium);
|
|
47
|
+
font-size: var(--font-size-normal-text-sm);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.ibis-toaster__message {
|
|
51
|
+
font-size: var(--font-size-normal-text-sm);
|
|
52
|
+
color: var(--color-white);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.ibis-toaster--default .ibis-toaster__message {
|
|
56
|
+
font-size: var(--font-size-normal-text-sm);
|
|
57
|
+
color: var(--color-black);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.ibis-toaster--default .ibis-toaster__icon {
|
|
61
|
+
color: var(--color-black);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.ibis-toaster__close {
|
|
65
|
+
background: transparent;
|
|
66
|
+
border: none;
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
font-size: 18px; /*hardcoded*/
|
|
69
|
+
line-height: 1;
|
|
70
|
+
color: var(--color-white);
|
|
71
|
+
flex-shrink: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.ibis-toaster--default .ibis-toaster__close {
|
|
75
|
+
color: var(--color-black);
|
|
76
|
+
border-color: var(--color-white);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* SUCCESS */
|
|
80
|
+
.ibis-toaster--success {
|
|
81
|
+
border-color: var(--color-status-success);
|
|
82
|
+
background-color: var(--color-status-success);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.ibis-toaster--success .ibis-toaster__title {
|
|
86
|
+
color: var(--color-white);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* ERROR */
|
|
90
|
+
.ibis-toaster--error {
|
|
91
|
+
border-color: var(--color-status-error);
|
|
92
|
+
background-color: var(--color-status-error);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.ibis-toaster--error .ibis-toaster__title {
|
|
96
|
+
color: var(--color-white);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* ACCENT */
|
|
100
|
+
.ibis-toaster--accent {
|
|
101
|
+
border-color: #920075; /*hardcoded*/
|
|
102
|
+
background-color: #920075; /*hardcoded*/
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.ibis-toaster--accent .ibis-toaster__title {
|
|
106
|
+
color: var(--color-white);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* DEFAULT */
|
|
110
|
+
.ibis-toaster--default {
|
|
111
|
+
border-color: var(--color-neutral-100);
|
|
112
|
+
background-color: var(--color-neutral-100);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.ibis-toaster--default .ibis-toaster__title {
|
|
116
|
+
color: var(--color-black);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.ibis-toaster__loader {
|
|
120
|
+
width: 1em;
|
|
121
|
+
height: 1em;
|
|
122
|
+
|
|
123
|
+
border: var(--border-width-default) solid var(--color-primary-300);
|
|
124
|
+
border-top-color: var(--color-primary-900);
|
|
125
|
+
border-radius: 50%;
|
|
126
|
+
|
|
127
|
+
animation: ibis-spin 0.8s linear infinite;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@keyframes ibis-spin {
|
|
131
|
+
from {
|
|
132
|
+
transform: rotate(0deg);
|
|
133
|
+
}
|
|
134
|
+
to {
|
|
135
|
+
transform: rotate(360deg);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import "./checkbox.css";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLInputAttributes {
|
|
7
|
+
label?: string;
|
|
8
|
+
id?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Defines whether the checkbox is checked.
|
|
11
|
+
*
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
checked?: boolean;
|
|
15
|
+
inputSize?: "sm" | "md" | "lg";
|
|
16
|
+
/**
|
|
17
|
+
* Defines whether the checkbox is disabled.
|
|
18
|
+
*
|
|
19
|
+
* @default false
|
|
20
|
+
*/
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Defines whether the checkbox is in an invalid state.
|
|
24
|
+
*
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
invalid?: boolean;
|
|
28
|
+
description?: string;
|
|
29
|
+
error?: string;
|
|
30
|
+
helpText?: string;
|
|
31
|
+
checkboxSnippet?: Snippet;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let {
|
|
35
|
+
id,
|
|
36
|
+
label,
|
|
37
|
+
checked = $bindable(false),
|
|
38
|
+
inputSize = "md",
|
|
39
|
+
disabled = false,
|
|
40
|
+
invalid = false,
|
|
41
|
+
description,
|
|
42
|
+
error,
|
|
43
|
+
helpText,
|
|
44
|
+
checkboxSnippet,
|
|
45
|
+
...rest
|
|
46
|
+
}: Props = $props();
|
|
47
|
+
|
|
48
|
+
const fallbackId = `ibis-checkbox-${Math.random().toString(36).slice(2)}`;
|
|
49
|
+
const inputId = $derived(id ?? fallbackId);
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<div
|
|
53
|
+
class="ibis-checkbox
|
|
54
|
+
ibis-checkbox--{inputSize}
|
|
55
|
+
{disabled ? 'ibis-checkbox--disabled' : ''}
|
|
56
|
+
{invalid ? 'ibis-checkbox--invalid' : ''}">
|
|
57
|
+
{#if label}
|
|
58
|
+
<div class="ibis-checkbox__label-wrapper">
|
|
59
|
+
<label class="ibis-checkbox__label" for={inputId}>{label}</label>
|
|
60
|
+
|
|
61
|
+
{#if description}
|
|
62
|
+
<div class="ibis-checkbox__description">{description}</div>
|
|
63
|
+
{/if}
|
|
64
|
+
</div>
|
|
65
|
+
{/if}
|
|
66
|
+
|
|
67
|
+
<div class="ibis-checkbox__wrapper">
|
|
68
|
+
<label class="ibis-checkbox__control">
|
|
69
|
+
<input
|
|
70
|
+
{...rest}
|
|
71
|
+
id={inputId}
|
|
72
|
+
type="checkbox"
|
|
73
|
+
bind:checked
|
|
74
|
+
{disabled}
|
|
75
|
+
aria-invalid={invalid}
|
|
76
|
+
class="ibis-checkbox__input" />
|
|
77
|
+
|
|
78
|
+
<span class="ibis-checkbox__box">
|
|
79
|
+
<span class="ibis-checkbox__icon">
|
|
80
|
+
{@render checkboxSnippet?.()}
|
|
81
|
+
</span>
|
|
82
|
+
</span>
|
|
83
|
+
|
|
84
|
+
{#if label}
|
|
85
|
+
<span class="ibis-checkbox__text">{label}</span>
|
|
86
|
+
{/if}
|
|
87
|
+
</label>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
{#if invalid && error}
|
|
91
|
+
<div class="ibis-checkbox__error" role="alert">{error}</div>
|
|
92
|
+
{:else if helpText}
|
|
93
|
+
<div class="ibis-checkbox__help">{helpText}</div>
|
|
94
|
+
{/if}
|
|
95
|
+
</div>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import "./checkbox.css";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
4
|
+
interface Props extends HTMLInputAttributes {
|
|
5
|
+
label?: string;
|
|
6
|
+
id?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Defines whether the checkbox is checked.
|
|
9
|
+
*
|
|
10
|
+
* @default false
|
|
11
|
+
*/
|
|
12
|
+
checked?: boolean;
|
|
13
|
+
inputSize?: "sm" | "md" | "lg";
|
|
14
|
+
/**
|
|
15
|
+
* Defines whether the checkbox is disabled.
|
|
16
|
+
*
|
|
17
|
+
* @default false
|
|
18
|
+
*/
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Defines whether the checkbox is in an invalid state.
|
|
22
|
+
*
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
invalid?: boolean;
|
|
26
|
+
description?: string;
|
|
27
|
+
error?: string;
|
|
28
|
+
helpText?: string;
|
|
29
|
+
checkboxSnippet?: Snippet;
|
|
30
|
+
}
|
|
31
|
+
declare const Checkbox: import("svelte").Component<Props, {}, "checked">;
|
|
32
|
+
type Checkbox = ReturnType<typeof Checkbox>;
|
|
33
|
+
export default Checkbox;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import "./chips.css";
|
|
3
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
4
|
+
import type { Snippet } from "svelte";
|
|
5
|
+
// define props
|
|
6
|
+
interface Props extends HTMLButtonAttributes {
|
|
7
|
+
/**
|
|
8
|
+
* Defines the size of the chip.
|
|
9
|
+
*
|
|
10
|
+
* @default "md"
|
|
11
|
+
*/
|
|
12
|
+
size?: "sm" | "md" | "lg";
|
|
13
|
+
/**
|
|
14
|
+
* Defines whether the chip is disabled.
|
|
15
|
+
*
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Defines whether the chip is selected.
|
|
21
|
+
*
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
selected?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Shows a loading spinner and disables the chip.
|
|
27
|
+
*
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
loading?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Disables the chip and applies skeleton styling
|
|
33
|
+
*
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
skeleton?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Plain text label for the chip. Use children snippet for complex content.
|
|
39
|
+
*/
|
|
40
|
+
label?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Plain text or emoji icon. Use icon snippet for complex content.
|
|
43
|
+
*/
|
|
44
|
+
iconText?: string;
|
|
45
|
+
children?: Snippet;
|
|
46
|
+
icon?: Snippet<[]>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let {
|
|
50
|
+
size = "md",
|
|
51
|
+
selected = $bindable(false),
|
|
52
|
+
disabled = false,
|
|
53
|
+
loading = false,
|
|
54
|
+
skeleton = false,
|
|
55
|
+
label,
|
|
56
|
+
iconText,
|
|
57
|
+
children,
|
|
58
|
+
icon,
|
|
59
|
+
...rest
|
|
60
|
+
}: Props = $props();
|
|
61
|
+
|
|
62
|
+
const toggleSelected = () => {
|
|
63
|
+
if (disabled || loading || skeleton) return;
|
|
64
|
+
selected = !selected;
|
|
65
|
+
};
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<!-- add how it would look in the DOM -->
|
|
69
|
+
<button
|
|
70
|
+
{...rest}
|
|
71
|
+
{disabled}
|
|
72
|
+
aria-pressed={selected}
|
|
73
|
+
aria-busy={loading}
|
|
74
|
+
onclick={toggleSelected}
|
|
75
|
+
class="ibis-chips
|
|
76
|
+
ibis-chips--{size}
|
|
77
|
+
{selected ? 'ibis-chips--selected' : ''}
|
|
78
|
+
{skeleton ? 'ibis-chips--skeleton' : ''}">
|
|
79
|
+
<span class="ibis-chips__content {skeleton ? 'ibis-chips__content--hidden' : ''}">
|
|
80
|
+
{#if icon || iconText}
|
|
81
|
+
<span class="ibis-chips__icon">
|
|
82
|
+
{#if icon}
|
|
83
|
+
{@render icon()}
|
|
84
|
+
{:else}
|
|
85
|
+
{iconText}
|
|
86
|
+
{/if}
|
|
87
|
+
</span>
|
|
88
|
+
{/if}
|
|
89
|
+
|
|
90
|
+
{#if children || label}
|
|
91
|
+
<span class="ibis-chips__label">
|
|
92
|
+
{#if children}
|
|
93
|
+
{@render children?.()}
|
|
94
|
+
{:else}
|
|
95
|
+
{label}
|
|
96
|
+
{/if}
|
|
97
|
+
</span>
|
|
98
|
+
{/if}
|
|
99
|
+
</span>
|
|
100
|
+
|
|
101
|
+
{#if loading}
|
|
102
|
+
<span class="ibis-chips__loader" aria-hidden="true"></span>
|
|
103
|
+
{/if}
|
|
104
|
+
</button>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import "./chips.css";
|
|
2
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
interface Props extends HTMLButtonAttributes {
|
|
5
|
+
/**
|
|
6
|
+
* Defines the size of the chip.
|
|
7
|
+
*
|
|
8
|
+
* @default "md"
|
|
9
|
+
*/
|
|
10
|
+
size?: "sm" | "md" | "lg";
|
|
11
|
+
/**
|
|
12
|
+
* Defines whether the chip is disabled.
|
|
13
|
+
*
|
|
14
|
+
* @default false
|
|
15
|
+
*/
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Defines whether the chip is selected.
|
|
19
|
+
*
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
selected?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Shows a loading spinner and disables the chip.
|
|
25
|
+
*
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
loading?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Disables the chip and applies skeleton styling
|
|
31
|
+
*
|
|
32
|
+
* @default false
|
|
33
|
+
*/
|
|
34
|
+
skeleton?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Plain text label for the chip. Use children snippet for complex content.
|
|
37
|
+
*/
|
|
38
|
+
label?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Plain text or emoji icon. Use icon snippet for complex content.
|
|
41
|
+
*/
|
|
42
|
+
iconText?: string;
|
|
43
|
+
children?: Snippet;
|
|
44
|
+
icon?: Snippet<[]>;
|
|
45
|
+
}
|
|
46
|
+
declare const Chips: import("svelte").Component<Props, {}, "selected">;
|
|
47
|
+
type Chips = ReturnType<typeof Chips>;
|
|
48
|
+
export default Chips;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import "./dropdown.css";
|
|
3
|
+
import TextInput from "./TextInput.svelte";
|
|
4
|
+
|
|
5
|
+
interface Options {
|
|
6
|
+
label: string;
|
|
7
|
+
value: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
label?: string;
|
|
12
|
+
value?: string;
|
|
13
|
+
options?: Options[];
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
label,
|
|
20
|
+
value = $bindable(""),
|
|
21
|
+
options = [],
|
|
22
|
+
placeholder = "Select...",
|
|
23
|
+
disabled = false,
|
|
24
|
+
}: Props = $props();
|
|
25
|
+
|
|
26
|
+
let open = $state(false);
|
|
27
|
+
let dropdownRef = $state<HTMLDivElement | null>(null);
|
|
28
|
+
|
|
29
|
+
const listboxId = `ibis-dropdown-listbox-${Math.random().toString(36).slice(2)}`;
|
|
30
|
+
|
|
31
|
+
const selectOption = (option: Options) => {
|
|
32
|
+
value = option.value;
|
|
33
|
+
open = false;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const toggleDropdown = () => {
|
|
37
|
+
if (!disabled) open = !open;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const handleKeydown = (e: KeyboardEvent) => {
|
|
41
|
+
if (e.key === "Escape") open = false;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const handleClickOutside = (e: MouseEvent) => {
|
|
45
|
+
if (dropdownRef && !dropdownRef.contains(e.target as Node)) {
|
|
46
|
+
open = false;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const selectedLabel = $derived(options.find((o) => o.value === value)?.label ?? value);
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<svelte:window onclick={handleClickOutside} />
|
|
54
|
+
|
|
55
|
+
{#snippet suffixSnippet()}
|
|
56
|
+
▾
|
|
57
|
+
{/snippet}
|
|
58
|
+
|
|
59
|
+
<div
|
|
60
|
+
class="ibis-dropdown {open ? 'ibis-dropdown--open' : ''}"
|
|
61
|
+
role="combobox"
|
|
62
|
+
tabindex="0"
|
|
63
|
+
aria-expanded={open}
|
|
64
|
+
aria-haspopup="listbox"
|
|
65
|
+
aria-controls={listboxId}
|
|
66
|
+
bind:this={dropdownRef}
|
|
67
|
+
onkeydown={handleKeydown}>
|
|
68
|
+
<button type="button" class="ibis-dropdown__trigger" onclick={toggleDropdown} {disabled}>
|
|
69
|
+
<TextInput {label} value={selectedLabel} {placeholder} {disabled} readonly {suffixSnippet} />
|
|
70
|
+
</button>
|
|
71
|
+
|
|
72
|
+
{#if open}
|
|
73
|
+
<ul id={listboxId} role="listbox" class="ibis-dropdown__menu">
|
|
74
|
+
{#each options as option (option.value)}
|
|
75
|
+
<li role="option" aria-selected={option.value === value}>
|
|
76
|
+
<button type="button" class="ibis-dropdown__item" onclick={() => selectOption(option)}>
|
|
77
|
+
{option.label}
|
|
78
|
+
</button>
|
|
79
|
+
</li>
|
|
80
|
+
{/each}
|
|
81
|
+
</ul>
|
|
82
|
+
{/if}
|
|
83
|
+
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import "./dropdown.css";
|
|
2
|
+
interface Options {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
}
|
|
6
|
+
interface Props {
|
|
7
|
+
label?: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
options?: Options[];
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
}
|
|
13
|
+
declare const Dropdown: import("svelte").Component<Props, {}, "value">;
|
|
14
|
+
type Dropdown = ReturnType<typeof Dropdown>;
|
|
15
|
+
export default Dropdown;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import "./radio.css";
|
|
3
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
4
|
+
|
|
5
|
+
interface Props extends HTMLInputAttributes {
|
|
6
|
+
/**
|
|
7
|
+
* The text label displayed next to the radio button, describing its purpose or option.
|
|
8
|
+
*/
|
|
9
|
+
label?: string;
|
|
10
|
+
id?: string;
|
|
11
|
+
/**
|
|
12
|
+
* The value associated with the radio button.
|
|
13
|
+
*
|
|
14
|
+
* Determines which option is selected within a group of radio buttons.
|
|
15
|
+
*
|
|
16
|
+
* @default ""
|
|
17
|
+
*/
|
|
18
|
+
value: string | number;
|
|
19
|
+
/**
|
|
20
|
+
* The name of the radio button group.
|
|
21
|
+
*
|
|
22
|
+
* Radio buttons with the same `name` are grouped together, allowing only one to be selected at a time.
|
|
23
|
+
*
|
|
24
|
+
* @default undefined
|
|
25
|
+
*/
|
|
26
|
+
group?: string | number;
|
|
27
|
+
/**
|
|
28
|
+
* Determines the size of the radio button input.
|
|
29
|
+
*
|
|
30
|
+
* @default "md"
|
|
31
|
+
*/
|
|
32
|
+
inputSize?: "sm" | "md" | "lg";
|
|
33
|
+
/**
|
|
34
|
+
* Disables the radio button, preventing user interaction and applying disabled styles.
|
|
35
|
+
*
|
|
36
|
+
* @default false
|
|
37
|
+
*/
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Marks the radio button as invalid, applying error styles and showing error messages if provided.
|
|
41
|
+
*
|
|
42
|
+
* @default false
|
|
43
|
+
*/
|
|
44
|
+
invalid?: boolean;
|
|
45
|
+
description?: string;
|
|
46
|
+
error?: string;
|
|
47
|
+
helpText?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let {
|
|
51
|
+
id,
|
|
52
|
+
label,
|
|
53
|
+
value,
|
|
54
|
+
group = $bindable(),
|
|
55
|
+
inputSize = "md",
|
|
56
|
+
disabled = false,
|
|
57
|
+
invalid = false,
|
|
58
|
+
description,
|
|
59
|
+
error,
|
|
60
|
+
helpText,
|
|
61
|
+
...rest
|
|
62
|
+
}: Props = $props();
|
|
63
|
+
|
|
64
|
+
const fallbackId = `ibis-radio-${Math.random().toString(36).slice(2)}`;
|
|
65
|
+
const inputId = $derived(id ?? fallbackId);
|
|
66
|
+
|
|
67
|
+
const checked = $derived(group === value);
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
<div
|
|
71
|
+
class="ibis-radio
|
|
72
|
+
ibis-radio--{inputSize}
|
|
73
|
+
{disabled ? 'ibis-radio--disabled' : ''}
|
|
74
|
+
{invalid ? 'ibis-radio--invalid' : ''}">
|
|
75
|
+
{#if label}
|
|
76
|
+
<div class="ibis-radio__label-wrapper">
|
|
77
|
+
<label class="ibis-radio__label" for={inputId}>{label}</label>
|
|
78
|
+
|
|
79
|
+
{#if description}
|
|
80
|
+
<div class="ibis-radio__description">{description}</div>
|
|
81
|
+
{/if}
|
|
82
|
+
</div>
|
|
83
|
+
{/if}
|
|
84
|
+
|
|
85
|
+
<label class="ibis-radio__control" for={inputId}>
|
|
86
|
+
<input
|
|
87
|
+
{...rest}
|
|
88
|
+
id={inputId}
|
|
89
|
+
type="radio"
|
|
90
|
+
bind:group
|
|
91
|
+
{value}
|
|
92
|
+
{disabled}
|
|
93
|
+
class="ibis-radio__input" />
|
|
94
|
+
|
|
95
|
+
<span class="ibis-radio__circle">
|
|
96
|
+
<span class="ibis-radio__dot" class:ibis-radio__dot--active={checked}></span>
|
|
97
|
+
</span>
|
|
98
|
+
|
|
99
|
+
{#if label}
|
|
100
|
+
<span class="ibis-radio__text">{label}</span>
|
|
101
|
+
{/if}
|
|
102
|
+
</label>
|
|
103
|
+
|
|
104
|
+
{#if invalid && error}
|
|
105
|
+
<div class="ibis-radio__error" role="alert">{error}</div>
|
|
106
|
+
{:else if helpText}
|
|
107
|
+
<div class="ibis-radio__help">{helpText}</div>
|
|
108
|
+
{/if}
|
|
109
|
+
</div>
|