@dorsk/tsumikit 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/LICENSE +21 -0
- package/README.md +165 -0
- package/dist/autoresize.d.ts +11 -0
- package/dist/autoresize.js +24 -0
- package/dist/components/atoms/Badge.svelte +72 -0
- package/dist/components/atoms/Badge.svelte.d.ts +12 -0
- package/dist/components/atoms/Button.svelte +156 -0
- package/dist/components/atoms/Button.svelte.d.ts +13 -0
- package/dist/components/atoms/Card.svelte +46 -0
- package/dist/components/atoms/Card.svelte.d.ts +11 -0
- package/dist/components/atoms/Checkbox.svelte +99 -0
- package/dist/components/atoms/Checkbox.svelte.d.ts +10 -0
- package/dist/components/atoms/Chip.svelte +53 -0
- package/dist/components/atoms/Chip.svelte.d.ts +11 -0
- package/dist/components/atoms/Heading.svelte +66 -0
- package/dist/components/atoms/Heading.svelte.d.ts +13 -0
- package/dist/components/atoms/Icon.svelte +151 -0
- package/dist/components/atoms/Icon.svelte.d.ts +18 -0
- package/dist/components/atoms/Input.svelte +42 -0
- package/dist/components/atoms/Input.svelte.d.ts +10 -0
- package/dist/components/atoms/Link.svelte +31 -0
- package/dist/components/atoms/Link.svelte.d.ts +10 -0
- package/dist/components/atoms/Progress.svelte +59 -0
- package/dist/components/atoms/Progress.svelte.d.ts +9 -0
- package/dist/components/atoms/Select.svelte +95 -0
- package/dist/components/atoms/Select.svelte.d.ts +11 -0
- package/dist/components/atoms/Slider.svelte +136 -0
- package/dist/components/atoms/Slider.svelte.d.ts +14 -0
- package/dist/components/atoms/Switch.svelte +64 -0
- package/dist/components/atoms/Switch.svelte.d.ts +8 -0
- package/dist/components/atoms/Text.svelte +127 -0
- package/dist/components/atoms/Text.svelte.d.ts +16 -0
- package/dist/components/atoms/Textarea.svelte +62 -0
- package/dist/components/atoms/Textarea.svelte.d.ts +11 -0
- package/dist/components/layouts/AppShell.svelte +304 -0
- package/dist/components/layouts/AppShell.svelte.d.ts +21 -0
- package/dist/components/layouts/AutoGrid.svelte +36 -0
- package/dist/components/layouts/AutoGrid.svelte.d.ts +12 -0
- package/dist/components/layouts/Cluster.svelte +45 -0
- package/dist/components/layouts/Cluster.svelte.d.ts +14 -0
- package/dist/components/layouts/Container.svelte +40 -0
- package/dist/components/layouts/Container.svelte.d.ts +13 -0
- package/dist/components/layouts/NavItem.svelte +95 -0
- package/dist/components/layouts/NavItem.svelte.d.ts +14 -0
- package/dist/components/layouts/Stack.svelte +44 -0
- package/dist/components/layouts/Stack.svelte.d.ts +13 -0
- package/dist/components/molecules/Accordion.svelte +94 -0
- package/dist/components/molecules/Accordion.svelte.d.ts +16 -0
- package/dist/components/molecules/CodeBlock.svelte +119 -0
- package/dist/components/molecules/CodeBlock.svelte.d.ts +17 -0
- package/dist/components/molecules/CopyButton.svelte +80 -0
- package/dist/components/molecules/CopyButton.svelte.d.ts +13 -0
- package/dist/components/molecules/Dropzone.svelte +140 -0
- package/dist/components/molecules/Dropzone.svelte.d.ts +13 -0
- package/dist/components/molecules/Field.svelte +57 -0
- package/dist/components/molecules/Field.svelte.d.ts +12 -0
- package/dist/components/molecules/FileButton.svelte +68 -0
- package/dist/components/molecules/FileButton.svelte.d.ts +14 -0
- package/dist/components/molecules/FontScalePicker.svelte +21 -0
- package/dist/components/molecules/FontScalePicker.svelte.d.ts +6 -0
- package/dist/components/molecules/IconButton.svelte +36 -0
- package/dist/components/molecules/IconButton.svelte.d.ts +13 -0
- package/dist/components/molecules/Menu.svelte +120 -0
- package/dist/components/molecules/Menu.svelte.d.ts +17 -0
- package/dist/components/molecules/Modal.svelte +263 -0
- package/dist/components/molecules/Modal.svelte.d.ts +13 -0
- package/dist/components/molecules/OptionButton.svelte +76 -0
- package/dist/components/molecules/OptionButton.svelte.d.ts +10 -0
- package/dist/components/molecules/Popover.svelte +125 -0
- package/dist/components/molecules/Popover.svelte.d.ts +18 -0
- package/dist/components/molecules/RadioGroup.svelte +110 -0
- package/dist/components/molecules/RadioGroup.svelte.d.ts +16 -0
- package/dist/components/molecules/SelectButton.svelte +52 -0
- package/dist/components/molecules/SelectButton.svelte.d.ts +15 -0
- package/dist/components/molecules/Tabs.svelte +119 -0
- package/dist/components/molecules/Tabs.svelte.d.ts +15 -0
- package/dist/components/molecules/ThemePicker.svelte +22 -0
- package/dist/components/molecules/ThemePicker.svelte.d.ts +6 -0
- package/dist/components/molecules/Toaster.svelte +73 -0
- package/dist/components/molecules/Toaster.svelte.d.ts +18 -0
- package/dist/components/molecules/Toggle.svelte +68 -0
- package/dist/components/molecules/Toggle.svelte.d.ts +11 -0
- package/dist/components/molecules/Tooltip.svelte +106 -0
- package/dist/components/molecules/Tooltip.svelte.d.ts +10 -0
- package/dist/components/organisms/DataTable.svelte +145 -0
- package/dist/components/organisms/DataTable.svelte.d.ts +43 -0
- package/dist/env.d.ts +1 -0
- package/dist/env.js +4 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +56 -0
- package/dist/stores/fontscale.svelte.d.ts +15 -0
- package/dist/stores/fontscale.svelte.js +49 -0
- package/dist/stores/theme.svelte.d.ts +96 -0
- package/dist/stores/theme.svelte.js +71 -0
- package/dist/stores/toast.svelte.d.ts +19 -0
- package/dist/stores/toast.svelte.js +26 -0
- package/dist/styles/app.css +522 -0
- package/dist/styles/variables.css +651 -0
- package/package.json +71 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// Range/slider primitive. A real <input type="range"> (keeps the native
|
|
3
|
+
// slider role, keyboard stepping and form participation) restyled across
|
|
4
|
+
// engines from tokens. The track shows a filled portion up to the current
|
|
5
|
+
// value, and an optional `output` displays the value with a correct
|
|
6
|
+
// for-association. `bind:value` and all native attrs/events pass through.
|
|
7
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
value = $bindable(0),
|
|
11
|
+
min = 0,
|
|
12
|
+
max = 100,
|
|
13
|
+
step = 1,
|
|
14
|
+
label,
|
|
15
|
+
showValue = false,
|
|
16
|
+
format = (v: number) => String(v),
|
|
17
|
+
id = `slider-${Math.random().toString(36).slice(2, 8)}`,
|
|
18
|
+
class: klass = '',
|
|
19
|
+
el = $bindable(null),
|
|
20
|
+
...rest
|
|
21
|
+
}: HTMLInputAttributes & {
|
|
22
|
+
value?: number;
|
|
23
|
+
min?: number;
|
|
24
|
+
max?: number;
|
|
25
|
+
step?: number;
|
|
26
|
+
label?: string;
|
|
27
|
+
showValue?: boolean;
|
|
28
|
+
format?: (v: number) => string;
|
|
29
|
+
el?: HTMLInputElement | null;
|
|
30
|
+
} = $props();
|
|
31
|
+
|
|
32
|
+
// Fill percentage for the track gradient.
|
|
33
|
+
const pct = $derived(
|
|
34
|
+
Math.max(0, Math.min(100, ((Number(value) - +min) / (+max - +min || 1)) * 100))
|
|
35
|
+
);
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<div class="slider {klass}" style="--pct: {pct}%">
|
|
39
|
+
<input
|
|
40
|
+
bind:this={el}
|
|
41
|
+
{id}
|
|
42
|
+
type="range"
|
|
43
|
+
{min}
|
|
44
|
+
{max}
|
|
45
|
+
{step}
|
|
46
|
+
bind:value
|
|
47
|
+
aria-label={label}
|
|
48
|
+
{...rest}
|
|
49
|
+
/>
|
|
50
|
+
{#if showValue}
|
|
51
|
+
<output for={id} class="slider-out">{format(Number(value))}</output>
|
|
52
|
+
{/if}
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<style>
|
|
56
|
+
.slider {
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
gap: var(--sp-3);
|
|
60
|
+
width: 100%;
|
|
61
|
+
}
|
|
62
|
+
input[type='range'] {
|
|
63
|
+
appearance: none;
|
|
64
|
+
-webkit-appearance: none;
|
|
65
|
+
flex: 1;
|
|
66
|
+
height: 1.25rem;
|
|
67
|
+
background: none;
|
|
68
|
+
cursor: pointer;
|
|
69
|
+
}
|
|
70
|
+
/* Track — WebKit/Blink. Filled up to --pct with the accent, then the rail. */
|
|
71
|
+
input[type='range']::-webkit-slider-runnable-track {
|
|
72
|
+
height: 0.35rem;
|
|
73
|
+
border-radius: var(--r-pill);
|
|
74
|
+
background: linear-gradient(
|
|
75
|
+
to right,
|
|
76
|
+
var(--accent) var(--pct),
|
|
77
|
+
var(--bg-elevated-2) var(--pct)
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
input[type='range']::-moz-range-track {
|
|
81
|
+
height: 0.35rem;
|
|
82
|
+
border-radius: var(--r-pill);
|
|
83
|
+
background: var(--bg-elevated-2);
|
|
84
|
+
}
|
|
85
|
+
input[type='range']::-moz-range-progress {
|
|
86
|
+
height: 0.35rem;
|
|
87
|
+
border-radius: var(--r-pill);
|
|
88
|
+
background: var(--accent);
|
|
89
|
+
}
|
|
90
|
+
/* Thumb */
|
|
91
|
+
input[type='range']::-webkit-slider-thumb {
|
|
92
|
+
appearance: none;
|
|
93
|
+
-webkit-appearance: none;
|
|
94
|
+
margin-top: -0.425rem; /* center on the 0.35rem track */
|
|
95
|
+
width: 1.2rem;
|
|
96
|
+
height: 1.2rem;
|
|
97
|
+
border-radius: 50%;
|
|
98
|
+
background: var(--accent);
|
|
99
|
+
border: 2px solid var(--bg);
|
|
100
|
+
box-shadow: var(--shadow-sm);
|
|
101
|
+
transition: transform 0.1s var(--ease);
|
|
102
|
+
}
|
|
103
|
+
input[type='range']::-moz-range-thumb {
|
|
104
|
+
width: 1.2rem;
|
|
105
|
+
height: 1.2rem;
|
|
106
|
+
border-radius: 50%;
|
|
107
|
+
background: var(--accent);
|
|
108
|
+
border: 2px solid var(--bg);
|
|
109
|
+
box-shadow: var(--shadow-sm);
|
|
110
|
+
}
|
|
111
|
+
input[type='range']:active::-webkit-slider-thumb {
|
|
112
|
+
transform: scale(1.12);
|
|
113
|
+
}
|
|
114
|
+
input[type='range']:focus-visible {
|
|
115
|
+
outline: none;
|
|
116
|
+
}
|
|
117
|
+
input[type='range']:focus-visible::-webkit-slider-thumb {
|
|
118
|
+
outline: 2px solid var(--accent);
|
|
119
|
+
outline-offset: 2px;
|
|
120
|
+
}
|
|
121
|
+
input[type='range']:focus-visible::-moz-range-thumb {
|
|
122
|
+
outline: 2px solid var(--accent);
|
|
123
|
+
outline-offset: 2px;
|
|
124
|
+
}
|
|
125
|
+
input[type='range']:disabled {
|
|
126
|
+
opacity: 0.45;
|
|
127
|
+
cursor: not-allowed;
|
|
128
|
+
}
|
|
129
|
+
.slider-out {
|
|
130
|
+
min-width: 2.5rem;
|
|
131
|
+
text-align: right;
|
|
132
|
+
font-size: var(--fs-sm);
|
|
133
|
+
font-variant-numeric: tabular-nums;
|
|
134
|
+
color: var(--text-muted);
|
|
135
|
+
}
|
|
136
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
2
|
+
type $$ComponentProps = HTMLInputAttributes & {
|
|
3
|
+
value?: number;
|
|
4
|
+
min?: number;
|
|
5
|
+
max?: number;
|
|
6
|
+
step?: number;
|
|
7
|
+
label?: string;
|
|
8
|
+
showValue?: boolean;
|
|
9
|
+
format?: (v: number) => string;
|
|
10
|
+
el?: HTMLInputElement | null;
|
|
11
|
+
};
|
|
12
|
+
declare const Slider: import("svelte").Component<$$ComponentProps, {}, "value" | "el">;
|
|
13
|
+
type Slider = ReturnType<typeof Slider>;
|
|
14
|
+
export default Slider;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// Canonical on/off toggle (role="switch") — a pill track with a sliding knob.
|
|
3
|
+
// Owns its sizing/colors from theme tokens; the parent supplies `checked`
|
|
4
|
+
// and an `onclick` handler plus an accessible label/title.
|
|
5
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
checked = false,
|
|
9
|
+
label,
|
|
10
|
+
class: klass = '',
|
|
11
|
+
...rest
|
|
12
|
+
}: HTMLButtonAttributes & { checked?: boolean; label: string } = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<button
|
|
16
|
+
{...rest}
|
|
17
|
+
type="button"
|
|
18
|
+
class="switch {klass}"
|
|
19
|
+
class:on={checked}
|
|
20
|
+
role="switch"
|
|
21
|
+
aria-checked={checked}
|
|
22
|
+
aria-label={label}
|
|
23
|
+
>
|
|
24
|
+
<span class="knob"></span>
|
|
25
|
+
</button>
|
|
26
|
+
|
|
27
|
+
<style>
|
|
28
|
+
.switch {
|
|
29
|
+
flex: none;
|
|
30
|
+
width: 2.75rem;
|
|
31
|
+
height: 1.6rem;
|
|
32
|
+
border-radius: var(--r-pill);
|
|
33
|
+
border: 1px solid var(--border-strong);
|
|
34
|
+
background: var(--bg-elevated-2);
|
|
35
|
+
padding: 2px;
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
transition:
|
|
40
|
+
background 0.14s var(--ease),
|
|
41
|
+
border-color 0.14s var(--ease);
|
|
42
|
+
}
|
|
43
|
+
.switch .knob {
|
|
44
|
+
width: 1.25rem;
|
|
45
|
+
height: 1.25rem;
|
|
46
|
+
border-radius: 50%;
|
|
47
|
+
background: var(--text-muted);
|
|
48
|
+
transition:
|
|
49
|
+
transform 0.14s var(--ease),
|
|
50
|
+
background 0.14s var(--ease);
|
|
51
|
+
}
|
|
52
|
+
.switch.on {
|
|
53
|
+
background: var(--accent);
|
|
54
|
+
border-color: var(--accent);
|
|
55
|
+
}
|
|
56
|
+
.switch.on .knob {
|
|
57
|
+
transform: translateX(1.15rem);
|
|
58
|
+
background: var(--text-on-accent);
|
|
59
|
+
}
|
|
60
|
+
.switch:disabled {
|
|
61
|
+
opacity: 0.45;
|
|
62
|
+
cursor: not-allowed;
|
|
63
|
+
}
|
|
64
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
2
|
+
type $$ComponentProps = HTMLButtonAttributes & {
|
|
3
|
+
checked?: boolean;
|
|
4
|
+
label: string;
|
|
5
|
+
};
|
|
6
|
+
declare const Switch: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type Switch = ReturnType<typeof Switch>;
|
|
8
|
+
export default Switch;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// Text primitive: the ONLY place body/label/caption/code text and its bearing
|
|
3
|
+
// elements (<p>/<span>/<label>/<div> of pure text) are emitted. `variant` picks
|
|
4
|
+
// a token preset; `tone`/`weight`/`size` override individual axes; bare <Text>
|
|
5
|
+
// (no props) inherits the surrounding style like a plain <span> so it can wrap
|
|
6
|
+
// inline glue text without changing rendering. All values come from tokens.
|
|
7
|
+
import type { Snippet } from 'svelte';
|
|
8
|
+
|
|
9
|
+
type Size = 'xs' | 'sm' | 'base' | 'md' | 'lg' | 'xl' | '2xl';
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
as = 'span',
|
|
13
|
+
variant,
|
|
14
|
+
tone = 'inherit',
|
|
15
|
+
weight,
|
|
16
|
+
size,
|
|
17
|
+
truncate = false,
|
|
18
|
+
class: klass = '',
|
|
19
|
+
children,
|
|
20
|
+
...rest
|
|
21
|
+
}: {
|
|
22
|
+
as?: 'span' | 'p' | 'div' | 'label';
|
|
23
|
+
// body: default reading text · label: form-label · caption: small meta ·
|
|
24
|
+
// code: monospace. Omit for inline glue that should inherit its parent.
|
|
25
|
+
variant?: 'body' | 'label' | 'caption' | 'code';
|
|
26
|
+
tone?: 'inherit' | 'default' | 'muted' | 'faint' | 'danger' | 'accent';
|
|
27
|
+
weight?: 'normal' | 'medium' | 'semibold' | 'bold';
|
|
28
|
+
size?: Size;
|
|
29
|
+
truncate?: boolean;
|
|
30
|
+
class?: string;
|
|
31
|
+
children?: Snippet;
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
} = $props();
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<svelte:element
|
|
37
|
+
this={as}
|
|
38
|
+
class="text {variant ? `v-${variant}` : ''} tone-{tone} {weight ? `fw-${weight}` : ''} {size
|
|
39
|
+
? `fs-${size}`
|
|
40
|
+
: ''} {truncate ? 'truncate' : ''} {klass}"
|
|
41
|
+
{...rest}
|
|
42
|
+
>
|
|
43
|
+
{@render children?.()}
|
|
44
|
+
</svelte:element>
|
|
45
|
+
|
|
46
|
+
<style>
|
|
47
|
+
/* Base: inherit everything — a bare <Text> renders like a plain span. */
|
|
48
|
+
.text {
|
|
49
|
+
margin: 0;
|
|
50
|
+
}
|
|
51
|
+
/* Variants (presets) — listed before tone/weight/size so those override. */
|
|
52
|
+
.v-body {
|
|
53
|
+
font-size: var(--fs-base);
|
|
54
|
+
line-height: var(--lh-normal);
|
|
55
|
+
color: var(--text);
|
|
56
|
+
}
|
|
57
|
+
.v-label {
|
|
58
|
+
font-size: var(--fs-sm);
|
|
59
|
+
font-weight: var(--fw-medium);
|
|
60
|
+
color: var(--text-muted);
|
|
61
|
+
}
|
|
62
|
+
.v-caption {
|
|
63
|
+
font-size: var(--fs-xs);
|
|
64
|
+
color: var(--text-faint);
|
|
65
|
+
}
|
|
66
|
+
.v-code {
|
|
67
|
+
font-family: var(--font-mono);
|
|
68
|
+
font-size: 0.92em;
|
|
69
|
+
}
|
|
70
|
+
/* Tone (colour) — overrides variant colour. */
|
|
71
|
+
.tone-default {
|
|
72
|
+
color: var(--text);
|
|
73
|
+
}
|
|
74
|
+
.tone-muted {
|
|
75
|
+
color: var(--text-muted);
|
|
76
|
+
}
|
|
77
|
+
.tone-faint {
|
|
78
|
+
color: var(--text-faint);
|
|
79
|
+
}
|
|
80
|
+
.tone-danger {
|
|
81
|
+
color: var(--danger);
|
|
82
|
+
}
|
|
83
|
+
.tone-accent {
|
|
84
|
+
color: var(--accent);
|
|
85
|
+
}
|
|
86
|
+
/* Weight — overrides variant weight. */
|
|
87
|
+
.fw-normal {
|
|
88
|
+
font-weight: var(--fw-normal);
|
|
89
|
+
}
|
|
90
|
+
.fw-medium {
|
|
91
|
+
font-weight: var(--fw-medium);
|
|
92
|
+
}
|
|
93
|
+
.fw-semibold {
|
|
94
|
+
font-weight: var(--fw-semibold);
|
|
95
|
+
}
|
|
96
|
+
.fw-bold {
|
|
97
|
+
font-weight: var(--fw-bold);
|
|
98
|
+
}
|
|
99
|
+
/* Size — overrides variant size (listed last so it wins). */
|
|
100
|
+
.fs-xs {
|
|
101
|
+
font-size: var(--fs-xs);
|
|
102
|
+
}
|
|
103
|
+
.fs-sm {
|
|
104
|
+
font-size: var(--fs-sm);
|
|
105
|
+
}
|
|
106
|
+
.fs-base {
|
|
107
|
+
font-size: var(--fs-base);
|
|
108
|
+
}
|
|
109
|
+
.fs-md {
|
|
110
|
+
font-size: var(--fs-md);
|
|
111
|
+
}
|
|
112
|
+
.fs-lg {
|
|
113
|
+
font-size: var(--fs-lg);
|
|
114
|
+
}
|
|
115
|
+
.fs-xl {
|
|
116
|
+
font-size: var(--fs-xl);
|
|
117
|
+
}
|
|
118
|
+
.fs-2xl {
|
|
119
|
+
font-size: var(--fs-2xl);
|
|
120
|
+
}
|
|
121
|
+
.truncate {
|
|
122
|
+
overflow: hidden;
|
|
123
|
+
text-overflow: ellipsis;
|
|
124
|
+
white-space: nowrap;
|
|
125
|
+
min-width: 0;
|
|
126
|
+
}
|
|
127
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type Size = 'xs' | 'sm' | 'base' | 'md' | 'lg' | 'xl' | '2xl';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
as?: 'span' | 'p' | 'div' | 'label';
|
|
5
|
+
variant?: 'body' | 'label' | 'caption' | 'code';
|
|
6
|
+
tone?: 'inherit' | 'default' | 'muted' | 'faint' | 'danger' | 'accent';
|
|
7
|
+
weight?: 'normal' | 'medium' | 'semibold' | 'bold';
|
|
8
|
+
size?: Size;
|
|
9
|
+
truncate?: boolean;
|
|
10
|
+
class?: string;
|
|
11
|
+
children?: Snippet;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
};
|
|
14
|
+
declare const Text: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
15
|
+
type Text = ReturnType<typeof Text>;
|
|
16
|
+
export default Text;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// Multi-line text input primitive. Owns its styling from theme tokens;
|
|
3
|
+
// supports `bind:value` and passes through every native <textarea> attribute
|
|
4
|
+
// and event (Svelte 5 events are props, so `...rest` forwards them). `mono`
|
|
5
|
+
// switches to the monospace family. `autoresize` opts into the grow-with-
|
|
6
|
+
// content action without the call-site wiring `use:` itself. `bind:el`
|
|
7
|
+
// exposes the underlying element for focus/measure.
|
|
8
|
+
import type { HTMLTextareaAttributes } from 'svelte/elements';
|
|
9
|
+
import { autoresize as autoresizeAction } from '../../autoresize';
|
|
10
|
+
|
|
11
|
+
type Props = HTMLTextareaAttributes & {
|
|
12
|
+
mono?: boolean;
|
|
13
|
+
autoresize?: boolean;
|
|
14
|
+
class?: string;
|
|
15
|
+
value?: HTMLTextareaAttributes['value'];
|
|
16
|
+
el?: HTMLTextAreaElement | null;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
mono = false,
|
|
21
|
+
autoresize = false,
|
|
22
|
+
class: klass = '',
|
|
23
|
+
value = $bindable(),
|
|
24
|
+
el = $bindable(null),
|
|
25
|
+
...rest
|
|
26
|
+
}: Props = $props();
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
{#if autoresize}
|
|
30
|
+
<textarea
|
|
31
|
+
bind:this={el}
|
|
32
|
+
class="textarea {klass}"
|
|
33
|
+
class:mono
|
|
34
|
+
bind:value
|
|
35
|
+
use:autoresizeAction={typeof value === 'string' ? value : ''}
|
|
36
|
+
{...rest}
|
|
37
|
+
></textarea>
|
|
38
|
+
{:else}
|
|
39
|
+
<textarea bind:this={el} class="textarea {klass}" class:mono bind:value {...rest}></textarea>
|
|
40
|
+
{/if}
|
|
41
|
+
|
|
42
|
+
<style>
|
|
43
|
+
.textarea {
|
|
44
|
+
width: 100%;
|
|
45
|
+
padding: var(--sp-3);
|
|
46
|
+
background: var(--bg);
|
|
47
|
+
border: 1px solid var(--border-strong);
|
|
48
|
+
border-radius: var(--r-md);
|
|
49
|
+
color: var(--text);
|
|
50
|
+
transition: border-color 0.12s var(--ease);
|
|
51
|
+
resize: vertical;
|
|
52
|
+
min-height: 5rem;
|
|
53
|
+
font-family: inherit;
|
|
54
|
+
}
|
|
55
|
+
.textarea:focus {
|
|
56
|
+
outline: none;
|
|
57
|
+
border-color: var(--accent);
|
|
58
|
+
}
|
|
59
|
+
.mono {
|
|
60
|
+
font-family: var(--font-mono);
|
|
61
|
+
}
|
|
62
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HTMLTextareaAttributes } from 'svelte/elements';
|
|
2
|
+
type Props = HTMLTextareaAttributes & {
|
|
3
|
+
mono?: boolean;
|
|
4
|
+
autoresize?: boolean;
|
|
5
|
+
class?: string;
|
|
6
|
+
value?: HTMLTextareaAttributes['value'];
|
|
7
|
+
el?: HTMLTextAreaElement | null;
|
|
8
|
+
};
|
|
9
|
+
declare const Textarea: import("svelte").Component<Props, {}, "value" | "el">;
|
|
10
|
+
type Textarea = ReturnType<typeof Textarea>;
|
|
11
|
+
export default Textarea;
|