svelte-comp 1.2.5 → 1.2.6
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/package.json +1 -1
- package/dist/App.svelte +0 -551
- package/dist/App.svelte.d.ts +0 -3
- package/dist/Container.svelte +0 -60
- package/dist/Container.svelte.d.ts +0 -12
- package/dist/app.css +0 -235
- package/dist/index.d.ts +0 -5
- package/dist/index.js +0 -6
- package/dist/lang.d.ts +0 -1081
- package/dist/lang.js +0 -1096
- package/dist/lib/Accordion.svelte +0 -155
- package/dist/lib/Accordion.svelte.d.ts +0 -40
- package/dist/lib/Button.svelte +0 -170
- package/dist/lib/Button.svelte.d.ts +0 -53
- package/dist/lib/Card.svelte +0 -103
- package/dist/lib/Card.svelte.d.ts +0 -42
- package/dist/lib/Carousel.svelte +0 -293
- package/dist/lib/Carousel.svelte.d.ts +0 -13
- package/dist/lib/CheckBox.svelte +0 -210
- package/dist/lib/CheckBox.svelte.d.ts +0 -53
- package/dist/lib/CodeView.svelte +0 -307
- package/dist/lib/CodeView.svelte.d.ts +0 -64
- package/dist/lib/ColorPicker.svelte +0 -161
- package/dist/lib/ColorPicker.svelte.d.ts +0 -40
- package/dist/lib/DatePicker.svelte +0 -170
- package/dist/lib/DatePicker.svelte.d.ts +0 -53
- package/dist/lib/Dialog.svelte +0 -235
- package/dist/lib/Dialog.svelte.d.ts +0 -58
- package/dist/lib/Field.svelte +0 -299
- package/dist/lib/Field.svelte.d.ts +0 -8
- package/dist/lib/FilePicker.svelte +0 -241
- package/dist/lib/FilePicker.svelte.d.ts +0 -52
- package/dist/lib/Form.svelte +0 -438
- package/dist/lib/Form.svelte.d.ts +0 -20
- package/dist/lib/Hamburger.svelte +0 -211
- package/dist/lib/Hamburger.svelte.d.ts +0 -52
- package/dist/lib/Menu.svelte +0 -623
- package/dist/lib/Menu.svelte.d.ts +0 -33
- package/dist/lib/PaginatedCard.svelte +0 -73
- package/dist/lib/PaginatedCard.svelte.d.ts +0 -11
- package/dist/lib/Pagination.svelte +0 -119
- package/dist/lib/Pagination.svelte.d.ts +0 -9
- package/dist/lib/PrimaryColorSelect.svelte +0 -113
- package/dist/lib/PrimaryColorSelect.svelte.d.ts +0 -9
- package/dist/lib/ProgressBar.svelte +0 -141
- package/dist/lib/ProgressBar.svelte.d.ts +0 -48
- package/dist/lib/ProgressCircle.svelte +0 -192
- package/dist/lib/ProgressCircle.svelte.d.ts +0 -39
- package/dist/lib/Radio.svelte +0 -189
- package/dist/lib/Radio.svelte.d.ts +0 -55
- package/dist/lib/SearchInput.svelte +0 -106
- package/dist/lib/SearchInput.svelte.d.ts +0 -13
- package/dist/lib/Select.svelte +0 -524
- package/dist/lib/Select.svelte.d.ts +0 -21
- package/dist/lib/Slider.svelte +0 -253
- package/dist/lib/Slider.svelte.d.ts +0 -56
- package/dist/lib/Splitter.svelte +0 -150
- package/dist/lib/Splitter.svelte.d.ts +0 -43
- package/dist/lib/Switch.svelte +0 -167
- package/dist/lib/Switch.svelte.d.ts +0 -42
- package/dist/lib/Table.svelte +0 -299
- package/dist/lib/Table.svelte.d.ts +0 -17
- package/dist/lib/Tabs.svelte +0 -213
- package/dist/lib/Tabs.svelte.d.ts +0 -48
- package/dist/lib/ThemeToggle.svelte +0 -127
- package/dist/lib/ThemeToggle.svelte.d.ts +0 -32
- package/dist/lib/TimePicker.svelte +0 -269
- package/dist/lib/TimePicker.svelte.d.ts +0 -48
- package/dist/lib/Toast.svelte +0 -226
- package/dist/lib/Toast.svelte.d.ts +0 -14
- package/dist/lib/Tooltip.svelte +0 -110
- package/dist/lib/Tooltip.svelte.d.ts +0 -40
- package/dist/lib/index.d.ts +0 -32
- package/dist/lib/index.js +0 -33
- package/dist/lib/lang.d.ts +0 -158
- package/dist/lib/lang.js +0 -150
- package/dist/lib/types/index.d.ts +0 -111
- package/dist/lib/types/index.js +0 -26
- package/dist/main.d.ts +0 -3
- package/dist/main.js +0 -7
- package/dist/styles.css +0 -232
- package/dist/utils/index.d.ts +0 -34
- package/dist/utils/index.js +0 -268
package/dist/lib/Slider.svelte
DELETED
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
<!-- src/lib/Slider.svelte -->
|
|
2
|
-
<script lang="ts">
|
|
3
|
-
/**
|
|
4
|
-
* @component Slider
|
|
5
|
-
* @description A customizable slider component for selecting a value from a range.
|
|
6
|
-
*
|
|
7
|
-
* @prop value {number} - The current value (bindable)
|
|
8
|
-
* @default 0
|
|
9
|
-
*
|
|
10
|
-
* @prop min {number} - Minimum value
|
|
11
|
-
* @default 0
|
|
12
|
-
*
|
|
13
|
-
* @prop max {number} - Maximum value
|
|
14
|
-
* @default 100
|
|
15
|
-
*
|
|
16
|
-
* @prop step {number} - Step size
|
|
17
|
-
* @default 1
|
|
18
|
-
*
|
|
19
|
-
* @prop sz {SizeKey} - Slider size
|
|
20
|
-
* @options xs|sm|md|lg|xl
|
|
21
|
-
* @default md
|
|
22
|
-
*
|
|
23
|
-
* @prop variant {ComponentVariant} - Color variant
|
|
24
|
-
* @options default|neutral
|
|
25
|
-
* @default default
|
|
26
|
-
*
|
|
27
|
-
* @prop disabled {boolean} - Disable the slider
|
|
28
|
-
* @default false
|
|
29
|
-
*
|
|
30
|
-
* @prop showValue {boolean} - Show the current value
|
|
31
|
-
* @default false
|
|
32
|
-
*
|
|
33
|
-
* @prop onInput {(value: number) => void} - Fires on value change
|
|
34
|
-
*
|
|
35
|
-
* @prop class {string} - Custom wrapper classes
|
|
36
|
-
* @default ""
|
|
37
|
-
*
|
|
38
|
-
* @note Works with both keyboard and mouse.
|
|
39
|
-
* @note Size and variant control appearance.
|
|
40
|
-
* @note Uses proper ARIA attributes.
|
|
41
|
-
*/
|
|
42
|
-
import type { HTMLAttributes } from "svelte/elements";
|
|
43
|
-
import type { SizeKey, ComponentVariant } from "./types";
|
|
44
|
-
import { TEXT } from "./types";
|
|
45
|
-
import { cx, clamp } from "../utils";
|
|
46
|
-
|
|
47
|
-
type Props = HTMLAttributes<HTMLDivElement> & {
|
|
48
|
-
value?: number;
|
|
49
|
-
min?: number;
|
|
50
|
-
max?: number;
|
|
51
|
-
step?: number;
|
|
52
|
-
sz?: SizeKey;
|
|
53
|
-
variant?: ComponentVariant;
|
|
54
|
-
disabled?: boolean;
|
|
55
|
-
showValue?: boolean;
|
|
56
|
-
onInput?: (value: number) => void;
|
|
57
|
-
class?: string;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
let {
|
|
61
|
-
value = $bindable(0),
|
|
62
|
-
min = 0,
|
|
63
|
-
max = 100,
|
|
64
|
-
step = 1,
|
|
65
|
-
sz = "md",
|
|
66
|
-
variant = "default",
|
|
67
|
-
disabled = false,
|
|
68
|
-
showValue = false,
|
|
69
|
-
onInput,
|
|
70
|
-
class: externalClass = "",
|
|
71
|
-
...rest
|
|
72
|
-
}: Props = $props();
|
|
73
|
-
|
|
74
|
-
const sizeTrack = $derived(
|
|
75
|
-
{
|
|
76
|
-
xs: "h-[4px]",
|
|
77
|
-
sm: "h-[5px]",
|
|
78
|
-
md: "h-[6px]",
|
|
79
|
-
lg: "h-[7px]",
|
|
80
|
-
xl: "h-[8px]",
|
|
81
|
-
}[sz]
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
const sizeThumb = $derived(
|
|
85
|
-
{
|
|
86
|
-
xs: "[&::-webkit-slider-thumb]:w-3 [&::-webkit-slider-thumb]:h-3 [&::-moz-range-thumb]:w-3 [&::-moz-range-thumb]:h-3",
|
|
87
|
-
sm: "[&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:h-4",
|
|
88
|
-
md: "[&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:h-5 [&::-moz-range-thumb]:w-5 [&::-moz-range-thumb]:h-5",
|
|
89
|
-
lg: "[&::-webkit-slider-thumb]:w-6 [&::-webkit-slider-thumb]:h-6 [&::-moz-range-thumb]:w-6 [&::-moz-range-thumb]:h-6",
|
|
90
|
-
xl: "[&::-webkit-slider-thumb]:w-7 [&::-webkit-slider-thumb]:h-7 [&::-moz-range-thumb]:w-7 [&::-moz-range-thumb]:h-7",
|
|
91
|
-
}[sz]
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
const bar = $derived(
|
|
95
|
-
variant === "neutral"
|
|
96
|
-
? "bg-[var(--color-bg-secondary)]"
|
|
97
|
-
: "bg-[var(--color-bg-primary)]"
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const thumb = $derived(
|
|
101
|
-
variant === "neutral"
|
|
102
|
-
? "[&::-webkit-slider-thumb]:bg-[var(--color-bg-secondary)] [&::-moz-range-thumb]:bg-[var(--color-bg-secondary)]"
|
|
103
|
-
: "[&::-webkit-slider-thumb]:bg-[var(--color-bg-primary)] [&::-moz-range-thumb]:bg-[var(--color-bg-primary)]"
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
const pct = $derived(
|
|
107
|
-
clamp(((value - min) / Math.max(1e-12, max - min)) * 100, 0, 100)
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
const rootClass = $derived(
|
|
111
|
-
cx(
|
|
112
|
-
"relative w-full data-[disabled=true]:opacity-[var(--opacity-disabled)]",
|
|
113
|
-
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
114
|
-
externalClass
|
|
115
|
-
)
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
const trackClass = $derived(
|
|
119
|
-
cx(
|
|
120
|
-
"absolute top-1/2 -translate-y-1/2 w-full bg-[var(--color-bg-muted)] rounded overflow-hidden",
|
|
121
|
-
sizeTrack
|
|
122
|
-
)
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
const rangeBase =
|
|
126
|
-
"relative z-10 w-full h-10 bg-transparent appearance-none cursor-pointer disabled:cursor-not-allowed " +
|
|
127
|
-
"[&::-webkit-slider-thumb]:appearance-none " +
|
|
128
|
-
"[&::-webkit-slider-thumb]:rounded-[var(--radius-full)] " +
|
|
129
|
-
"[&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-[var(--color-bg-surface)] " +
|
|
130
|
-
"[&::-webkit-slider-thumb]:shadow-[var(--shadow-color)] " +
|
|
131
|
-
"[&::-moz-range-thumb]:rounded-[var(--radius-full)] " +
|
|
132
|
-
"[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-[var(--color-bg-surface)] " +
|
|
133
|
-
"[&::-moz-range-thumb]:shadow-[var(--shadow-color)] " +
|
|
134
|
-
"hover:[&::-webkit-slider-thumb]:scale-110 active:[&::-webkit-slider-thumb]:scale-125 " +
|
|
135
|
-
"hover:[&::-moz-range-thumb]:scale-110 active:[&::-moz-range-thumb]:scale-125 " +
|
|
136
|
-
"focus:outline-none focus-visible:outline-none " +
|
|
137
|
-
"focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_3px_var(--border-color-focus)] " +
|
|
138
|
-
"focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_3px_var(--border-color-focus)] " +
|
|
139
|
-
"disabled:hover:[&::-webkit-slider-thumb]:scale-100 disabled:active:[&::-webkit-slider-thumb]:scale-100 " +
|
|
140
|
-
"disabled:hover:[&::-moz-range-thumb]:scale-100 disabled:active:[&::-moz-range-thumb]:scale-100";
|
|
141
|
-
|
|
142
|
-
const rangeClass = $derived(cx(rangeBase, sizeThumb, thumb));
|
|
143
|
-
|
|
144
|
-
function snap(v: number) {
|
|
145
|
-
const s = step || 1;
|
|
146
|
-
const ticks = Math.round((v - min) / s);
|
|
147
|
-
const snapped = min + ticks * s;
|
|
148
|
-
return clamp(Number(snapped.toFixed(6)), min, max);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
let wrap: HTMLDivElement;
|
|
152
|
-
|
|
153
|
-
function setFromClientX(x: number) {
|
|
154
|
-
const r = wrap.getBoundingClientRect();
|
|
155
|
-
const ratio = clamp((x - r.left) / r.width, 0, 1);
|
|
156
|
-
value = snap(min + ratio * (max - min));
|
|
157
|
-
onInput?.(value);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function onTrackClick(e: MouseEvent) {
|
|
161
|
-
if (disabled) return;
|
|
162
|
-
setFromClientX(e.clientX);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function onRangeInput(e: Event) {
|
|
166
|
-
const t = e.currentTarget as HTMLInputElement;
|
|
167
|
-
value = snap(Number(t.value));
|
|
168
|
-
onInput?.(value);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function onKey(e: KeyboardEvent) {
|
|
172
|
-
if (disabled) return;
|
|
173
|
-
const span = max - min;
|
|
174
|
-
const big = Math.max(step || 1, Math.round(span / 10));
|
|
175
|
-
let v = value;
|
|
176
|
-
|
|
177
|
-
switch (e.key) {
|
|
178
|
-
case "ArrowLeft":
|
|
179
|
-
case "ArrowDown":
|
|
180
|
-
v = value - (step || 1);
|
|
181
|
-
break;
|
|
182
|
-
case "ArrowRight":
|
|
183
|
-
case "ArrowUp":
|
|
184
|
-
v = value + (step || 1);
|
|
185
|
-
break;
|
|
186
|
-
case "PageDown":
|
|
187
|
-
v = value - big;
|
|
188
|
-
break;
|
|
189
|
-
case "PageUp":
|
|
190
|
-
v = value + big;
|
|
191
|
-
break;
|
|
192
|
-
case "Home":
|
|
193
|
-
v = min;
|
|
194
|
-
break;
|
|
195
|
-
case "End":
|
|
196
|
-
v = max;
|
|
197
|
-
break;
|
|
198
|
-
default:
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
value = snap(v);
|
|
203
|
-
onInput?.(value);
|
|
204
|
-
e.preventDefault();
|
|
205
|
-
}
|
|
206
|
-
</script>
|
|
207
|
-
|
|
208
|
-
<div
|
|
209
|
-
bind:this={wrap}
|
|
210
|
-
class={rootClass}
|
|
211
|
-
onclick={onTrackClick}
|
|
212
|
-
onfocusin={(e) => (rest as unknown as { onfocus?: (e: FocusEvent) => void }).onfocus?.(e as FocusEvent)}
|
|
213
|
-
onfocusout={(e) => (rest as unknown as { onblur?: (e: FocusEvent) => void }).onblur?.(e as FocusEvent)}
|
|
214
|
-
data-disabled={disabled ? "true" : undefined}
|
|
215
|
-
{...rest}
|
|
216
|
-
>
|
|
217
|
-
<div class="relative flex items-center w-full h-10">
|
|
218
|
-
<div class={trackClass}>
|
|
219
|
-
<div
|
|
220
|
-
class={cx("w-full h-full transition-[width]", bar)}
|
|
221
|
-
style={`width:${pct}%`}
|
|
222
|
-
></div>
|
|
223
|
-
</div>
|
|
224
|
-
|
|
225
|
-
<input
|
|
226
|
-
type="range"
|
|
227
|
-
class={rangeClass}
|
|
228
|
-
{min}
|
|
229
|
-
{max}
|
|
230
|
-
{step}
|
|
231
|
-
{value}
|
|
232
|
-
oninput={onRangeInput}
|
|
233
|
-
onkeydown={onKey}
|
|
234
|
-
{disabled}
|
|
235
|
-
aria-label="slider"
|
|
236
|
-
aria-valuemin={min}
|
|
237
|
-
aria-valuemax={max}
|
|
238
|
-
aria-valuenow={value}
|
|
239
|
-
/>
|
|
240
|
-
</div>
|
|
241
|
-
|
|
242
|
-
{#if showValue}
|
|
243
|
-
<div class="flex justify-end mt-1">
|
|
244
|
-
<div
|
|
245
|
-
class="font-[var(--font-mono)] text-[var(--color-text-muted)] select-none {TEXT[
|
|
246
|
-
sz
|
|
247
|
-
]}"
|
|
248
|
-
>
|
|
249
|
-
{value}
|
|
250
|
-
</div>
|
|
251
|
-
</div>
|
|
252
|
-
{/if}
|
|
253
|
-
</div>
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @component Slider
|
|
3
|
-
* @description A customizable slider component for selecting a value from a range.
|
|
4
|
-
*
|
|
5
|
-
* @prop value {number} - The current value (bindable)
|
|
6
|
-
* @default 0
|
|
7
|
-
*
|
|
8
|
-
* @prop min {number} - Minimum value
|
|
9
|
-
* @default 0
|
|
10
|
-
*
|
|
11
|
-
* @prop max {number} - Maximum value
|
|
12
|
-
* @default 100
|
|
13
|
-
*
|
|
14
|
-
* @prop step {number} - Step size
|
|
15
|
-
* @default 1
|
|
16
|
-
*
|
|
17
|
-
* @prop sz {SizeKey} - Slider size
|
|
18
|
-
* @options xs|sm|md|lg|xl
|
|
19
|
-
* @default md
|
|
20
|
-
*
|
|
21
|
-
* @prop variant {ComponentVariant} - Color variant
|
|
22
|
-
* @options default|neutral
|
|
23
|
-
* @default default
|
|
24
|
-
*
|
|
25
|
-
* @prop disabled {boolean} - Disable the slider
|
|
26
|
-
* @default false
|
|
27
|
-
*
|
|
28
|
-
* @prop showValue {boolean} - Show the current value
|
|
29
|
-
* @default false
|
|
30
|
-
*
|
|
31
|
-
* @prop onInput {(value: number) => void} - Fires on value change
|
|
32
|
-
*
|
|
33
|
-
* @prop class {string} - Custom wrapper classes
|
|
34
|
-
* @default ""
|
|
35
|
-
*
|
|
36
|
-
* @note Works with both keyboard and mouse.
|
|
37
|
-
* @note Size and variant control appearance.
|
|
38
|
-
* @note Uses proper ARIA attributes.
|
|
39
|
-
*/
|
|
40
|
-
import type { HTMLAttributes } from "svelte/elements";
|
|
41
|
-
import type { SizeKey, ComponentVariant } from "./types";
|
|
42
|
-
type Props = HTMLAttributes<HTMLDivElement> & {
|
|
43
|
-
value?: number;
|
|
44
|
-
min?: number;
|
|
45
|
-
max?: number;
|
|
46
|
-
step?: number;
|
|
47
|
-
sz?: SizeKey;
|
|
48
|
-
variant?: ComponentVariant;
|
|
49
|
-
disabled?: boolean;
|
|
50
|
-
showValue?: boolean;
|
|
51
|
-
onInput?: (value: number) => void;
|
|
52
|
-
class?: string;
|
|
53
|
-
};
|
|
54
|
-
declare const Slider: import("svelte").Component<Props, {}, "value">;
|
|
55
|
-
type Slider = ReturnType<typeof Slider>;
|
|
56
|
-
export default Slider;
|
package/dist/lib/Splitter.svelte
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
<!-- src/lib/Splitter.svelte -->
|
|
2
|
-
<script lang="ts">
|
|
3
|
-
/**
|
|
4
|
-
* @component Splitter
|
|
5
|
-
* @description Resizable split panel container with horizontal or vertical orientation.
|
|
6
|
-
*
|
|
7
|
-
* @prop direction {'horizontal' | 'vertical'} - Split orientation
|
|
8
|
-
* @options horizontal|vertical
|
|
9
|
-
* @default horizontal
|
|
10
|
-
*
|
|
11
|
-
* @prop initialSize {number} - Initial size of the first panel as percentage
|
|
12
|
-
* @default 30
|
|
13
|
-
*
|
|
14
|
-
* @prop dividerSize {number} - Width/height of the divider handle in pixels
|
|
15
|
-
* @default 4
|
|
16
|
-
*
|
|
17
|
-
* @prop minSize {number} - Minimum size of the first panel as percentage
|
|
18
|
-
* @default 10
|
|
19
|
-
*
|
|
20
|
-
* @prop maxSize {number} - Maximum size of the first panel as percentage
|
|
21
|
-
* @default 90
|
|
22
|
-
*
|
|
23
|
-
* @prop first {Snippet} - Content for the first panel
|
|
24
|
-
*
|
|
25
|
-
* @prop second {Snippet} - Content for the second panel
|
|
26
|
-
*
|
|
27
|
-
* @note Uses pointer events for smooth dragging with proper event delegation
|
|
28
|
-
* @note Responsive - automatically adjusts to container resize
|
|
29
|
-
* @note Accessible with proper cursor hints and hover states
|
|
30
|
-
* @note No wrapper elements - panels render directly for clean DOM structure
|
|
31
|
-
* @note Supports any content type through snippet rendering
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
import type { Snippet } from "svelte";
|
|
35
|
-
|
|
36
|
-
type Props = {
|
|
37
|
-
direction?: "horizontal" | "vertical";
|
|
38
|
-
initialSize?: number;
|
|
39
|
-
dividerSize?: number;
|
|
40
|
-
minSize?: number;
|
|
41
|
-
maxSize?: number;
|
|
42
|
-
first?: Snippet;
|
|
43
|
-
second?: Snippet;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
let {
|
|
47
|
-
direction = "horizontal",
|
|
48
|
-
initialSize = 30,
|
|
49
|
-
dividerSize = 4,
|
|
50
|
-
minSize = 10,
|
|
51
|
-
maxSize = 90,
|
|
52
|
-
first,
|
|
53
|
-
second,
|
|
54
|
-
}: Props = $props();
|
|
55
|
-
|
|
56
|
-
let container: HTMLElement;
|
|
57
|
-
|
|
58
|
-
let size = $derived(initialSize);
|
|
59
|
-
let isDragging = $state(false);
|
|
60
|
-
let startSize = 0;
|
|
61
|
-
let startPos = 0;
|
|
62
|
-
let containerSize = 0;
|
|
63
|
-
|
|
64
|
-
function getContainerSize(): number {
|
|
65
|
-
if (!container) return 0;
|
|
66
|
-
return direction === "horizontal"
|
|
67
|
-
? container.offsetWidth
|
|
68
|
-
: container.offsetHeight;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function startDrag(e: PointerEvent): void {
|
|
72
|
-
isDragging = true;
|
|
73
|
-
startSize = size;
|
|
74
|
-
startPos = direction === "horizontal" ? e.clientX : e.clientY;
|
|
75
|
-
containerSize = getContainerSize();
|
|
76
|
-
|
|
77
|
-
document.addEventListener("pointermove", onDrag);
|
|
78
|
-
document.addEventListener("pointerup", stopDrag);
|
|
79
|
-
document.addEventListener("pointercancel", stopDrag);
|
|
80
|
-
|
|
81
|
-
e.preventDefault();
|
|
82
|
-
e.stopPropagation();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function onDrag(e: PointerEvent): void {
|
|
86
|
-
if (!isDragging) return;
|
|
87
|
-
|
|
88
|
-
const currentPos = direction === "horizontal" ? e.clientX : e.clientY;
|
|
89
|
-
const delta = currentPos - startPos;
|
|
90
|
-
const deltaPercent = (delta / containerSize) * 100;
|
|
91
|
-
const newSize = startSize + deltaPercent;
|
|
92
|
-
|
|
93
|
-
size = Math.max(minSize, Math.min(maxSize, newSize));
|
|
94
|
-
|
|
95
|
-
e.preventDefault();
|
|
96
|
-
e.stopPropagation();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function stopDrag(): void {
|
|
100
|
-
isDragging = false;
|
|
101
|
-
document.removeEventListener("pointermove", onDrag);
|
|
102
|
-
document.removeEventListener("pointerup", stopDrag);
|
|
103
|
-
document.removeEventListener("pointercancel", stopDrag);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
$effect(() => {
|
|
107
|
-
const onResize = () => {
|
|
108
|
-
containerSize = getContainerSize();
|
|
109
|
-
};
|
|
110
|
-
window.addEventListener("resize", onResize);
|
|
111
|
-
return () => window.removeEventListener("resize", onResize);
|
|
112
|
-
});
|
|
113
|
-
</script>
|
|
114
|
-
|
|
115
|
-
<div
|
|
116
|
-
bind:this={container}
|
|
117
|
-
class="w-full h-full overflow-hidden"
|
|
118
|
-
class:flex={direction === "horizontal"}
|
|
119
|
-
class:flex-col={direction === "vertical"}
|
|
120
|
-
>
|
|
121
|
-
{#if direction === "horizontal"}
|
|
122
|
-
<div class="overflow-auto min-w-0 min-h-0" style="width: {size}%">
|
|
123
|
-
{@render first?.()}
|
|
124
|
-
</div>
|
|
125
|
-
|
|
126
|
-
<div
|
|
127
|
-
class="touch-none select-none z-10 cursor-col-resize bg-[var(--color-bg-muted)] hover:bg-[var(--color-bg-hover)] transition-colors"
|
|
128
|
-
style="width: {dividerSize}px"
|
|
129
|
-
onpointerdown={startDrag}
|
|
130
|
-
></div>
|
|
131
|
-
|
|
132
|
-
<div class="overflow-auto min-w-0 min-h-0 flex-1">
|
|
133
|
-
{@render second?.()}
|
|
134
|
-
</div>
|
|
135
|
-
{:else}
|
|
136
|
-
<div class="overflow-auto min-w-0 min-h-0" style="height: {size}%">
|
|
137
|
-
{@render first?.()}
|
|
138
|
-
</div>
|
|
139
|
-
|
|
140
|
-
<div
|
|
141
|
-
class="touch-none select-none z-10 cursor-row-resize bg-[var(--color-bg-muted)] hover:bg-[var(--color-bg-hover)] transition-colors"
|
|
142
|
-
style="height: {dividerSize}px"
|
|
143
|
-
onpointerdown={startDrag}
|
|
144
|
-
></div>
|
|
145
|
-
|
|
146
|
-
<div class="overflow-auto min-w-0 min-h-0" style="height: calc(100% - {size}% - {dividerSize}px)">
|
|
147
|
-
{@render second?.()}
|
|
148
|
-
</div>
|
|
149
|
-
{/if}
|
|
150
|
-
</div>
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @component Splitter
|
|
3
|
-
* @description Resizable split panel container with horizontal or vertical orientation.
|
|
4
|
-
*
|
|
5
|
-
* @prop direction {'horizontal' | 'vertical'} - Split orientation
|
|
6
|
-
* @options horizontal|vertical
|
|
7
|
-
* @default horizontal
|
|
8
|
-
*
|
|
9
|
-
* @prop initialSize {number} - Initial size of the first panel as percentage
|
|
10
|
-
* @default 30
|
|
11
|
-
*
|
|
12
|
-
* @prop dividerSize {number} - Width/height of the divider handle in pixels
|
|
13
|
-
* @default 4
|
|
14
|
-
*
|
|
15
|
-
* @prop minSize {number} - Minimum size of the first panel as percentage
|
|
16
|
-
* @default 10
|
|
17
|
-
*
|
|
18
|
-
* @prop maxSize {number} - Maximum size of the first panel as percentage
|
|
19
|
-
* @default 90
|
|
20
|
-
*
|
|
21
|
-
* @prop first {Snippet} - Content for the first panel
|
|
22
|
-
*
|
|
23
|
-
* @prop second {Snippet} - Content for the second panel
|
|
24
|
-
*
|
|
25
|
-
* @note Uses pointer events for smooth dragging with proper event delegation
|
|
26
|
-
* @note Responsive - automatically adjusts to container resize
|
|
27
|
-
* @note Accessible with proper cursor hints and hover states
|
|
28
|
-
* @note No wrapper elements - panels render directly for clean DOM structure
|
|
29
|
-
* @note Supports any content type through snippet rendering
|
|
30
|
-
*/
|
|
31
|
-
import type { Snippet } from "svelte";
|
|
32
|
-
type Props = {
|
|
33
|
-
direction?: "horizontal" | "vertical";
|
|
34
|
-
initialSize?: number;
|
|
35
|
-
dividerSize?: number;
|
|
36
|
-
minSize?: number;
|
|
37
|
-
maxSize?: number;
|
|
38
|
-
first?: Snippet;
|
|
39
|
-
second?: Snippet;
|
|
40
|
-
};
|
|
41
|
-
declare const Splitter: import("svelte").Component<Props, {}, "">;
|
|
42
|
-
type Splitter = ReturnType<typeof Splitter>;
|
|
43
|
-
export default Splitter;
|
package/dist/lib/Switch.svelte
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
<!-- src/lib/Switch.svelte -->
|
|
2
|
-
<script lang="ts">
|
|
3
|
-
/**
|
|
4
|
-
* @component Switch
|
|
5
|
-
* @description A compact toggle switch component built on top of a native `<input type="checkbox">`. Supports optional labels around the control and works naturally with `bind:checked`.
|
|
6
|
-
*
|
|
7
|
-
* @prop sz {SizeKey} - Size preset for the control
|
|
8
|
-
* @options xs|sm|md|lg|xl
|
|
9
|
-
* @default md
|
|
10
|
-
*
|
|
11
|
-
* @prop checked {boolean} - Current state (bindable)
|
|
12
|
-
* @default false
|
|
13
|
-
*
|
|
14
|
-
* @prop leftLabel {string} - Optional label rendered on the left side
|
|
15
|
-
*
|
|
16
|
-
* @prop rightLabel {string} - Optional label rendered on the right side
|
|
17
|
-
*
|
|
18
|
-
* @prop topLabel {string} - Optional label placed above the switch
|
|
19
|
-
*
|
|
20
|
-
* @prop onChange {(v: boolean) => void} - Fired on toggle with the new value
|
|
21
|
-
*
|
|
22
|
-
* @prop class {string} - External wrapper classes
|
|
23
|
-
* @default ""
|
|
24
|
-
*
|
|
25
|
-
* @note Built over a real checkbox so browser accessibility comes for free: keyboard (Space/Enter), focus ring, and screen reader semantics.
|
|
26
|
-
* @note Labels do not affect the actual checkbox hitbox, but the whole area is clickable if wrapped correctly.
|
|
27
|
-
* @note Size preset adjusts track width, knob size, and spacing.
|
|
28
|
-
* @note Reflects `disabled` by dimming visuals and removing pointer events.
|
|
29
|
-
* @note The component keeps no internal state besides the bound `checked` value, so it's predictable in forms and controlled UI.
|
|
30
|
-
*/
|
|
31
|
-
import type { HTMLInputAttributes } from "svelte/elements";
|
|
32
|
-
import type { SizeKey } from "./types";
|
|
33
|
-
import { TEXT } from "./types";
|
|
34
|
-
import { cx, uid } from "../utils";
|
|
35
|
-
|
|
36
|
-
type Props = HTMLInputAttributes & {
|
|
37
|
-
sz?: SizeKey;
|
|
38
|
-
checked?: boolean;
|
|
39
|
-
leftLabel?: string;
|
|
40
|
-
rightLabel?: string;
|
|
41
|
-
topLabel?: string;
|
|
42
|
-
onChange?: (v: boolean) => void;
|
|
43
|
-
class?: string;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
let {
|
|
47
|
-
sz = "md",
|
|
48
|
-
checked = $bindable(false),
|
|
49
|
-
leftLabel,
|
|
50
|
-
rightLabel,
|
|
51
|
-
topLabel,
|
|
52
|
-
onChange,
|
|
53
|
-
class: externalClass = "",
|
|
54
|
-
...rest
|
|
55
|
-
}: Props = $props();
|
|
56
|
-
|
|
57
|
-
const inputId = $derived(rest.id ?? uid("sw-"));
|
|
58
|
-
|
|
59
|
-
const track = {
|
|
60
|
-
xs: "w-8 h-4",
|
|
61
|
-
sm: "w-10 h-5",
|
|
62
|
-
md: "w-12 h-6",
|
|
63
|
-
lg: "w-14 h-7",
|
|
64
|
-
xl: "w-16 h-8",
|
|
65
|
-
} as const;
|
|
66
|
-
|
|
67
|
-
const knob = {
|
|
68
|
-
xs: "h-[14px] w-[14px]",
|
|
69
|
-
sm: "h-[17px] w-[17px]",
|
|
70
|
-
md: "h-5 w-5",
|
|
71
|
-
lg: "h-6 w-6",
|
|
72
|
-
xl: "h-7 w-7",
|
|
73
|
-
} as const;
|
|
74
|
-
|
|
75
|
-
const pad = {
|
|
76
|
-
xs: "p-[1px]",
|
|
77
|
-
sm: "p-[1.5px]",
|
|
78
|
-
md: "p-[2px]",
|
|
79
|
-
lg: "p-[2px]",
|
|
80
|
-
xl: "p-[2px]",
|
|
81
|
-
} as const;
|
|
82
|
-
|
|
83
|
-
const isDisabled = $derived(
|
|
84
|
-
"disabled" in rest ? Boolean(rest.disabled) : false
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
function toggle() {
|
|
88
|
-
if (isDisabled) return;
|
|
89
|
-
checked = !checked;
|
|
90
|
-
onChange?.(checked);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const justifyClass = $derived(checked ? "justify-end" : "justify-start");
|
|
94
|
-
|
|
95
|
-
const trackClass = $derived(
|
|
96
|
-
cx(
|
|
97
|
-
"relative inline-flex items-center rounded-full border transition focus:outline-none focus:ring-2 focus:ring-[var(--border-color-focus)]",
|
|
98
|
-
track[sz],
|
|
99
|
-
pad[sz],
|
|
100
|
-
checked
|
|
101
|
-
? "bg-[var(--color-bg-primary)] border-[var(--color-bg-primary)]"
|
|
102
|
-
: "bg-[var(--color-bg-muted)] border-[var(--border-color-default)]",
|
|
103
|
-
isDisabled
|
|
104
|
-
? "opacity-[var(--opacity-disabled)] cursor-not-allowed"
|
|
105
|
-
: "cursor-pointer",
|
|
106
|
-
justifyClass
|
|
107
|
-
)
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
const rootClass = $derived(
|
|
111
|
-
cx("inline-flex flex-col items-center gap-1 select-none", externalClass)
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
const knobClass = $derived(
|
|
115
|
-
cx(
|
|
116
|
-
knob[sz],
|
|
117
|
-
"rounded-full bg-white border border-[var(--border-color-default)] shadow-sm"
|
|
118
|
-
)
|
|
119
|
-
);
|
|
120
|
-
</script>
|
|
121
|
-
|
|
122
|
-
<label class={rootClass} for={inputId}>
|
|
123
|
-
{#if topLabel}
|
|
124
|
-
<span class="text-[var(--color-text-muted)] {TEXT[sz]}">
|
|
125
|
-
{topLabel}
|
|
126
|
-
</span>
|
|
127
|
-
{/if}
|
|
128
|
-
|
|
129
|
-
<div class="inline-flex items-center gap-2">
|
|
130
|
-
{#if leftLabel}
|
|
131
|
-
<span class="text-[var(--color-text-muted)] {TEXT[sz]}">
|
|
132
|
-
{leftLabel}
|
|
133
|
-
</span>
|
|
134
|
-
{/if}
|
|
135
|
-
|
|
136
|
-
<input
|
|
137
|
-
id={inputId}
|
|
138
|
-
type="checkbox"
|
|
139
|
-
{checked}
|
|
140
|
-
{...rest}
|
|
141
|
-
class="sr-only"
|
|
142
|
-
aria-checked={checked}
|
|
143
|
-
aria-invalid={rest["aria-invalid"] || undefined}
|
|
144
|
-
aria-describedby={rest["aria-describedby"]}
|
|
145
|
-
onchange={() => toggle()}
|
|
146
|
-
/>
|
|
147
|
-
|
|
148
|
-
<button
|
|
149
|
-
type="button"
|
|
150
|
-
class={trackClass}
|
|
151
|
-
onclick={toggle}
|
|
152
|
-
aria-pressed={checked}
|
|
153
|
-
aria-label={typeof rest["aria-label"] === "string"
|
|
154
|
-
? rest["aria-label"]
|
|
155
|
-
: "Switch"}
|
|
156
|
-
disabled={isDisabled}
|
|
157
|
-
>
|
|
158
|
-
<span class={knobClass}></span>
|
|
159
|
-
</button>
|
|
160
|
-
|
|
161
|
-
{#if rightLabel}
|
|
162
|
-
<span class="text-[var(--color-text-muted)] {TEXT[sz]}">
|
|
163
|
-
{rightLabel}
|
|
164
|
-
</span>
|
|
165
|
-
{/if}
|
|
166
|
-
</div>
|
|
167
|
-
</label>
|