sveltacular 1.0.7 → 1.0.10
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 +1 -1
- package/dist/forms/index.d.ts +1 -1
- package/dist/forms/index.js +1 -1
- package/dist/forms/radio-group/radio-group.svelte +1 -1
- package/dist/forms/tag-box/tag-box.svelte +225 -0
- package/dist/forms/tag-box/tag-box.svelte.d.ts +19 -0
- package/dist/forms/text-area/text-area.svelte +0 -1
- package/dist/generic/avatar/avatar.svelte +0 -11
- package/dist/generic/badge/badge.svelte +0 -1
- package/dist/generic/chip/chip.svelte +1 -14
- package/dist/generic/header/header.svelte +28 -20
- package/dist/generic/header/header.svelte.d.ts +4 -3
- package/dist/generic/rating/rating.svelte +2 -3
- package/dist/generic/section/section.svelte +7 -3
- package/dist/generic/spinner/spinner.svelte +0 -1
- package/dist/generic/theme-provider/theme-provider-demo.svelte +38 -64
- package/dist/generic/theme-provider/theme-provider.svelte +5 -11
- package/dist/generic/toaster/toaster.svelte +1 -1
- package/dist/helpers/use-position.svelte.js +1 -1
- package/dist/helpers/use-virtual-list.svelte.js +1 -1
- package/dist/icons/check-icon.svelte +0 -2
- package/dist/icons/copy-icon.svelte +0 -1
- package/dist/layout/flex-col.svelte +89 -58
- package/dist/layout/flex-col.svelte.d.ts +25 -9
- package/dist/layout/flex-item.svelte +30 -8
- package/dist/layout/flex-item.svelte.d.ts +11 -5
- package/dist/layout/flex-row.svelte +88 -73
- package/dist/layout/flex-row.svelte.d.ts +25 -11
- package/dist/layout/main/main.svelte +41 -0
- package/dist/layout/main/main.svelte.d.ts +7 -0
- package/dist/modals/alert.svelte +6 -1
- package/dist/modals/confirm.svelte +6 -1
- package/dist/modals/dialog-footer.svelte +1 -1
- package/dist/modals/modal.svelte +2 -2
- package/dist/modals/prompt.svelte +16 -11
- package/dist/navigation/accordion/accordion.svelte +15 -13
- package/dist/navigation/app-bar/app-bar.svelte +12 -4
- package/dist/navigation/command-palette/command-palette.svelte +34 -41
- package/dist/navigation/context-menu/README.md +34 -56
- package/dist/navigation/context-menu/context-menu-divider.svelte +2 -12
- package/dist/navigation/context-menu/context-menu-item.svelte +10 -11
- package/dist/navigation/context-menu/context-menu.svelte +6 -7
- package/dist/navigation/drawer/drawer.svelte +0 -1
- package/dist/navigation/dropdown-button/dropdown-button.svelte +6 -1
- package/dist/placeholders/skeleton-table.svelte +0 -1
- package/dist/tables/table-row.svelte +2 -6
- package/dist/test-utils/accessibility-helpers.js +2 -3
- package/dist/test-utils/render-helpers.js +4 -7
- package/dist/typography/code.svelte +0 -1
- package/dist/typography/headline.svelte +6 -6
- package/dist/typography/paragraph.svelte +1 -1
- package/dist/typography/subtitle.svelte +1 -1
- package/package.json +4 -8
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ npm i sveltacular
|
|
|
75
75
|
- **SwitchBox** - Toggle switch component
|
|
76
76
|
- **BoolBox** - Boolean input component
|
|
77
77
|
- **MoneyBox** - Currency input with formatting
|
|
78
|
-
- **
|
|
78
|
+
- **TagBox** - Tag input with chip display
|
|
79
79
|
- **UrlBox** - URL input with validation
|
|
80
80
|
- **InfoBox** - Information display box
|
|
81
81
|
- **NewOrExistingCombo** - Combo component for new/existing selection
|
package/dist/forms/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export { default as NumberRangeBox } from './number-range-box/number-range-box.s
|
|
|
11
11
|
export { default as PhoneBox } from './phone-box/phone-box.svelte';
|
|
12
12
|
export { default as Slider } from './slider/slider.svelte';
|
|
13
13
|
export { default as SwitchBox } from './switch-box/switch-box.svelte';
|
|
14
|
-
export { default as
|
|
14
|
+
export { default as TagBox } from './tag-box/tag-box.svelte';
|
|
15
15
|
export { default as TextArea } from './text-area/text-area.svelte';
|
|
16
16
|
export { default as TextBox } from './text-box/text-box.svelte';
|
|
17
17
|
export { default as TimeBox } from './time-box/time-box.svelte';
|
package/dist/forms/index.js
CHANGED
|
@@ -12,7 +12,7 @@ export { default as NumberRangeBox } from './number-range-box/number-range-box.s
|
|
|
12
12
|
export { default as PhoneBox } from './phone-box/phone-box.svelte';
|
|
13
13
|
export { default as Slider } from './slider/slider.svelte';
|
|
14
14
|
export { default as SwitchBox } from './switch-box/switch-box.svelte';
|
|
15
|
-
export { default as
|
|
15
|
+
export { default as TagBox } from './tag-box/tag-box.svelte';
|
|
16
16
|
export { default as TextArea } from './text-area/text-area.svelte';
|
|
17
17
|
export { default as TextBox } from './text-box/text-box.svelte';
|
|
18
18
|
export { default as TimeBox } from './time-box/time-box.svelte';
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
<FormField {size} {label} {id} {required} {disabled} {helperText} {feedback}>
|
|
33
33
|
<div>
|
|
34
34
|
{#each items as item}
|
|
35
|
-
<RadioBox bind:group {disabled} value={item.value}
|
|
35
|
+
<RadioBox bind:group {disabled} value={item.value} {onChange}>{item.name}</RadioBox>
|
|
36
36
|
{/each}
|
|
37
37
|
</div>
|
|
38
38
|
</FormField>
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { uniqueId } from '../../helpers/unique-id.js';
|
|
3
|
+
import FormField, { type FormFieldFeedback } from '../form-field/form-field.svelte';
|
|
4
|
+
import Chip from '../../generic/chip/chip.svelte';
|
|
5
|
+
import type { FormFieldSizeOptions } from '../../types/form.js';
|
|
6
|
+
|
|
7
|
+
const id = uniqueId();
|
|
8
|
+
const datalistId = uniqueId();
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
value = $bindable([] as string[]),
|
|
12
|
+
placeholder = 'Add a tag...',
|
|
13
|
+
required = false,
|
|
14
|
+
disabled = false,
|
|
15
|
+
autocomplete = [] as string[],
|
|
16
|
+
separators = [',', ';'] as string[],
|
|
17
|
+
size = 'full' as FormFieldSizeOptions,
|
|
18
|
+
label = undefined as string | undefined,
|
|
19
|
+
helperText = undefined as string | undefined,
|
|
20
|
+
feedback = undefined as FormFieldFeedback | undefined,
|
|
21
|
+
showAddButton = false,
|
|
22
|
+
onChange = undefined as ((value: string[]) => void) | undefined
|
|
23
|
+
}: {
|
|
24
|
+
value?: string[];
|
|
25
|
+
placeholder?: string;
|
|
26
|
+
required?: boolean;
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
autocomplete?: string[];
|
|
29
|
+
separators?: string[];
|
|
30
|
+
size?: FormFieldSizeOptions;
|
|
31
|
+
label?: string;
|
|
32
|
+
helperText?: string;
|
|
33
|
+
feedback?: FormFieldFeedback;
|
|
34
|
+
showAddButton?: boolean;
|
|
35
|
+
onChange?: ((value: string[]) => void) | undefined;
|
|
36
|
+
} = $props();
|
|
37
|
+
|
|
38
|
+
let newTag = $state('');
|
|
39
|
+
|
|
40
|
+
function addTag(tagToAdd?: string) {
|
|
41
|
+
const tag = tagToAdd || newTag.trim();
|
|
42
|
+
if (tag && !value.includes(tag)) {
|
|
43
|
+
value = [...value, tag];
|
|
44
|
+
newTag = '';
|
|
45
|
+
onChange?.(value);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function removeTag(tagToRemove: string) {
|
|
50
|
+
value = value.filter((tag) => tag !== tagToRemove);
|
|
51
|
+
onChange?.(value);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
55
|
+
if (event.key === 'Enter') {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
addTag();
|
|
58
|
+
} else if (event.key === 'Backspace' && newTag === '' && value.length > 0) {
|
|
59
|
+
removeTag(value[value.length - 1]);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function handleInput(event: Event) {
|
|
64
|
+
const input = event.target as HTMLInputElement;
|
|
65
|
+
const inputValue = input.value;
|
|
66
|
+
|
|
67
|
+
// Check if the last character is a separator
|
|
68
|
+
if (inputValue.length > 0) {
|
|
69
|
+
const lastChar = inputValue[inputValue.length - 1];
|
|
70
|
+
if (separators.includes(lastChar)) {
|
|
71
|
+
// Extract the tag before the separator
|
|
72
|
+
const tagBeforeSeparator = inputValue.slice(0, -1).trim();
|
|
73
|
+
if (tagBeforeSeparator) {
|
|
74
|
+
// Prevent the separator from being added
|
|
75
|
+
newTag = tagBeforeSeparator;
|
|
76
|
+
// Add the tag
|
|
77
|
+
addTag(tagBeforeSeparator);
|
|
78
|
+
} else {
|
|
79
|
+
// If there's no text before the separator, just clear it
|
|
80
|
+
newTag = '';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<FormField {size} {label} {id} {required} {disabled} {helperText} {feedback}>
|
|
88
|
+
<div class="tag-box">
|
|
89
|
+
<div class="input-container">
|
|
90
|
+
<div class="input {disabled ? 'disabled' : 'enabled'}">
|
|
91
|
+
<input
|
|
92
|
+
{id}
|
|
93
|
+
type="text"
|
|
94
|
+
bind:value={newTag}
|
|
95
|
+
{placeholder}
|
|
96
|
+
onkeydown={handleKeydown}
|
|
97
|
+
oninput={handleInput}
|
|
98
|
+
{disabled}
|
|
99
|
+
{required}
|
|
100
|
+
list={autocomplete.length > 0 ? datalistId : undefined}
|
|
101
|
+
aria-label="Tag input"
|
|
102
|
+
/>
|
|
103
|
+
{#if autocomplete.length > 0}
|
|
104
|
+
<datalist id={datalistId}>
|
|
105
|
+
{#each autocomplete as option}
|
|
106
|
+
<option value={option}></option>
|
|
107
|
+
{/each}
|
|
108
|
+
</datalist>
|
|
109
|
+
{/if}
|
|
110
|
+
</div>
|
|
111
|
+
{#if showAddButton}
|
|
112
|
+
<button
|
|
113
|
+
type="button"
|
|
114
|
+
class="add-button"
|
|
115
|
+
onclick={() => addTag()}
|
|
116
|
+
disabled={disabled || !newTag.trim()}
|
|
117
|
+
aria-label="Add tag"
|
|
118
|
+
>
|
|
119
|
+
Add
|
|
120
|
+
</button>
|
|
121
|
+
{/if}
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
{#if value.length > 0}
|
|
125
|
+
<div class="tags">
|
|
126
|
+
{#each value as tag}
|
|
127
|
+
<Chip label={tag} removable={true} onRemove={() => removeTag(tag)} />
|
|
128
|
+
{/each}
|
|
129
|
+
</div>
|
|
130
|
+
{/if}
|
|
131
|
+
</div>
|
|
132
|
+
</FormField>
|
|
133
|
+
|
|
134
|
+
<style>.tag-box {
|
|
135
|
+
display: flex;
|
|
136
|
+
flex-direction: column;
|
|
137
|
+
gap: var(--spacing-sm);
|
|
138
|
+
width: 100%;
|
|
139
|
+
}
|
|
140
|
+
.tag-box .input-container {
|
|
141
|
+
display: flex;
|
|
142
|
+
gap: var(--spacing-sm);
|
|
143
|
+
align-items: stretch;
|
|
144
|
+
}
|
|
145
|
+
.tag-box .input-container .input {
|
|
146
|
+
display: flex;
|
|
147
|
+
align-items: center;
|
|
148
|
+
justify-content: flex-start;
|
|
149
|
+
position: relative;
|
|
150
|
+
width: 100%;
|
|
151
|
+
height: 100%;
|
|
152
|
+
border-radius: var(--radius-md);
|
|
153
|
+
border: var(--border-thin) solid var(--form-input-border);
|
|
154
|
+
background-color: var(--form-input-bg);
|
|
155
|
+
color: var(--form-input-fg);
|
|
156
|
+
font-size: var(--font-md);
|
|
157
|
+
font-weight: 500;
|
|
158
|
+
line-height: 2rem;
|
|
159
|
+
transition: background-color var(--transition-base) var(--ease-in-out), border-color var(--transition-base) var(--ease-in-out), color var(--transition-base) var(--ease-in-out), fill var(--transition-base) var(--ease-in-out), stroke var(--transition-base) var(--ease-in-out);
|
|
160
|
+
user-select: none;
|
|
161
|
+
white-space: nowrap;
|
|
162
|
+
flex: 1;
|
|
163
|
+
}
|
|
164
|
+
.tag-box .input-container .input.disabled {
|
|
165
|
+
opacity: 0.5;
|
|
166
|
+
}
|
|
167
|
+
.tag-box .input-container .input input {
|
|
168
|
+
background-color: transparent;
|
|
169
|
+
border: none;
|
|
170
|
+
line-height: 2rem;
|
|
171
|
+
font-size: var(--font-md);
|
|
172
|
+
width: 100%;
|
|
173
|
+
flex-grow: 1;
|
|
174
|
+
padding-left: var(--spacing-base);
|
|
175
|
+
padding-right: var(--spacing-base);
|
|
176
|
+
}
|
|
177
|
+
.tag-box .input-container .input input:focus {
|
|
178
|
+
outline: none;
|
|
179
|
+
}
|
|
180
|
+
.tag-box .input-container .input input:focus-visible {
|
|
181
|
+
outline: 2px solid var(--focus-ring, #007bff);
|
|
182
|
+
outline-offset: 2px;
|
|
183
|
+
}
|
|
184
|
+
.tag-box .input-container .input input:disabled {
|
|
185
|
+
cursor: not-allowed;
|
|
186
|
+
}
|
|
187
|
+
.tag-box .input-container .input input::placeholder {
|
|
188
|
+
color: var(--form-input-placeholder);
|
|
189
|
+
}
|
|
190
|
+
.tag-box .input-container .add-button {
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: center;
|
|
193
|
+
justify-content: center;
|
|
194
|
+
padding: 0 var(--spacing-base);
|
|
195
|
+
background-color: var(--button-primary-bg);
|
|
196
|
+
color: var(--button-primary-fg);
|
|
197
|
+
border: var(--border-thin) solid var(--button-primary-border);
|
|
198
|
+
border-radius: var(--radius-md);
|
|
199
|
+
font-size: var(--font-sm);
|
|
200
|
+
font-weight: 500;
|
|
201
|
+
cursor: pointer;
|
|
202
|
+
transition: background-color var(--transition-base) var(--ease-in-out), border-color var(--transition-base) var(--ease-in-out), color var(--transition-base) var(--ease-in-out);
|
|
203
|
+
white-space: nowrap;
|
|
204
|
+
height: 100%;
|
|
205
|
+
line-height: 2rem;
|
|
206
|
+
}
|
|
207
|
+
.tag-box .input-container .add-button:hover:not(:disabled) {
|
|
208
|
+
background-color: var(--button-primary-hover-bg);
|
|
209
|
+
color: var(--button-primary-hover-fg);
|
|
210
|
+
}
|
|
211
|
+
.tag-box .input-container .add-button:disabled {
|
|
212
|
+
background-color: var(--gray-400);
|
|
213
|
+
border-color: var(--gray-400);
|
|
214
|
+
color: var(--gray-600);
|
|
215
|
+
cursor: not-allowed;
|
|
216
|
+
opacity: 0.6;
|
|
217
|
+
}
|
|
218
|
+
.tag-box .input-container .add-button:active:not(:disabled) {
|
|
219
|
+
transform: scale(0.98);
|
|
220
|
+
}
|
|
221
|
+
.tag-box .tags {
|
|
222
|
+
display: flex;
|
|
223
|
+
flex-wrap: wrap;
|
|
224
|
+
gap: var(--spacing-sm);
|
|
225
|
+
}</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type FormFieldFeedback } from '../form-field/form-field.svelte';
|
|
2
|
+
import type { FormFieldSizeOptions } from '../../types/form.js';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
value?: string[];
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
autocomplete?: string[];
|
|
9
|
+
separators?: string[];
|
|
10
|
+
size?: FormFieldSizeOptions;
|
|
11
|
+
label?: string;
|
|
12
|
+
helperText?: string;
|
|
13
|
+
feedback?: FormFieldFeedback;
|
|
14
|
+
showAddButton?: boolean;
|
|
15
|
+
onChange?: ((value: string[]) => void) | undefined;
|
|
16
|
+
};
|
|
17
|
+
declare const TagBox: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
18
|
+
type TagBox = ReturnType<typeof TagBox>;
|
|
19
|
+
export default TagBox;
|
|
@@ -19,9 +19,7 @@
|
|
|
19
19
|
<div class="chip {size} {variant}">
|
|
20
20
|
<span class="label">{label}</span>
|
|
21
21
|
{#if removable}
|
|
22
|
-
<button type="button" class="remove" onclick={onRemove} aria-label="Remove {label}">
|
|
23
|
-
×
|
|
24
|
-
</button>
|
|
22
|
+
<button type="button" class="remove" onclick={onRemove} aria-label="Remove {label}"> × </button>
|
|
25
23
|
{/if}
|
|
26
24
|
</div>
|
|
27
25
|
|
|
@@ -83,14 +81,3 @@
|
|
|
83
81
|
background-color: var(--chip-negative-bg, #ffcdd2);
|
|
84
82
|
color: var(--chip-negative-fg, #c62828);
|
|
85
83
|
}</style>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import FlexRow from '../../layout/flex-row.svelte';
|
|
4
3
|
import type { SectionLevel } from '../../types/generic.js';
|
|
5
4
|
import Headline from '../../typography/headline.svelte';
|
|
6
5
|
import Subtitle from '../../typography/subtitle.svelte';
|
|
7
6
|
import { getContext } from 'svelte';
|
|
7
|
+
import Paragraph from '../../typography/paragraph.svelte';
|
|
8
8
|
|
|
9
9
|
const section: { title: string; level: SectionLevel } | undefined = getContext('section');
|
|
10
10
|
|
|
@@ -12,38 +12,46 @@
|
|
|
12
12
|
level = (section?.level || 2) as SectionLevel,
|
|
13
13
|
title = section?.title || '',
|
|
14
14
|
subtitle = '',
|
|
15
|
+
description = '',
|
|
15
16
|
underline = false,
|
|
16
17
|
children = undefined
|
|
17
18
|
}: {
|
|
18
19
|
level?: SectionLevel;
|
|
19
|
-
title?: string;
|
|
20
|
-
subtitle?: string;
|
|
20
|
+
title?: string | undefined;
|
|
21
|
+
subtitle?: string | undefined;
|
|
22
|
+
description?: string | undefined;
|
|
21
23
|
underline?: boolean;
|
|
22
|
-
children?: Snippet;
|
|
24
|
+
children?: Snippet | undefined;
|
|
23
25
|
} = $props();
|
|
24
26
|
</script>
|
|
25
27
|
|
|
26
28
|
<header class:underline data-level={level}>
|
|
27
|
-
<
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
29
|
+
<hgroup>
|
|
30
|
+
<Headline {level}>{title}</Headline>
|
|
31
|
+
{#if subtitle}
|
|
32
|
+
<Subtitle {level}>{subtitle}</Subtitle>
|
|
33
|
+
{/if}
|
|
34
|
+
{#if description}
|
|
35
|
+
<Paragraph>{description}</Paragraph>
|
|
36
|
+
{/if}
|
|
37
|
+
</hgroup>
|
|
38
|
+
<div>
|
|
39
|
+
{#if children}
|
|
40
|
+
{@render children?.()}
|
|
41
|
+
{/if}
|
|
42
|
+
</div>
|
|
40
43
|
</header>
|
|
41
44
|
|
|
42
45
|
<style>header {
|
|
43
|
-
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: row;
|
|
48
|
+
align-items: stretch;
|
|
49
|
+
justify-content: space-between;
|
|
50
|
+
gap: var(--spacing-base, 1rem);
|
|
51
|
+
margin-bottom: var(--spacing-base, 1rem);
|
|
44
52
|
font-family: var(--base-headline-font-family, sans-serif);
|
|
45
53
|
}
|
|
46
54
|
header.underline {
|
|
47
|
-
padding-bottom: 0.
|
|
48
|
-
border-bottom: solid 1px
|
|
55
|
+
padding-bottom: var(--spacing-xs, 0.25rem);
|
|
56
|
+
border-bottom: solid var(--border-thin, 1px) var(--divider-color, rgba(127, 127, 127, 0.5));
|
|
49
57
|
}</style>
|
|
@@ -2,10 +2,11 @@ import type { Snippet } from 'svelte';
|
|
|
2
2
|
import type { SectionLevel } from '../../types/generic.js';
|
|
3
3
|
type $$ComponentProps = {
|
|
4
4
|
level?: SectionLevel;
|
|
5
|
-
title?: string;
|
|
6
|
-
subtitle?: string;
|
|
5
|
+
title?: string | undefined;
|
|
6
|
+
subtitle?: string | undefined;
|
|
7
|
+
description?: string | undefined;
|
|
7
8
|
underline?: boolean;
|
|
8
|
-
children?: Snippet;
|
|
9
|
+
children?: Snippet | undefined;
|
|
9
10
|
};
|
|
10
11
|
declare const Header: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
11
12
|
type Header = ReturnType<typeof Header>;
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
.rating .star.filled {
|
|
60
60
|
color: var(--rating-filled-color, #ffc107);
|
|
61
61
|
}
|
|
62
|
-
.rating .star:hover:not(
|
|
62
|
+
.rating .star:hover:not(:disabled) {
|
|
63
63
|
color: var(--rating-hover-color, #ffb300);
|
|
64
64
|
}
|
|
65
|
-
.rating .star
|
|
65
|
+
.rating .star:disabled {
|
|
66
66
|
cursor: default;
|
|
67
67
|
}
|
|
68
68
|
.rating .star:focus {
|
|
@@ -82,4 +82,3 @@
|
|
|
82
82
|
.rating.xl .star {
|
|
83
83
|
font-size: 2.5rem;
|
|
84
84
|
}</style>
|
|
85
|
-
|
|
@@ -21,9 +21,13 @@
|
|
|
21
21
|
children: Snippet;
|
|
22
22
|
} = $props();
|
|
23
23
|
|
|
24
|
-
setContext('section', {
|
|
25
|
-
get level() {
|
|
26
|
-
|
|
24
|
+
setContext('section', {
|
|
25
|
+
get level() {
|
|
26
|
+
return level;
|
|
27
|
+
},
|
|
28
|
+
get title() {
|
|
29
|
+
return title;
|
|
30
|
+
}
|
|
27
31
|
});
|
|
28
32
|
</script>
|
|
29
33
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
/**
|
|
3
3
|
* Theme Provider Demo Component
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* Demonstrates theme switching functionality with example components.
|
|
6
6
|
*/
|
|
7
7
|
import ThemeProvider from './theme-provider.svelte';
|
|
@@ -29,43 +29,41 @@
|
|
|
29
29
|
<Card>
|
|
30
30
|
<div style="padding: 1.5rem; margin-bottom: 2rem;">
|
|
31
31
|
<h2 style="margin-top: 0; margin-bottom: 1rem;">Theme Controls</h2>
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
<div style="display: flex; gap: 0.5rem; margin-bottom: 1rem; flex-wrap: wrap;">
|
|
34
|
-
<Button
|
|
34
|
+
<Button
|
|
35
35
|
variant={theme.current === 'light' ? 'primary' : 'outline'}
|
|
36
36
|
onClick={() => theme.set('light')}
|
|
37
37
|
>
|
|
38
38
|
☀️ Light
|
|
39
39
|
</Button>
|
|
40
|
-
<Button
|
|
40
|
+
<Button
|
|
41
41
|
variant={theme.current === 'dark' ? 'primary' : 'outline'}
|
|
42
42
|
onClick={() => theme.set('dark')}
|
|
43
43
|
>
|
|
44
44
|
🌙 Dark
|
|
45
45
|
</Button>
|
|
46
|
-
<Button
|
|
46
|
+
<Button
|
|
47
47
|
variant={theme.current === 'system' ? 'primary' : 'outline'}
|
|
48
48
|
onClick={() => theme.set('system')}
|
|
49
49
|
>
|
|
50
50
|
💻 System
|
|
51
51
|
</Button>
|
|
52
|
-
<Button
|
|
53
|
-
variant="secondary"
|
|
54
|
-
onClick={() => theme.toggle()}
|
|
55
|
-
>
|
|
56
|
-
🔄 Toggle
|
|
57
|
-
</Button>
|
|
52
|
+
<Button variant="secondary" onClick={() => theme.toggle()}>🔄 Toggle</Button>
|
|
58
53
|
</div>
|
|
59
54
|
|
|
60
55
|
<div style="display: flex; gap: 1rem; font-size: 0.875rem; color: var(--base-accent-fg);">
|
|
61
56
|
<div>
|
|
62
|
-
<strong>Current:</strong>
|
|
57
|
+
<strong>Current:</strong>
|
|
58
|
+
{theme.current}
|
|
63
59
|
</div>
|
|
64
60
|
<div>
|
|
65
|
-
<strong>Resolved:</strong>
|
|
61
|
+
<strong>Resolved:</strong>
|
|
62
|
+
{theme.resolved}
|
|
66
63
|
</div>
|
|
67
64
|
<div>
|
|
68
|
-
<strong>Is Dark:</strong>
|
|
65
|
+
<strong>Is Dark:</strong>
|
|
66
|
+
{theme.isDark}
|
|
69
67
|
</div>
|
|
70
68
|
</div>
|
|
71
69
|
</div>
|
|
@@ -108,18 +106,10 @@
|
|
|
108
106
|
<div style="padding: 1.5rem;">
|
|
109
107
|
<h4 style="margin-top: 0; margin-bottom: 1rem;">Notices</h4>
|
|
110
108
|
<div style="display: grid; gap: 0.75rem;">
|
|
111
|
-
<Notice variant="info">
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Operation completed successfully!
|
|
116
|
-
</Notice>
|
|
117
|
-
<Notice variant="attention">
|
|
118
|
-
Please review your changes carefully.
|
|
119
|
-
</Notice>
|
|
120
|
-
<Notice variant="error">
|
|
121
|
-
An error occurred while processing your request.
|
|
122
|
-
</Notice>
|
|
109
|
+
<Notice variant="info">This is an informational message.</Notice>
|
|
110
|
+
<Notice variant="success">Operation completed successfully!</Notice>
|
|
111
|
+
<Notice variant="attention">Please review your changes carefully.</Notice>
|
|
112
|
+
<Notice variant="error">An error occurred while processing your request.</Notice>
|
|
123
113
|
</div>
|
|
124
114
|
</div>
|
|
125
115
|
</Card>
|
|
@@ -129,28 +119,13 @@
|
|
|
129
119
|
<div style="padding: 1.5rem;">
|
|
130
120
|
<h4 style="margin-top: 0; margin-bottom: 1rem;">Form Inputs</h4>
|
|
131
121
|
<div style="display: grid; gap: 1rem; max-width: 500px;">
|
|
132
|
-
<TextBox
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
/>
|
|
137
|
-
|
|
138
|
-
<
|
|
139
|
-
bind:value={textAreaValue}
|
|
140
|
-
label="Text Area"
|
|
141
|
-
rows={4}
|
|
142
|
-
/>
|
|
143
|
-
|
|
144
|
-
<CheckBox
|
|
145
|
-
bind:isChecked={checked}
|
|
146
|
-
label="Check Box Option"
|
|
147
|
-
/>
|
|
148
|
-
|
|
149
|
-
<SwitchBox
|
|
150
|
-
bind:checked={switchOn}
|
|
151
|
-
>
|
|
152
|
-
Switch Option
|
|
153
|
-
</SwitchBox>
|
|
122
|
+
<TextBox bind:value={textValue} label="Text Input" placeholder="Enter some text..." />
|
|
123
|
+
|
|
124
|
+
<TextArea bind:value={textAreaValue} label="Text Area" rows={4} />
|
|
125
|
+
|
|
126
|
+
<CheckBox bind:isChecked={checked} label="Check Box Option" />
|
|
127
|
+
|
|
128
|
+
<SwitchBox bind:checked={switchOn}>Switch Option</SwitchBox>
|
|
154
129
|
</div>
|
|
155
130
|
</div>
|
|
156
131
|
</Card>
|
|
@@ -159,24 +134,23 @@
|
|
|
159
134
|
<Card>
|
|
160
135
|
<div style="padding: 1.5rem;">
|
|
161
136
|
<h4 style="margin-top: 0; margin-bottom: 1rem;">Typography</h4>
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
137
|
+
<p style="margin-bottom: 0.5rem;">
|
|
138
|
+
This is regular text using the base foreground color.
|
|
139
|
+
</p>
|
|
140
|
+
<p style="margin-bottom: 0.5rem;">
|
|
141
|
+
<button
|
|
142
|
+
type="button"
|
|
143
|
+
style="background: none; border: none; padding: 0; color: var(--base-link-fg); text-decoration: underline; cursor: pointer; font: inherit;"
|
|
144
|
+
onclick={() => {}}
|
|
145
|
+
>
|
|
146
|
+
This is a link
|
|
147
|
+
</button> with proper link styling.
|
|
148
|
+
</p>
|
|
149
|
+
<p style="margin-bottom: 0; color: var(--base-accent-fg); font-size: 0.875rem;">
|
|
150
|
+
This is accent text using a muted color.
|
|
151
|
+
</p>
|
|
177
152
|
</div>
|
|
178
153
|
</Card>
|
|
179
154
|
</div>
|
|
180
155
|
</div>
|
|
181
156
|
</ThemeProvider>
|
|
182
|
-
|