@hyvnt/hyvui 0.1.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 +253 -0
- package/dist/components/ambient/CornerBrackets.svelte +87 -0
- package/dist/components/ambient/CornerBrackets.svelte.d.ts +11 -0
- package/dist/components/ambient/DataStream.svelte +94 -0
- package/dist/components/ambient/DataStream.svelte.d.ts +13 -0
- package/dist/components/ambient/GlyphMark.svelte +69 -0
- package/dist/components/ambient/GlyphMark.svelte.d.ts +13 -0
- package/dist/components/ambient/GridOverlay.svelte +28 -0
- package/dist/components/ambient/GridOverlay.svelte.d.ts +7 -0
- package/dist/components/ambient/ParallaxLayer.svelte +41 -0
- package/dist/components/ambient/ParallaxLayer.svelte.d.ts +12 -0
- package/dist/components/ambient/ScanBand.svelte +91 -0
- package/dist/components/ambient/ScanBand.svelte.d.ts +17 -0
- package/dist/components/ambient/SignalRing.svelte +100 -0
- package/dist/components/ambient/SignalRing.svelte.d.ts +13 -0
- package/dist/components/ambient/ThreadLine.svelte +78 -0
- package/dist/components/ambient/ThreadLine.svelte.d.ts +17 -0
- package/dist/components/ambient/Vignette.svelte +26 -0
- package/dist/components/ambient/Vignette.svelte.d.ts +7 -0
- package/dist/components/depth/DepthLayer.svelte +27 -0
- package/dist/components/depth/DepthLayer.svelte.d.ts +15 -0
- package/dist/components/depth/DepthStage.svelte +62 -0
- package/dist/components/depth/DepthStage.svelte.d.ts +19 -0
- package/dist/components/depth/FloatCard.svelte +104 -0
- package/dist/components/depth/FloatCard.svelte.d.ts +14 -0
- package/dist/components/depth/HorizonGrid.svelte +160 -0
- package/dist/components/depth/HorizonGrid.svelte.d.ts +15 -0
- package/dist/components/depth/Plinth.svelte +57 -0
- package/dist/components/depth/Plinth.svelte.d.ts +13 -0
- package/dist/components/display/Avatar.svelte +69 -0
- package/dist/components/display/Avatar.svelte.d.ts +13 -0
- package/dist/components/display/Badge.svelte +63 -0
- package/dist/components/display/Badge.svelte.d.ts +12 -0
- package/dist/components/display/Blockquote.svelte +34 -0
- package/dist/components/display/Blockquote.svelte.d.ts +10 -0
- package/dist/components/display/CodeBlock.svelte +76 -0
- package/dist/components/display/CodeBlock.svelte.d.ts +13 -0
- package/dist/components/display/MetricCard.svelte +83 -0
- package/dist/components/display/MetricCard.svelte.d.ts +15 -0
- package/dist/components/display/Table.svelte +104 -0
- package/dist/components/display/Table.svelte.d.ts +19 -0
- package/dist/components/feedback/Alert.svelte +76 -0
- package/dist/components/feedback/Alert.svelte.d.ts +14 -0
- package/dist/components/feedback/EmptyState.svelte +68 -0
- package/dist/components/feedback/EmptyState.svelte.d.ts +14 -0
- package/dist/components/feedback/ErrorState.svelte +73 -0
- package/dist/components/feedback/ErrorState.svelte.d.ts +15 -0
- package/dist/components/feedback/Skeleton.svelte +52 -0
- package/dist/components/feedback/Skeleton.svelte.d.ts +13 -0
- package/dist/components/feedback/StatusDot.svelte +54 -0
- package/dist/components/feedback/StatusDot.svelte.d.ts +13 -0
- package/dist/components/feedback/StatusLine.svelte +122 -0
- package/dist/components/feedback/StatusLine.svelte.d.ts +17 -0
- package/dist/components/feedback/Toast.svelte +136 -0
- package/dist/components/feedback/Toast.svelte.d.ts +21 -0
- package/dist/components/inputs/Button.svelte +237 -0
- package/dist/components/inputs/Button.svelte.d.ts +30 -0
- package/dist/components/inputs/Checkbox.svelte +105 -0
- package/dist/components/inputs/Checkbox.svelte.d.ts +15 -0
- package/dist/components/inputs/FileUpload.svelte +163 -0
- package/dist/components/inputs/FileUpload.svelte.d.ts +17 -0
- package/dist/components/inputs/Input.svelte +147 -0
- package/dist/components/inputs/Input.svelte.d.ts +25 -0
- package/dist/components/inputs/Select.svelte +150 -0
- package/dist/components/inputs/Select.svelte.d.ts +23 -0
- package/dist/components/inputs/Textarea.svelte +154 -0
- package/dist/components/inputs/Textarea.svelte.d.ts +25 -0
- package/dist/components/inputs/Toggle.svelte +120 -0
- package/dist/components/inputs/Toggle.svelte.d.ts +15 -0
- package/dist/components/layout/Card.svelte +76 -0
- package/dist/components/layout/Card.svelte.d.ts +16 -0
- package/dist/components/layout/Drawer.svelte +109 -0
- package/dist/components/layout/Drawer.svelte.d.ts +18 -0
- package/dist/components/layout/Grid.svelte +43 -0
- package/dist/components/layout/Grid.svelte.d.ts +16 -0
- package/dist/components/layout/Modal.svelte +159 -0
- package/dist/components/layout/Modal.svelte.d.ts +20 -0
- package/dist/components/layout/Panel.svelte +54 -0
- package/dist/components/layout/Panel.svelte.d.ts +14 -0
- package/dist/components/layout/Popover.svelte +67 -0
- package/dist/components/layout/Popover.svelte.d.ts +14 -0
- package/dist/components/layout/Stack.svelte +53 -0
- package/dist/components/layout/Stack.svelte.d.ts +22 -0
- package/dist/components/navigation/Breadcrumb.svelte +73 -0
- package/dist/components/navigation/Breadcrumb.svelte.d.ts +13 -0
- package/dist/components/navigation/DropdownMenu.svelte +124 -0
- package/dist/components/navigation/DropdownMenu.svelte.d.ts +19 -0
- package/dist/components/navigation/SidebarNav.svelte +90 -0
- package/dist/components/navigation/SidebarNav.svelte.d.ts +16 -0
- package/dist/components/navigation/Tabs.svelte +86 -0
- package/dist/components/navigation/Tabs.svelte.d.ts +17 -0
- package/dist/components/navigation/Topbar.svelte +85 -0
- package/dist/components/navigation/Topbar.svelte.d.ts +14 -0
- package/dist/components/patterns/ActionBar.svelte +76 -0
- package/dist/components/patterns/ActionBar.svelte.d.ts +14 -0
- package/dist/components/patterns/ConfirmDialog.svelte +64 -0
- package/dist/components/patterns/ConfirmDialog.svelte.d.ts +23 -0
- package/dist/components/patterns/PageHeader.svelte +114 -0
- package/dist/components/patterns/PageHeader.svelte.d.ts +16 -0
- package/dist/components/patterns/SearchBar.svelte +59 -0
- package/dist/components/patterns/SearchBar.svelte.d.ts +15 -0
- package/dist/components/patterns/TerminalBoot.svelte +104 -0
- package/dist/components/patterns/TerminalBoot.svelte.d.ts +25 -0
- package/dist/components/primitives/Divider.svelte +29 -0
- package/dist/components/primitives/Divider.svelte.d.ts +9 -0
- package/dist/components/primitives/Icon.svelte +49 -0
- package/dist/components/primitives/Icon.svelte.d.ts +14 -0
- package/dist/components/primitives/Label.svelte +44 -0
- package/dist/components/primitives/Label.svelte.d.ts +14 -0
- package/dist/components/primitives/Surface.svelte +87 -0
- package/dist/components/primitives/Surface.svelte.d.ts +16 -0
- package/dist/components/primitives/Text.svelte +98 -0
- package/dist/components/primitives/Text.svelte.d.ts +19 -0
- package/dist/components/primitives/text.d.ts +1 -0
- package/dist/components/primitives/text.js +1 -0
- package/dist/components/scenes/ArchiveScene.svelte +95 -0
- package/dist/components/scenes/ArchiveScene.svelte.d.ts +16 -0
- package/dist/components/scenes/LogScene.svelte +77 -0
- package/dist/components/scenes/LogScene.svelte.d.ts +14 -0
- package/dist/components/scenes/NarrativeScene.svelte +92 -0
- package/dist/components/scenes/NarrativeScene.svelte.d.ts +16 -0
- package/dist/components/scenes/ReadoutScene.svelte +107 -0
- package/dist/components/scenes/ReadoutScene.svelte.d.ts +16 -0
- package/dist/components/scenes/StageScene.svelte +104 -0
- package/dist/components/scenes/StageScene.svelte.d.ts +18 -0
- package/dist/examples/FieldReport.svelte +223 -0
- package/dist/examples/FieldReport.svelte.d.ts +18 -0
- package/dist/examples/ObservationDeck.svelte +317 -0
- package/dist/examples/ObservationDeck.svelte.d.ts +3 -0
- package/dist/examples/SignalLost.svelte +191 -0
- package/dist/examples/SignalLost.svelte.d.ts +3 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.js +83 -0
- package/dist/system/actions/echo.d.ts +10 -0
- package/dist/system/actions/echo.js +46 -0
- package/dist/system/actions/resolve.d.ts +23 -0
- package/dist/system/actions/resolve.js +59 -0
- package/dist/system/actions/reveal.d.ts +18 -0
- package/dist/system/actions/reveal.js +54 -0
- package/dist/system/actions/surface.d.ts +14 -0
- package/dist/system/actions/surface.js +25 -0
- package/dist/system/depth/depth.css +49 -0
- package/dist/system/depth/depth.d.ts +15 -0
- package/dist/system/depth/depth.js +24 -0
- package/dist/system/expressions.css +80 -0
- package/dist/system/override-template.css +72 -0
- package/dist/system/register.css +74 -0
- package/dist/system/register.d.ts +11 -0
- package/dist/system/register.js +16 -0
- package/dist/tokens/tokens.css +86 -0
- package/dist/tokens/tokens.d.ts +25 -0
- package/dist/tokens/tokens.js +25 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/utils/cn.js +4 -0
- package/dist/utils/motion.d.ts +17 -0
- package/dist/utils/motion.js +11 -0
- package/package.json +60 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
/** Accepted file types (e.g. "image/*"). */
|
|
3
|
+
accept?: string;
|
|
4
|
+
/** Allow multiple file selection. */
|
|
5
|
+
multiple?: boolean;
|
|
6
|
+
/** Disables the upload zone. */
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
/** Label text displayed in the zone. */
|
|
9
|
+
label?: string;
|
|
10
|
+
/** Additional CSS classes. */
|
|
11
|
+
class?: string;
|
|
12
|
+
/** Fires with the selected files. */
|
|
13
|
+
onfiles?: (files: File[]) => void;
|
|
14
|
+
}
|
|
15
|
+
declare const FileUpload: import("svelte").Component<Props, {}, "">;
|
|
16
|
+
type FileUpload = ReturnType<typeof FileUpload>;
|
|
17
|
+
export default FileUpload;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../utils/cn.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
/** Input type. */
|
|
6
|
+
type?: 'text' | 'number' | 'password' | 'email' | 'search';
|
|
7
|
+
/** Current value (bindable). */
|
|
8
|
+
value?: string;
|
|
9
|
+
/** Placeholder text. */
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
/** Disables the input. */
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
/** Error message. Displays below the input and activates error styling. */
|
|
14
|
+
error?: string;
|
|
15
|
+
/** Hint text displayed below the input. */
|
|
16
|
+
hint?: string;
|
|
17
|
+
/** Label text displayed above the input. */
|
|
18
|
+
label?: string;
|
|
19
|
+
/** Additional CSS classes. */
|
|
20
|
+
class?: string;
|
|
21
|
+
/** Input handler. */
|
|
22
|
+
oninput?: (e: Event) => void;
|
|
23
|
+
/** Change handler. */
|
|
24
|
+
onchange?: (e: Event) => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let {
|
|
28
|
+
type = 'text',
|
|
29
|
+
value = $bindable(''),
|
|
30
|
+
placeholder = '',
|
|
31
|
+
disabled = false,
|
|
32
|
+
error = '',
|
|
33
|
+
hint = '',
|
|
34
|
+
label = '',
|
|
35
|
+
class: className = '',
|
|
36
|
+
oninput,
|
|
37
|
+
onchange,
|
|
38
|
+
}: Props = $props();
|
|
39
|
+
|
|
40
|
+
const inputId = `hyvui-input-${Math.random().toString(36).slice(2, 8)}`;
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<div class={cn('hyvui-input-wrap', className)}>
|
|
44
|
+
{#if label}
|
|
45
|
+
<label class="hyvui-input-label" for={inputId}>{label}</label>
|
|
46
|
+
{/if}
|
|
47
|
+
<input
|
|
48
|
+
id={inputId}
|
|
49
|
+
{type}
|
|
50
|
+
bind:value
|
|
51
|
+
{placeholder}
|
|
52
|
+
{disabled}
|
|
53
|
+
class={cn('hyvui-input', error && 'hyvui-input-error')}
|
|
54
|
+
{oninput}
|
|
55
|
+
{onchange}
|
|
56
|
+
/>
|
|
57
|
+
{#if error}
|
|
58
|
+
<span class="hyvui-input-message hyvui-input-message-error">{error}</span>
|
|
59
|
+
{:else if hint}
|
|
60
|
+
<span class="hyvui-input-message">{hint}</span>
|
|
61
|
+
{/if}
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<style>
|
|
65
|
+
.hyvui-input-wrap {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
gap: var(--space-xs);
|
|
69
|
+
min-width: 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.hyvui-input-label {
|
|
73
|
+
font-family: var(--font-mono);
|
|
74
|
+
font-size: 0.7rem;
|
|
75
|
+
font-weight: 400;
|
|
76
|
+
letter-spacing: 0.16em;
|
|
77
|
+
text-transform: uppercase;
|
|
78
|
+
color: var(--muted-strong);
|
|
79
|
+
line-height: 1.2;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.hyvui-input {
|
|
83
|
+
font-family: var(--font-mono);
|
|
84
|
+
font-size: 0.82rem;
|
|
85
|
+
font-weight: 400;
|
|
86
|
+
color: var(--text);
|
|
87
|
+
min-height: var(--control-height-md);
|
|
88
|
+
background:
|
|
89
|
+
linear-gradient(180deg, rgba(240, 232, 218, 0.018), transparent 46%),
|
|
90
|
+
linear-gradient(135deg, rgba(199, 156, 87, 0.045), transparent 44%),
|
|
91
|
+
var(--bg-elev);
|
|
92
|
+
border: 1px solid var(--line);
|
|
93
|
+
border-radius: var(--radius-md);
|
|
94
|
+
padding: var(--control-pad-y) var(--control-pad-x);
|
|
95
|
+
outline: none;
|
|
96
|
+
transition:
|
|
97
|
+
border-color var(--transition-fast),
|
|
98
|
+
background var(--transition-fast),
|
|
99
|
+
box-shadow var(--transition-fast);
|
|
100
|
+
width: 100%;
|
|
101
|
+
box-shadow: inset 0 1px 0 rgba(240, 232, 218, 0.03);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.hyvui-input::placeholder {
|
|
105
|
+
color: var(--muted);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.hyvui-input:hover:not(:disabled) {
|
|
109
|
+
border-color: color-mix(in srgb, var(--line-strong) 82%, transparent);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.hyvui-input:focus {
|
|
113
|
+
border-color: var(--line-strong);
|
|
114
|
+
background:
|
|
115
|
+
linear-gradient(180deg, rgba(240, 232, 218, 0.022), transparent 46%),
|
|
116
|
+
linear-gradient(135deg, rgba(199, 156, 87, 0.06), transparent 44%),
|
|
117
|
+
var(--bg-elev);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.hyvui-input:disabled {
|
|
121
|
+
opacity: 0.4;
|
|
122
|
+
cursor: not-allowed;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.hyvui-input-error {
|
|
126
|
+
border-color: var(--status-fail);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.hyvui-input-message {
|
|
130
|
+
font-family: var(--font-mono);
|
|
131
|
+
font-size: 0.66rem;
|
|
132
|
+
letter-spacing: 0.14em;
|
|
133
|
+
text-transform: uppercase;
|
|
134
|
+
color: var(--muted-strong);
|
|
135
|
+
line-height: 1.3;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.hyvui-input-message-error {
|
|
139
|
+
color: var(--status-fail);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@media (prefers-reduced-motion: reduce) {
|
|
143
|
+
.hyvui-input {
|
|
144
|
+
transition: none;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
/** Input type. */
|
|
3
|
+
type?: 'text' | 'number' | 'password' | 'email' | 'search';
|
|
4
|
+
/** Current value (bindable). */
|
|
5
|
+
value?: string;
|
|
6
|
+
/** Placeholder text. */
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
/** Disables the input. */
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
/** Error message. Displays below the input and activates error styling. */
|
|
11
|
+
error?: string;
|
|
12
|
+
/** Hint text displayed below the input. */
|
|
13
|
+
hint?: string;
|
|
14
|
+
/** Label text displayed above the input. */
|
|
15
|
+
label?: string;
|
|
16
|
+
/** Additional CSS classes. */
|
|
17
|
+
class?: string;
|
|
18
|
+
/** Input handler. */
|
|
19
|
+
oninput?: (e: Event) => void;
|
|
20
|
+
/** Change handler. */
|
|
21
|
+
onchange?: (e: Event) => void;
|
|
22
|
+
}
|
|
23
|
+
declare const Input: import("svelte").Component<Props, {}, "value">;
|
|
24
|
+
type Input = ReturnType<typeof Input>;
|
|
25
|
+
export default Input;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../utils/cn.js';
|
|
3
|
+
|
|
4
|
+
interface SelectOption {
|
|
5
|
+
value: string;
|
|
6
|
+
label: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
/** Available options. */
|
|
11
|
+
options?: SelectOption[];
|
|
12
|
+
/** Current selected value (bindable). */
|
|
13
|
+
value?: string;
|
|
14
|
+
/** Label text displayed above the select. */
|
|
15
|
+
label?: string;
|
|
16
|
+
/** Error message. */
|
|
17
|
+
error?: string;
|
|
18
|
+
/** Disables the select. */
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
/** Additional CSS classes. */
|
|
21
|
+
class?: string;
|
|
22
|
+
/** Change handler. */
|
|
23
|
+
onchange?: (e: Event) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
options = [],
|
|
28
|
+
value = $bindable(''),
|
|
29
|
+
label = '',
|
|
30
|
+
error = '',
|
|
31
|
+
disabled = false,
|
|
32
|
+
class: className = '',
|
|
33
|
+
onchange,
|
|
34
|
+
}: Props = $props();
|
|
35
|
+
|
|
36
|
+
const selectId = `hyvui-select-${Math.random().toString(36).slice(2, 8)}`;
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<div class={cn('hyvui-select-wrap', className)}>
|
|
40
|
+
{#if label}
|
|
41
|
+
<label class="hyvui-select-label" for={selectId}>{label}</label>
|
|
42
|
+
{/if}
|
|
43
|
+
<div class="hyvui-select-container">
|
|
44
|
+
<select
|
|
45
|
+
id={selectId}
|
|
46
|
+
bind:value
|
|
47
|
+
{disabled}
|
|
48
|
+
class={cn('hyvui-select', error && 'hyvui-select-error')}
|
|
49
|
+
{onchange}
|
|
50
|
+
>
|
|
51
|
+
{#each options as opt}
|
|
52
|
+
<option value={opt.value}>{opt.label}</option>
|
|
53
|
+
{/each}
|
|
54
|
+
</select>
|
|
55
|
+
<svg class="hyvui-select-chevron" width="12" height="12" viewBox="0 0 12 12" aria-hidden="true">
|
|
56
|
+
<path d="M2.5 4.5L6 8L9.5 4.5" stroke="var(--accent)" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
57
|
+
</svg>
|
|
58
|
+
</div>
|
|
59
|
+
{#if error}
|
|
60
|
+
<span class="hyvui-select-message">{error}</span>
|
|
61
|
+
{/if}
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<style>
|
|
65
|
+
.hyvui-select-wrap {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
gap: var(--space-xs);
|
|
69
|
+
min-width: 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.hyvui-select-label {
|
|
73
|
+
font-family: var(--font-mono);
|
|
74
|
+
font-size: 0.7rem;
|
|
75
|
+
font-weight: 400;
|
|
76
|
+
letter-spacing: 0.16em;
|
|
77
|
+
text-transform: uppercase;
|
|
78
|
+
color: var(--muted-strong);
|
|
79
|
+
line-height: 1.2;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.hyvui-select-container {
|
|
83
|
+
position: relative;
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.hyvui-select {
|
|
89
|
+
font-family: var(--font-mono);
|
|
90
|
+
font-size: 0.82rem;
|
|
91
|
+
font-weight: 400;
|
|
92
|
+
color: var(--text);
|
|
93
|
+
min-height: var(--control-height-md);
|
|
94
|
+
background:
|
|
95
|
+
linear-gradient(180deg, rgba(240, 232, 218, 0.018), transparent 46%),
|
|
96
|
+
linear-gradient(135deg, rgba(199, 156, 87, 0.045), transparent 44%),
|
|
97
|
+
var(--bg-elev);
|
|
98
|
+
border: 1px solid var(--line);
|
|
99
|
+
border-radius: var(--radius-md);
|
|
100
|
+
padding: var(--control-pad-y) 2.3rem var(--control-pad-y) var(--control-pad-x);
|
|
101
|
+
outline: none;
|
|
102
|
+
appearance: none;
|
|
103
|
+
width: 100%;
|
|
104
|
+
cursor: pointer;
|
|
105
|
+
transition:
|
|
106
|
+
border-color var(--transition-fast),
|
|
107
|
+
background var(--transition-fast),
|
|
108
|
+
box-shadow var(--transition-fast);
|
|
109
|
+
box-shadow: inset 0 1px 0 rgba(240, 232, 218, 0.03);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.hyvui-select:hover:not(:disabled) {
|
|
113
|
+
border-color: color-mix(in srgb, var(--line-strong) 82%, transparent);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.hyvui-select:focus {
|
|
117
|
+
border-color: var(--line-strong);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.hyvui-select:disabled {
|
|
121
|
+
opacity: 0.4;
|
|
122
|
+
cursor: not-allowed;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.hyvui-select-error {
|
|
126
|
+
border-color: var(--status-fail);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.hyvui-select-chevron {
|
|
130
|
+
position: absolute;
|
|
131
|
+
right: 0.85rem;
|
|
132
|
+
pointer-events: none;
|
|
133
|
+
opacity: 0.8;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.hyvui-select-message {
|
|
137
|
+
font-family: var(--font-mono);
|
|
138
|
+
font-size: 0.66rem;
|
|
139
|
+
letter-spacing: 0.14em;
|
|
140
|
+
text-transform: uppercase;
|
|
141
|
+
color: var(--status-fail);
|
|
142
|
+
line-height: 1.3;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@media (prefers-reduced-motion: reduce) {
|
|
146
|
+
.hyvui-select {
|
|
147
|
+
transition: none;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface SelectOption {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
}
|
|
5
|
+
interface Props {
|
|
6
|
+
/** Available options. */
|
|
7
|
+
options?: SelectOption[];
|
|
8
|
+
/** Current selected value (bindable). */
|
|
9
|
+
value?: string;
|
|
10
|
+
/** Label text displayed above the select. */
|
|
11
|
+
label?: string;
|
|
12
|
+
/** Error message. */
|
|
13
|
+
error?: string;
|
|
14
|
+
/** Disables the select. */
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
/** Additional CSS classes. */
|
|
17
|
+
class?: string;
|
|
18
|
+
/** Change handler. */
|
|
19
|
+
onchange?: (e: Event) => void;
|
|
20
|
+
}
|
|
21
|
+
declare const Select: import("svelte").Component<Props, {}, "value">;
|
|
22
|
+
type Select = ReturnType<typeof Select>;
|
|
23
|
+
export default Select;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../utils/cn.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
/** Current value (bindable). */
|
|
6
|
+
value?: string;
|
|
7
|
+
/** Number of visible rows. */
|
|
8
|
+
rows?: number;
|
|
9
|
+
/** Placeholder text. */
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
/** Label text displayed above the textarea. */
|
|
12
|
+
label?: string;
|
|
13
|
+
/** Error message. */
|
|
14
|
+
error?: string;
|
|
15
|
+
/** Hint text. */
|
|
16
|
+
hint?: string;
|
|
17
|
+
/** Auto-expand height based on content. */
|
|
18
|
+
autoresize?: boolean;
|
|
19
|
+
/** Disables the textarea. */
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
/** Additional CSS classes. */
|
|
22
|
+
class?: string;
|
|
23
|
+
/** Input handler. */
|
|
24
|
+
oninput?: (e: Event) => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let {
|
|
28
|
+
value = $bindable(''),
|
|
29
|
+
rows = 4,
|
|
30
|
+
placeholder = '',
|
|
31
|
+
label = '',
|
|
32
|
+
error = '',
|
|
33
|
+
hint = '',
|
|
34
|
+
autoresize = false,
|
|
35
|
+
disabled = false,
|
|
36
|
+
class: className = '',
|
|
37
|
+
oninput,
|
|
38
|
+
}: Props = $props();
|
|
39
|
+
|
|
40
|
+
const textareaId = `hyvui-textarea-${Math.random().toString(36).slice(2, 8)}`;
|
|
41
|
+
|
|
42
|
+
let textareaEl: HTMLTextAreaElement | undefined = $state();
|
|
43
|
+
|
|
44
|
+
function handleInput(e: Event) {
|
|
45
|
+
if (autoresize && textareaEl) {
|
|
46
|
+
textareaEl.style.height = 'auto';
|
|
47
|
+
textareaEl.style.height = textareaEl.scrollHeight + 'px';
|
|
48
|
+
}
|
|
49
|
+
oninput?.(e);
|
|
50
|
+
}
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<div class={cn('hyvui-textarea-wrap', className)}>
|
|
54
|
+
{#if label}
|
|
55
|
+
<label class="hyvui-textarea-label" for={textareaId}>{label}</label>
|
|
56
|
+
{/if}
|
|
57
|
+
<textarea
|
|
58
|
+
id={textareaId}
|
|
59
|
+
bind:this={textareaEl}
|
|
60
|
+
bind:value
|
|
61
|
+
{rows}
|
|
62
|
+
{placeholder}
|
|
63
|
+
{disabled}
|
|
64
|
+
class={cn('hyvui-textarea', error && 'hyvui-textarea-error')}
|
|
65
|
+
oninput={handleInput}
|
|
66
|
+
></textarea>
|
|
67
|
+
{#if error}
|
|
68
|
+
<span class="hyvui-textarea-message hyvui-textarea-message-error">{error}</span>
|
|
69
|
+
{:else if hint}
|
|
70
|
+
<span class="hyvui-textarea-message">{hint}</span>
|
|
71
|
+
{/if}
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<style>
|
|
75
|
+
.hyvui-textarea-wrap {
|
|
76
|
+
display: flex;
|
|
77
|
+
flex-direction: column;
|
|
78
|
+
gap: var(--space-xs);
|
|
79
|
+
min-width: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.hyvui-textarea-label {
|
|
83
|
+
font-family: var(--font-mono);
|
|
84
|
+
font-size: 0.7rem;
|
|
85
|
+
font-weight: 400;
|
|
86
|
+
letter-spacing: 0.16em;
|
|
87
|
+
text-transform: uppercase;
|
|
88
|
+
color: var(--muted-strong);
|
|
89
|
+
line-height: 1.2;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.hyvui-textarea {
|
|
93
|
+
font-family: var(--font-mono);
|
|
94
|
+
font-size: 0.82rem;
|
|
95
|
+
font-weight: 400;
|
|
96
|
+
color: var(--text);
|
|
97
|
+
min-height: calc(var(--control-height-md) * 2.4);
|
|
98
|
+
background:
|
|
99
|
+
linear-gradient(180deg, rgba(240, 232, 218, 0.018), transparent 46%),
|
|
100
|
+
linear-gradient(135deg, rgba(199, 156, 87, 0.045), transparent 44%),
|
|
101
|
+
var(--bg-elev);
|
|
102
|
+
border: 1px solid var(--line);
|
|
103
|
+
border-radius: var(--radius-md);
|
|
104
|
+
padding: var(--control-pad-y) var(--control-pad-x);
|
|
105
|
+
outline: none;
|
|
106
|
+
resize: vertical;
|
|
107
|
+
transition:
|
|
108
|
+
border-color var(--transition-fast),
|
|
109
|
+
background var(--transition-fast),
|
|
110
|
+
box-shadow var(--transition-fast);
|
|
111
|
+
width: 100%;
|
|
112
|
+
box-shadow: inset 0 1px 0 rgba(240, 232, 218, 0.03);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.hyvui-textarea::placeholder {
|
|
116
|
+
color: var(--muted);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.hyvui-textarea:hover:not(:disabled) {
|
|
120
|
+
border-color: color-mix(in srgb, var(--line-strong) 82%, transparent);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.hyvui-textarea:focus {
|
|
124
|
+
border-color: var(--line-strong);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.hyvui-textarea:disabled {
|
|
128
|
+
opacity: 0.4;
|
|
129
|
+
cursor: not-allowed;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.hyvui-textarea-error {
|
|
133
|
+
border-color: var(--status-fail);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.hyvui-textarea-message {
|
|
137
|
+
font-family: var(--font-mono);
|
|
138
|
+
font-size: 0.66rem;
|
|
139
|
+
letter-spacing: 0.14em;
|
|
140
|
+
text-transform: uppercase;
|
|
141
|
+
color: var(--muted-strong);
|
|
142
|
+
line-height: 1.3;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.hyvui-textarea-message-error {
|
|
146
|
+
color: var(--status-fail);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@media (prefers-reduced-motion: reduce) {
|
|
150
|
+
.hyvui-textarea {
|
|
151
|
+
transition: none;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
/** Current value (bindable). */
|
|
3
|
+
value?: string;
|
|
4
|
+
/** Number of visible rows. */
|
|
5
|
+
rows?: number;
|
|
6
|
+
/** Placeholder text. */
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
/** Label text displayed above the textarea. */
|
|
9
|
+
label?: string;
|
|
10
|
+
/** Error message. */
|
|
11
|
+
error?: string;
|
|
12
|
+
/** Hint text. */
|
|
13
|
+
hint?: string;
|
|
14
|
+
/** Auto-expand height based on content. */
|
|
15
|
+
autoresize?: boolean;
|
|
16
|
+
/** Disables the textarea. */
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
/** Additional CSS classes. */
|
|
19
|
+
class?: string;
|
|
20
|
+
/** Input handler. */
|
|
21
|
+
oninput?: (e: Event) => void;
|
|
22
|
+
}
|
|
23
|
+
declare const Textarea: import("svelte").Component<Props, {}, "value">;
|
|
24
|
+
type Textarea = ReturnType<typeof Textarea>;
|
|
25
|
+
export default Textarea;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../utils/cn.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
/** Whether the toggle is on (bindable). */
|
|
6
|
+
checked?: boolean;
|
|
7
|
+
/** Label text. */
|
|
8
|
+
label?: string;
|
|
9
|
+
/** Disables the toggle. */
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
/** Additional CSS classes. */
|
|
12
|
+
class?: string;
|
|
13
|
+
/** Change handler. */
|
|
14
|
+
onchange?: (e: Event) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
checked = $bindable(false),
|
|
19
|
+
label = '',
|
|
20
|
+
disabled = false,
|
|
21
|
+
class: className = '',
|
|
22
|
+
onchange,
|
|
23
|
+
}: Props = $props();
|
|
24
|
+
|
|
25
|
+
function toggle() {
|
|
26
|
+
if (disabled) return;
|
|
27
|
+
checked = !checked;
|
|
28
|
+
onchange?.(new Event('change'));
|
|
29
|
+
}
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<label class={cn('hyvui-toggle', disabled && 'hyvui-toggle-disabled', className)}>
|
|
33
|
+
<button
|
|
34
|
+
type="button"
|
|
35
|
+
role="switch"
|
|
36
|
+
aria-checked={checked}
|
|
37
|
+
{disabled}
|
|
38
|
+
aria-label={label || 'toggle'}
|
|
39
|
+
class="hyvui-toggle-track"
|
|
40
|
+
class:hyvui-toggle-on={checked}
|
|
41
|
+
onclick={toggle}
|
|
42
|
+
>
|
|
43
|
+
<span class="hyvui-toggle-thumb" class:hyvui-toggle-thumb-on={checked}></span>
|
|
44
|
+
</button>
|
|
45
|
+
{#if label}
|
|
46
|
+
<span class="hyvui-toggle-label">{label}</span>
|
|
47
|
+
{/if}
|
|
48
|
+
</label>
|
|
49
|
+
|
|
50
|
+
<style>
|
|
51
|
+
.hyvui-toggle {
|
|
52
|
+
display: inline-flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
gap: var(--space-sm);
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
min-width: 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.hyvui-toggle-disabled {
|
|
60
|
+
opacity: 0.4;
|
|
61
|
+
cursor: not-allowed;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.hyvui-toggle-track {
|
|
65
|
+
width: 42px;
|
|
66
|
+
height: 24px;
|
|
67
|
+
border-radius: 999px;
|
|
68
|
+
background:
|
|
69
|
+
linear-gradient(180deg, rgba(240, 232, 218, 0.02), transparent 48%),
|
|
70
|
+
var(--bg-elev);
|
|
71
|
+
border: 1px solid var(--line-strong);
|
|
72
|
+
position: relative;
|
|
73
|
+
cursor: pointer;
|
|
74
|
+
padding: 0;
|
|
75
|
+
transition:
|
|
76
|
+
background-color var(--transition-fast),
|
|
77
|
+
border-color var(--transition-fast),
|
|
78
|
+
box-shadow var(--transition-fast);
|
|
79
|
+
box-shadow: inset 0 1px 0 rgba(240, 232, 218, 0.03);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.hyvui-toggle-track:disabled {
|
|
83
|
+
cursor: not-allowed;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.hyvui-toggle-on {
|
|
87
|
+
background-color: var(--accent);
|
|
88
|
+
border-color: var(--accent);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.hyvui-toggle-thumb {
|
|
92
|
+
position: absolute;
|
|
93
|
+
top: 2px;
|
|
94
|
+
left: 2px;
|
|
95
|
+
width: 18px;
|
|
96
|
+
height: 18px;
|
|
97
|
+
border-radius: 50%;
|
|
98
|
+
background-color: var(--muted);
|
|
99
|
+
transition: transform var(--transition-fast), background-color var(--transition-fast);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.hyvui-toggle-thumb-on {
|
|
103
|
+
transform: translateX(18px);
|
|
104
|
+
background-color: var(--bg);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.hyvui-toggle-label {
|
|
108
|
+
font-family: var(--font-body);
|
|
109
|
+
font-size: 0.98rem;
|
|
110
|
+
color: var(--text-soft);
|
|
111
|
+
line-height: 1.5;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@media (prefers-reduced-motion: reduce) {
|
|
115
|
+
.hyvui-toggle-track,
|
|
116
|
+
.hyvui-toggle-thumb {
|
|
117
|
+
transition: none;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
/** Whether the toggle is on (bindable). */
|
|
3
|
+
checked?: boolean;
|
|
4
|
+
/** Label text. */
|
|
5
|
+
label?: string;
|
|
6
|
+
/** Disables the toggle. */
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
/** Additional CSS classes. */
|
|
9
|
+
class?: string;
|
|
10
|
+
/** Change handler. */
|
|
11
|
+
onchange?: (e: Event) => void;
|
|
12
|
+
}
|
|
13
|
+
declare const Toggle: import("svelte").Component<Props, {}, "checked">;
|
|
14
|
+
type Toggle = ReturnType<typeof Toggle>;
|
|
15
|
+
export default Toggle;
|