twintrinsic 0.0.1
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 +674 -0
- package/README.md +150 -0
- package/dist/App/App.svelte +54 -0
- package/dist/App/App.svelte.d.ts +65 -0
- package/dist/Section.svelte +25 -0
- package/dist/Section.svelte.d.ts +34 -0
- package/dist/actions/clickOutside.d.ts +9 -0
- package/dist/actions/clickOutside.js +19 -0
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/components/Accordion/Accordion.svelte +75 -0
- package/dist/components/Accordion/Accordion.svelte.d.ts +39 -0
- package/dist/components/Accordion/AccordionItem.svelte +150 -0
- package/dist/components/Accordion/AccordionItem.svelte.d.ts +30 -0
- package/dist/components/App/App.story.md +8 -0
- package/dist/components/App/App.story.svelte +170 -0
- package/dist/components/App/App.story.svelte.d.ts +22 -0
- package/dist/components/App/App.svelte +77 -0
- package/dist/components/App/App.svelte.d.ts +66 -0
- package/dist/components/App/Split.svelte +346 -0
- package/dist/components/App/Split.svelte.d.ts +54 -0
- package/dist/components/App/index.d.ts +2 -0
- package/dist/components/App/index.js +3 -0
- package/dist/components/AppHeader/AppHeader.svelte +439 -0
- package/dist/components/AppHeader/AppHeader.svelte.d.ts +24 -0
- package/dist/components/Avatar/Avatar.svelte +300 -0
- package/dist/components/Avatar/Avatar.svelte.d.ts +48 -0
- package/dist/components/Avatar/AvatarGroup.svelte +185 -0
- package/dist/components/Avatar/AvatarGroup.svelte.d.ts +46 -0
- package/dist/components/Badge/Badge.svelte +186 -0
- package/dist/components/Badge/Badge.svelte.d.ts +51 -0
- package/dist/components/BottomBar/BottomBar.svelte +146 -0
- package/dist/components/BottomBar/BottomBar.svelte.d.ts +38 -0
- package/dist/components/Breadcrumb/Breadcrumb.svelte +77 -0
- package/dist/components/Breadcrumb/Breadcrumb.svelte.d.ts +42 -0
- package/dist/components/Breadcrumb/BreadcrumbItem.svelte +171 -0
- package/dist/components/Breadcrumb/BreadcrumbItem.svelte.d.ts +38 -0
- package/dist/components/Button/Button.svelte +252 -0
- package/dist/components/Button/Button.svelte.d.ts +80 -0
- package/dist/components/Button/ButtonGroup.svelte +127 -0
- package/dist/components/Button/ButtonGroup.svelte.d.ts +44 -0
- package/dist/components/Card/Card.svelte +152 -0
- package/dist/components/Card/Card.svelte.d.ts +55 -0
- package/dist/components/Carousel/Carousel.svelte +461 -0
- package/dist/components/Carousel/Carousel.svelte.d.ts +79 -0
- package/dist/components/Carousel/CarouselItem.svelte +149 -0
- package/dist/components/Carousel/CarouselItem.svelte.d.ts +35 -0
- package/dist/components/Chip/Chip.svelte +288 -0
- package/dist/components/Chip/Chip.svelte.d.ts +71 -0
- package/dist/components/Chip/ChipGroup.svelte +190 -0
- package/dist/components/Chip/ChipGroup.svelte.d.ts +71 -0
- package/dist/components/CodeBlock/CodeBlock.svelte +356 -0
- package/dist/components/CodeBlock/CodeBlock.svelte.d.ts +44 -0
- package/dist/components/CodeBlock/index.d.ts +1 -0
- package/dist/components/CodeBlock/index.js +1 -0
- package/dist/components/CodeBlockSpeed/CodeBlockSpeed.svelte +145 -0
- package/dist/components/CodeBlockSpeed/CodeBlockSpeed.svelte.d.ts +44 -0
- package/dist/components/CodeEditor/CodeEditor.svelte +229 -0
- package/dist/components/CodeEditor/CodeEditor.svelte.d.ts +23 -0
- package/dist/components/Combobox/Combobox.svelte +279 -0
- package/dist/components/Combobox/Combobox.svelte.d.ts +34 -0
- package/dist/components/Container/Container.svelte +45 -0
- package/dist/components/Container/Container.svelte.d.ts +36 -0
- package/dist/components/DataTable/DataTable.svelte +879 -0
- package/dist/components/DataTable/DataTable.svelte.d.ts +102 -0
- package/dist/components/Form/AutoComplete.svelte +357 -0
- package/dist/components/Form/AutoComplete.svelte.d.ts +73 -0
- package/dist/components/Form/Calendar.svelte +429 -0
- package/dist/components/Form/Calendar.svelte.d.ts +53 -0
- package/dist/components/Form/Checkbox.svelte +196 -0
- package/dist/components/Form/Checkbox.svelte.d.ts +50 -0
- package/dist/components/Form/ColorPicker.svelte +396 -0
- package/dist/components/Form/ColorPicker.svelte.d.ts +43 -0
- package/dist/components/Form/Combobox.svelte +645 -0
- package/dist/components/Form/Combobox.svelte.d.ts +93 -0
- package/dist/components/Form/Dropdown.svelte +773 -0
- package/dist/components/Form/Dropdown.svelte.d.ts +81 -0
- package/dist/components/Form/FileUpload.svelte +796 -0
- package/dist/components/Form/FileUpload.svelte.d.ts +78 -0
- package/dist/components/Form/FloatLabel.svelte +245 -0
- package/dist/components/Form/FloatLabel.svelte.d.ts +44 -0
- package/dist/components/Form/Form.svelte +281 -0
- package/dist/components/Form/Form.svelte.d.ts +54 -0
- package/dist/components/Form/FormField.svelte +218 -0
- package/dist/components/Form/FormField.svelte.d.ts +47 -0
- package/dist/components/Form/Input.svelte +340 -0
- package/dist/components/Form/Input.svelte.d.ts +79 -0
- package/dist/components/Form/InputSwitch.svelte +189 -0
- package/dist/components/Form/InputSwitch.svelte.d.ts +46 -0
- package/dist/components/Form/InvalidState.svelte +97 -0
- package/dist/components/Form/InvalidState.svelte.d.ts +37 -0
- package/dist/components/Form/Knob.svelte +537 -0
- package/dist/components/Form/Knob.svelte.d.ts +78 -0
- package/dist/components/Form/ListInput.svelte +469 -0
- package/dist/components/Form/ListInput.svelte.d.ts +70 -0
- package/dist/components/Form/Listbox.svelte +513 -0
- package/dist/components/Form/Listbox.svelte.d.ts +74 -0
- package/dist/components/Form/NumberInput.svelte +452 -0
- package/dist/components/Form/NumberInput.svelte.d.ts +82 -0
- package/dist/components/Form/Radio.svelte +192 -0
- package/dist/components/Form/Radio.svelte.d.ts +53 -0
- package/dist/components/Form/RadioGroup.svelte +155 -0
- package/dist/components/Form/RadioGroup.svelte.d.ts +48 -0
- package/dist/components/Form/Rating.svelte +380 -0
- package/dist/components/Form/Rating.svelte.d.ts +64 -0
- package/dist/components/Form/Select.svelte +436 -0
- package/dist/components/Form/Select.svelte.d.ts +49 -0
- package/dist/components/Form/SelectGroup.svelte +34 -0
- package/dist/components/Form/SelectGroup.svelte.d.ts +33 -0
- package/dist/components/Form/Slider.svelte +622 -0
- package/dist/components/Form/Slider.svelte.d.ts +73 -0
- package/dist/components/Form/Switch.svelte +192 -0
- package/dist/components/Form/Switch.svelte.d.ts +46 -0
- package/dist/components/Form/TextInput.svelte +274 -0
- package/dist/components/Form/TextInput.svelte.d.ts +74 -0
- package/dist/components/Form/Textarea.svelte +207 -0
- package/dist/components/Form/Textarea.svelte.d.ts +62 -0
- package/dist/components/Icon/Icon.svelte +140 -0
- package/dist/components/Icon/Icon.svelte.d.ts +25 -0
- package/dist/components/Icon/index.d.ts +1 -0
- package/dist/components/Icon/index.js +1 -0
- package/dist/components/Lazy/Lazy.svelte +158 -0
- package/dist/components/Lazy/Lazy.svelte.d.ts +42 -0
- package/dist/components/Masonry/Masonry.svelte +299 -0
- package/dist/components/Masonry/Masonry.svelte.d.ts +55 -0
- package/dist/components/Menu/Menu/Menu.svelte +65 -0
- package/dist/components/Menu/Menu/Menu.svelte.d.ts +17 -0
- package/dist/components/Menu/Menu/MenuItem.svelte +90 -0
- package/dist/components/Menu/Menu/MenuItem.svelte.d.ts +27 -0
- package/dist/components/Modal/Modal.svelte +334 -0
- package/dist/components/Modal/Modal.svelte.d.ts +55 -0
- package/dist/components/Panel/Card.svelte +141 -0
- package/dist/components/Panel/Card.svelte.d.ts +52 -0
- package/dist/components/Panel/Hero/Hero.story.md +9 -0
- package/dist/components/Panel/Hero/Hero.story.svelte +49 -0
- package/dist/components/Panel/Hero/Hero.story.svelte.d.ts +21 -0
- package/dist/components/Panel/Hero/Hero.svelte +24 -0
- package/dist/components/Panel/Hero/Hero.svelte.d.ts +32 -0
- package/dist/components/Panel/LazyPanel.svelte +110 -0
- package/dist/components/Panel/LazyPanel.svelte.d.ts +46 -0
- package/dist/components/Panel/Panel.svelte +205 -0
- package/dist/components/Panel/Panel.svelte.d.ts +23 -0
- package/dist/components/Progress/Progress.svelte +220 -0
- package/dist/components/Progress/Progress.svelte.d.ts +61 -0
- package/dist/components/Separator/Separator.svelte +109 -0
- package/dist/components/Separator/Separator.svelte.d.ts +35 -0
- package/dist/components/Sidebar/Sidebar.svelte +213 -0
- package/dist/components/Sidebar/Sidebar.svelte.d.ts +60 -0
- package/dist/components/Skeleton/Skeleton.svelte +170 -0
- package/dist/components/Skeleton/Skeleton.svelte.d.ts +48 -0
- package/dist/components/Stepper/Stepper.svelte +111 -0
- package/dist/components/Stepper/Stepper.svelte.d.ts +54 -0
- package/dist/components/Stepper/StepperStep.svelte +369 -0
- package/dist/components/Stepper/StepperStep.svelte.d.ts +63 -0
- package/dist/components/Table/Table.svelte +167 -0
- package/dist/components/Table/Table.svelte.d.ts +56 -0
- package/dist/components/Table/TableBody.svelte +41 -0
- package/dist/components/Table/TableBody.svelte.d.ts +33 -0
- package/dist/components/Table/TableCell.svelte +76 -0
- package/dist/components/Table/TableCell.svelte.d.ts +36 -0
- package/dist/components/Table/TableHead.svelte +41 -0
- package/dist/components/Table/TableHead.svelte.d.ts +32 -0
- package/dist/components/Table/TableHeader.svelte +148 -0
- package/dist/components/Table/TableHeader.svelte.d.ts +42 -0
- package/dist/components/Table/TableRow.svelte +99 -0
- package/dist/components/Table/TableRow.svelte.d.ts +40 -0
- package/dist/components/Tabs/Tab.svelte +145 -0
- package/dist/components/Tabs/Tab.svelte.d.ts +36 -0
- package/dist/components/Tabs/TabList.svelte +60 -0
- package/dist/components/Tabs/TabList.svelte.d.ts +32 -0
- package/dist/components/Tabs/TabPanel.svelte +118 -0
- package/dist/components/Tabs/TabPanel.svelte.d.ts +38 -0
- package/dist/components/Tabs/Tabs.svelte +287 -0
- package/dist/components/Tabs/Tabs.svelte.d.ts +50 -0
- package/dist/components/Tag/Tag.svelte +260 -0
- package/dist/components/Tag/Tag.svelte.d.ts +54 -0
- package/dist/components/Tag/TagGroup.svelte +147 -0
- package/dist/components/Tag/TagGroup.svelte.d.ts +62 -0
- package/dist/components/ThemeToggle/ThemeToggle.svelte +93 -0
- package/dist/components/ThemeToggle/ThemeToggle.svelte.d.ts +12 -0
- package/dist/components/Timeline/Timeline.svelte +144 -0
- package/dist/components/Timeline/Timeline.svelte.d.ts +48 -0
- package/dist/components/Timeline/TimelineItem.svelte +391 -0
- package/dist/components/Timeline/TimelineItem.svelte.d.ts +63 -0
- package/dist/components/Toast/Toast.svelte +313 -0
- package/dist/components/Toast/Toast.svelte.d.ts +44 -0
- package/dist/components/Toast/toastStore.d.ts +40 -0
- package/dist/components/Toast/toastStore.js +293 -0
- package/dist/components/Tooltip/Tooltip.svelte +282 -0
- package/dist/components/Tooltip/Tooltip.svelte.d.ts +55 -0
- package/dist/components/Tree/Tree.svelte +129 -0
- package/dist/components/Tree/Tree.svelte.d.ts +61 -0
- package/dist/components/Tree/TreeNode.svelte +332 -0
- package/dist/components/Tree/TreeNode.svelte.d.ts +55 -0
- package/dist/components/icons/TwintrinsicLogo.svelte +73 -0
- package/dist/components/icons/TwintrinsicLogo.svelte.d.ts +17 -0
- package/dist/components/icons/twintrinsic-source.svg +73 -0
- package/dist/components/icons/twintrinsic.svg +38 -0
- package/dist/docs/EventsTable.svelte +86 -0
- package/dist/docs/EventsTable.svelte.d.ts +27 -0
- package/dist/docs/PropsTable.svelte +103 -0
- package/dist/docs/PropsTable.svelte.d.ts +28 -0
- package/dist/docs/index.d.ts +2 -0
- package/dist/docs/index.js +2 -0
- package/dist/helpers/detectLanguage.d.ts +6 -0
- package/dist/helpers/detectLanguage.js +60 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +94 -0
- package/dist/twintrinsic.css +347 -0
- package/package.json +98 -0
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Slider - A component for selecting values from a range.
|
|
4
|
+
Provides consistent styling, accessibility features, and interactive options.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
```svelte
|
|
8
|
+
<Slider value={50} min={0} max={100} />
|
|
9
|
+
|
|
10
|
+
<Slider
|
|
11
|
+
value={[20, 80]}
|
|
12
|
+
min={0}
|
|
13
|
+
max={100}
|
|
14
|
+
step={5}
|
|
15
|
+
showTicks
|
|
16
|
+
showValue
|
|
17
|
+
onchange={(e) => console.log(e.detail.value)}
|
|
18
|
+
/>
|
|
19
|
+
|
|
20
|
+
<Slider
|
|
21
|
+
value={25}
|
|
22
|
+
min={0}
|
|
23
|
+
max={100}
|
|
24
|
+
disabled={false}
|
|
25
|
+
variant="primary"
|
|
26
|
+
orientation="horizontal"
|
|
27
|
+
/>
|
|
28
|
+
```
|
|
29
|
+
-->
|
|
30
|
+
<script>
|
|
31
|
+
import { onDestroy } from "svelte"
|
|
32
|
+
|
|
33
|
+
const {
|
|
34
|
+
/** @type {string} - Additional CSS classes */
|
|
35
|
+
class: className = "",
|
|
36
|
+
|
|
37
|
+
/** @type {string} - HTML id for accessibility */
|
|
38
|
+
id = crypto.randomUUID(),
|
|
39
|
+
|
|
40
|
+
/** @type {number|Array} - Current value or range [min, max] */
|
|
41
|
+
value = 0,
|
|
42
|
+
|
|
43
|
+
/** @type {number} - Minimum value */
|
|
44
|
+
min = 0,
|
|
45
|
+
|
|
46
|
+
/** @type {number} - Maximum value */
|
|
47
|
+
max = 100,
|
|
48
|
+
|
|
49
|
+
/** @type {number} - Step size */
|
|
50
|
+
step = 1,
|
|
51
|
+
|
|
52
|
+
/** @type {string} - Visual style variant */
|
|
53
|
+
variant = "primary",
|
|
54
|
+
|
|
55
|
+
/** @type {string} - Orientation (horizontal, vertical) */
|
|
56
|
+
orientation = "horizontal",
|
|
57
|
+
|
|
58
|
+
/** @type {boolean} - Whether the slider is disabled */
|
|
59
|
+
disabled = false,
|
|
60
|
+
|
|
61
|
+
/** @type {boolean} - Whether to show tick marks */
|
|
62
|
+
showTicks = false,
|
|
63
|
+
|
|
64
|
+
/** @type {Array} - Custom tick values */
|
|
65
|
+
tickValues = [],
|
|
66
|
+
|
|
67
|
+
/** @type {boolean} - Whether to show the current value */
|
|
68
|
+
showValue = false,
|
|
69
|
+
|
|
70
|
+
/** @type {string} - Format for displayed value */
|
|
71
|
+
valueFormat = "{value}",
|
|
72
|
+
|
|
73
|
+
/** @type {boolean} - Whether to show tooltips on hover/drag */
|
|
74
|
+
showTooltip = false,
|
|
75
|
+
|
|
76
|
+
/** @type {string} - Name attribute for form submission */
|
|
77
|
+
name,
|
|
78
|
+
|
|
79
|
+
/** @type {string} - ARIA label for accessibility */
|
|
80
|
+
ariaLabel,
|
|
81
|
+
|
|
82
|
+
/** @type {(event: CustomEvent) => void} - Change event handler */
|
|
83
|
+
onchange,
|
|
84
|
+
/** @type {(event: CustomEvent) => void} - Input event handler */
|
|
85
|
+
oninput,
|
|
86
|
+
} = $props()
|
|
87
|
+
|
|
88
|
+
// Component state
|
|
89
|
+
let sliderValues = $state([])
|
|
90
|
+
let isDragging = $state(false)
|
|
91
|
+
let dragIndex = $state(-1)
|
|
92
|
+
let hoverIndex = $state(-1)
|
|
93
|
+
let trackElement = $state()
|
|
94
|
+
let thumbElements = $state([])
|
|
95
|
+
|
|
96
|
+
// Update internal value when prop changes
|
|
97
|
+
$effect(() => {
|
|
98
|
+
sliderValues = Array.isArray(value) ? [...value] : [value]
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
// Computed values
|
|
102
|
+
const isRange = $derived(sliderValues.length > 1)
|
|
103
|
+
const range = $derived(max - min)
|
|
104
|
+
|
|
105
|
+
// Determine variant classes
|
|
106
|
+
const variantClasses = $derived(
|
|
107
|
+
{
|
|
108
|
+
default: "bg-muted dark:bg-muted",
|
|
109
|
+
primary: "bg-primary-500 dark:bg-primary-500",
|
|
110
|
+
secondary: "bg-secondary-500 dark:bg-secondary-500",
|
|
111
|
+
success: "bg-success-500 dark:bg-success-500",
|
|
112
|
+
warning: "bg-warning-500 dark:bg-warning-500",
|
|
113
|
+
error: "bg-error-500 dark:bg-error-500",
|
|
114
|
+
info: "bg-info-500 dark:bg-info-500",
|
|
115
|
+
}[variant] || "bg-primary-500 dark:bg-primary-500"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
// Generate tick values if not provided
|
|
119
|
+
const ticks = $derived.by(() => {
|
|
120
|
+
if (!showTicks) return []
|
|
121
|
+
|
|
122
|
+
if (tickValues.length > 0) {
|
|
123
|
+
return tickValues
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Generate ticks based on step
|
|
127
|
+
const count = Math.floor(range / step) + 1
|
|
128
|
+
// Limit to a reasonable number of ticks
|
|
129
|
+
const stride = count > 20 ? Math.ceil(count / 20) : 1
|
|
130
|
+
|
|
131
|
+
return Array.from({ length: Math.ceil(count / stride) }, (_, i) => min + i * stride * step)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Calculates the percentage position for a value
|
|
136
|
+
* @param {number} val - Value to calculate position for
|
|
137
|
+
* @returns {number} - Percentage (0-100)
|
|
138
|
+
*/
|
|
139
|
+
function getPercentage(val) {
|
|
140
|
+
return ((val - min) / range) * 100
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Calculates the value from a percentage position
|
|
145
|
+
* @param {number} percentage - Percentage position (0-100)
|
|
146
|
+
* @returns {number} - Value
|
|
147
|
+
*/
|
|
148
|
+
function getValueFromPercentage(percentage) {
|
|
149
|
+
const rawValue = min + (percentage / 100) * range
|
|
150
|
+
|
|
151
|
+
// Round to nearest step
|
|
152
|
+
const steppedValue = Math.round(rawValue / step) * step
|
|
153
|
+
|
|
154
|
+
// Ensure value is within bounds
|
|
155
|
+
return Math.max(min, Math.min(max, steppedValue))
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Formats the displayed value
|
|
160
|
+
* @param {number} val - Value to format
|
|
161
|
+
* @returns {string} - Formatted value
|
|
162
|
+
*/
|
|
163
|
+
function formatValue(val) {
|
|
164
|
+
return valueFormat.replace("{value}", val)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Updates the value based on pointer position
|
|
169
|
+
* @param {MouseEvent|TouchEvent} event - Pointer event
|
|
170
|
+
*/
|
|
171
|
+
function updateValue(event) {
|
|
172
|
+
if (disabled || !trackElement) return
|
|
173
|
+
|
|
174
|
+
const rect = trackElement.getBoundingClientRect()
|
|
175
|
+
const clientPos = event.type.startsWith("touch") ? event.touches[0].clientX : event.clientX
|
|
176
|
+
|
|
177
|
+
// Calculate percentage
|
|
178
|
+
let percentage
|
|
179
|
+
if (orientation === "horizontal") {
|
|
180
|
+
percentage = ((clientPos - rect.left) / rect.width) * 100
|
|
181
|
+
} else {
|
|
182
|
+
percentage = ((rect.bottom - clientPos) / rect.height) * 100
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Clamp percentage
|
|
186
|
+
percentage = Math.max(0, Math.min(100, percentage))
|
|
187
|
+
|
|
188
|
+
// Get value from percentage
|
|
189
|
+
const newValue = getValueFromPercentage(percentage)
|
|
190
|
+
|
|
191
|
+
// Update the appropriate thumb
|
|
192
|
+
if (isRange) {
|
|
193
|
+
if (dragIndex >= 0) {
|
|
194
|
+
// Update the dragging thumb
|
|
195
|
+
sliderValues[dragIndex] = newValue
|
|
196
|
+
|
|
197
|
+
// Ensure values remain in order
|
|
198
|
+
if (dragIndex === 0 && newValue > sliderValues[1]) {
|
|
199
|
+
sliderValues[0] = sliderValues[1]
|
|
200
|
+
} else if (dragIndex === 1 && newValue < sliderValues[0]) {
|
|
201
|
+
sliderValues[1] = sliderValues[0]
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
// Determine which thumb to update based on proximity
|
|
205
|
+
const dist0 = Math.abs(percentage - getPercentage(sliderValues[0]))
|
|
206
|
+
const dist1 = Math.abs(percentage - getPercentage(sliderValues[1]))
|
|
207
|
+
|
|
208
|
+
if (dist0 < dist1) {
|
|
209
|
+
sliderValues[0] = newValue
|
|
210
|
+
dragIndex = 0
|
|
211
|
+
} else {
|
|
212
|
+
sliderValues[1] = newValue
|
|
213
|
+
dragIndex = 1
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
} else {
|
|
217
|
+
sliderValues[0] = newValue
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Dispatch change event
|
|
221
|
+
dispatchChange()
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Handles pointer down event
|
|
226
|
+
* @param {MouseEvent|TouchEvent} event - Pointer event
|
|
227
|
+
* @param {number} index - Thumb index
|
|
228
|
+
*/
|
|
229
|
+
function handlePointerDown(event, index) {
|
|
230
|
+
if (disabled) return
|
|
231
|
+
|
|
232
|
+
isDragging = true
|
|
233
|
+
dragIndex = index
|
|
234
|
+
|
|
235
|
+
// Update value immediately
|
|
236
|
+
updateValue(event)
|
|
237
|
+
|
|
238
|
+
// Add document event listeners
|
|
239
|
+
if (event.type === "mousedown") {
|
|
240
|
+
document.addEventListener("mousemove", handlePointerMove)
|
|
241
|
+
document.addEventListener("mouseup", handlePointerUp)
|
|
242
|
+
} else if (event.type === "touchstart") {
|
|
243
|
+
document.addEventListener("touchmove", handlePointerMove, { passive: false })
|
|
244
|
+
document.addEventListener("touchend", handlePointerUp)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Prevent default to avoid text selection
|
|
248
|
+
event.preventDefault()
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Handles pointer move event
|
|
253
|
+
* @param {MouseEvent|TouchEvent} event - Pointer event
|
|
254
|
+
*/
|
|
255
|
+
function handlePointerMove(event) {
|
|
256
|
+
if (!isDragging) return
|
|
257
|
+
|
|
258
|
+
updateValue(event)
|
|
259
|
+
|
|
260
|
+
// Prevent scrolling on touch devices
|
|
261
|
+
if (event.type === "touchmove") {
|
|
262
|
+
event.preventDefault()
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Handles pointer up event
|
|
268
|
+
*/
|
|
269
|
+
function handlePointerUp() {
|
|
270
|
+
isDragging = false
|
|
271
|
+
dragIndex = -1
|
|
272
|
+
|
|
273
|
+
// Remove document event listeners
|
|
274
|
+
document.removeEventListener("mousemove", handlePointerMove)
|
|
275
|
+
document.removeEventListener("mouseup", handlePointerUp)
|
|
276
|
+
document.removeEventListener("touchmove", handlePointerMove)
|
|
277
|
+
document.removeEventListener("touchend", handlePointerUp)
|
|
278
|
+
|
|
279
|
+
// Dispatch final change event
|
|
280
|
+
dispatchChange()
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Handles track click
|
|
285
|
+
* @param {MouseEvent} event - Click event
|
|
286
|
+
*/
|
|
287
|
+
function handleTrackClick(event) {
|
|
288
|
+
if (disabled) return
|
|
289
|
+
|
|
290
|
+
// Only handle direct track clicks
|
|
291
|
+
if (event.target === trackElement) {
|
|
292
|
+
updateValue(event)
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Handles thumb hover
|
|
298
|
+
* @param {number} index - Thumb index
|
|
299
|
+
*/
|
|
300
|
+
function handleThumbHover(index) {
|
|
301
|
+
hoverIndex = index
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Handles thumb leave
|
|
306
|
+
*/
|
|
307
|
+
function handleThumbLeave() {
|
|
308
|
+
hoverIndex = -1
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Handles keyboard navigation
|
|
313
|
+
* @param {KeyboardEvent} event - Keydown event
|
|
314
|
+
* @param {number} index - Thumb index
|
|
315
|
+
*/
|
|
316
|
+
function handleKeydown(event, index) {
|
|
317
|
+
if (disabled) return
|
|
318
|
+
|
|
319
|
+
let newValue = sliderValues[index]
|
|
320
|
+
const stepSize = event.shiftKey ? step * 10 : step
|
|
321
|
+
|
|
322
|
+
switch (event.key) {
|
|
323
|
+
case "ArrowRight":
|
|
324
|
+
case "ArrowUp":
|
|
325
|
+
newValue = Math.min(max, newValue + stepSize)
|
|
326
|
+
break
|
|
327
|
+
case "ArrowLeft":
|
|
328
|
+
case "ArrowDown":
|
|
329
|
+
newValue = Math.max(min, newValue - stepSize)
|
|
330
|
+
break
|
|
331
|
+
case "Home":
|
|
332
|
+
newValue = min
|
|
333
|
+
break
|
|
334
|
+
case "End":
|
|
335
|
+
newValue = max
|
|
336
|
+
break
|
|
337
|
+
default:
|
|
338
|
+
return
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Ensure range values remain in order
|
|
342
|
+
if (isRange) {
|
|
343
|
+
if (index === 0 && newValue > sliderValues[1]) {
|
|
344
|
+
newValue = sliderValues[1]
|
|
345
|
+
} else if (index === 1 && newValue < sliderValues[0]) {
|
|
346
|
+
newValue = sliderValues[0]
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (newValue !== sliderValues[index]) {
|
|
351
|
+
sliderValues[index] = newValue
|
|
352
|
+
dispatchChange()
|
|
353
|
+
event.preventDefault()
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Dispatches change event
|
|
359
|
+
*/
|
|
360
|
+
function dispatchChange() {
|
|
361
|
+
const eventValue = isRange ? [...sliderValues] : sliderValues[0]
|
|
362
|
+
onchange?.(new CustomEvent("change", { detail: { value: eventValue } }))
|
|
363
|
+
oninput?.(new CustomEvent("input", { detail: { value: eventValue } }))
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Clean up event listeners on destroy
|
|
367
|
+
onDestroy(() => {
|
|
368
|
+
document.removeEventListener("mousemove", handlePointerMove)
|
|
369
|
+
document.removeEventListener("mouseup", handlePointerUp)
|
|
370
|
+
document.removeEventListener("touchmove", handlePointerMove)
|
|
371
|
+
document.removeEventListener("touchend", handlePointerUp)
|
|
372
|
+
})
|
|
373
|
+
</script>
|
|
374
|
+
|
|
375
|
+
<div
|
|
376
|
+
{id}
|
|
377
|
+
class="
|
|
378
|
+
slider
|
|
379
|
+
slider-{orientation}
|
|
380
|
+
{disabled ? 'slider-disabled' : ''}
|
|
381
|
+
{className}
|
|
382
|
+
"
|
|
383
|
+
aria-disabled={disabled}
|
|
384
|
+
>
|
|
385
|
+
{#if name}
|
|
386
|
+
<input
|
|
387
|
+
type="hidden"
|
|
388
|
+
{name}
|
|
389
|
+
value={isRange ? sliderValues.join(',') : sliderValues[0]}
|
|
390
|
+
/>
|
|
391
|
+
{/if}
|
|
392
|
+
|
|
393
|
+
<div
|
|
394
|
+
class="slider-container"
|
|
395
|
+
onclick={handleTrackClick}
|
|
396
|
+
>
|
|
397
|
+
<div
|
|
398
|
+
class="slider-track"
|
|
399
|
+
bind:this={trackElement}
|
|
400
|
+
>
|
|
401
|
+
<div
|
|
402
|
+
class="slider-track-background"
|
|
403
|
+
></div>
|
|
404
|
+
|
|
405
|
+
<div
|
|
406
|
+
class="slider-track-fill {variantClasses}"
|
|
407
|
+
style="
|
|
408
|
+
{orientation === 'horizontal'
|
|
409
|
+
? `left: ${getPercentage(isRange ? sliderValues[0] : min)}%; right: ${100 - getPercentage(isRange ? sliderValues[1] : sliderValues[0])}%`
|
|
410
|
+
: `bottom: ${getPercentage(isRange ? sliderValues[0] : min)}%; top: ${100 - getPercentage(isRange ? sliderValues[1] : sliderValues[0])}%`}
|
|
411
|
+
"
|
|
412
|
+
></div>
|
|
413
|
+
|
|
414
|
+
{#if showTicks}
|
|
415
|
+
<div class="slider-ticks">
|
|
416
|
+
{#each ticks as tick}
|
|
417
|
+
<div
|
|
418
|
+
class="slider-tick"
|
|
419
|
+
style="
|
|
420
|
+
{orientation === 'horizontal'
|
|
421
|
+
? `left: ${getPercentage(tick)}%`
|
|
422
|
+
: `bottom: ${getPercentage(tick)}%`}
|
|
423
|
+
"
|
|
424
|
+
></div>
|
|
425
|
+
{/each}
|
|
426
|
+
</div>
|
|
427
|
+
{/if}
|
|
428
|
+
|
|
429
|
+
{#each sliderValues as value, i}
|
|
430
|
+
<div
|
|
431
|
+
class="
|
|
432
|
+
slider-thumb
|
|
433
|
+
{isDragging && dragIndex === i ? 'slider-thumb-active' : ''}
|
|
434
|
+
{variantClasses}
|
|
435
|
+
"
|
|
436
|
+
style="
|
|
437
|
+
{orientation === 'horizontal'
|
|
438
|
+
? `left: ${getPercentage(value)}%`
|
|
439
|
+
: `bottom: ${getPercentage(value)}%`}
|
|
440
|
+
"
|
|
441
|
+
role="slider"
|
|
442
|
+
aria-valuemin={min}
|
|
443
|
+
aria-valuemax={max}
|
|
444
|
+
aria-valuenow={value}
|
|
445
|
+
aria-orientation={orientation}
|
|
446
|
+
aria-label={ariaLabel || `Slider ${isRange ? i + 1 : ''}`}
|
|
447
|
+
tabindex={disabled ? undefined : 0}
|
|
448
|
+
onmousedown={(e) => handlePointerDown(e, i)}
|
|
449
|
+
ontouchstart={(e) => handlePointerDown(e, i)}
|
|
450
|
+
onkeydown={(e) => handleKeydown(e, i)}
|
|
451
|
+
onmouseenter={() => handleThumbHover(i)}
|
|
452
|
+
onmouseleave={handleThumbLeave}
|
|
453
|
+
bind:this={thumbElements[i]}
|
|
454
|
+
>
|
|
455
|
+
{#if showTooltip && (isDragging && dragIndex === i || hoverIndex === i)}
|
|
456
|
+
<div class="slider-tooltip">
|
|
457
|
+
{formatValue(value)}
|
|
458
|
+
</div>
|
|
459
|
+
{/if}
|
|
460
|
+
</div>
|
|
461
|
+
{/each}
|
|
462
|
+
</div>
|
|
463
|
+
|
|
464
|
+
{#if showValue}
|
|
465
|
+
<div class="slider-values">
|
|
466
|
+
{#if isRange}
|
|
467
|
+
<div class="slider-value">{formatValue(sliderValues[0])}</div>
|
|
468
|
+
<div class="slider-value">{formatValue(sliderValues[1])}</div>
|
|
469
|
+
{:else}
|
|
470
|
+
<div class="slider-value">{formatValue(sliderValues[0])}</div>
|
|
471
|
+
{/if}
|
|
472
|
+
</div>
|
|
473
|
+
{/if}
|
|
474
|
+
</div>
|
|
475
|
+
</div>
|
|
476
|
+
|
|
477
|
+
<style>
|
|
478
|
+
@reference "../../twintrinsic.css";
|
|
479
|
+
|
|
480
|
+
.slider {
|
|
481
|
+
@apply w-full;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.slider-horizontal {
|
|
485
|
+
@apply h-12;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
.slider-vertical {
|
|
489
|
+
@apply h-48 w-12;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
.slider-disabled {
|
|
493
|
+
@apply opacity-50 cursor-not-allowed;
|
|
494
|
+
@apply pointer-events-none;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.slider-container {
|
|
498
|
+
@apply relative;
|
|
499
|
+
@apply h-full;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.slider-track {
|
|
503
|
+
@apply absolute;
|
|
504
|
+
@apply cursor-pointer;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.slider-horizontal .slider-track {
|
|
508
|
+
@apply left-0 right-0 top-1/2 -translate-y-1/2;
|
|
509
|
+
@apply h-1.5;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.slider-vertical .slider-track {
|
|
513
|
+
@apply bottom-0 top-0 left-1/2 -translate-x-1/2;
|
|
514
|
+
@apply w-1.5;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.slider-track-background {
|
|
518
|
+
@apply absolute inset-0;
|
|
519
|
+
@apply bg-muted/20 dark:bg-muted/20;
|
|
520
|
+
@apply rounded-full;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.slider-track-fill {
|
|
524
|
+
@apply absolute;
|
|
525
|
+
@apply rounded-full;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.slider-horizontal .slider-track-fill {
|
|
529
|
+
@apply h-full;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
.slider-vertical .slider-track-fill {
|
|
533
|
+
@apply w-full;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.slider-ticks {
|
|
537
|
+
@apply absolute;
|
|
538
|
+
@apply pointer-events-none;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.slider-horizontal .slider-ticks {
|
|
542
|
+
@apply left-0 right-0 top-1/2;
|
|
543
|
+
@apply h-0;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.slider-vertical .slider-ticks {
|
|
547
|
+
@apply bottom-0 top-0 left-1/2;
|
|
548
|
+
@apply w-0;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
.slider-tick {
|
|
552
|
+
@apply absolute;
|
|
553
|
+
@apply w-1 h-3;
|
|
554
|
+
@apply bg-muted/40 dark:bg-muted/40;
|
|
555
|
+
@apply rounded-sm;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
.slider-horizontal .slider-tick {
|
|
559
|
+
@apply -translate-x-1/2 -translate-y-1/2;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
.slider-vertical .slider-tick {
|
|
563
|
+
@apply -translate-x-1/2 translate-y-1/2;
|
|
564
|
+
@apply h-1 w-3;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
.slider-thumb {
|
|
568
|
+
@apply absolute;
|
|
569
|
+
@apply w-5 h-5 rounded-full;
|
|
570
|
+
@apply shadow-md;
|
|
571
|
+
@apply cursor-grab;
|
|
572
|
+
@apply focus:outline-none focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400 focus:ring-offset-2;
|
|
573
|
+
@apply transition-transform duration-150;
|
|
574
|
+
@apply z-10;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.slider-horizontal .slider-thumb {
|
|
578
|
+
@apply -translate-x-1/2 -translate-y-1/2;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.slider-vertical .slider-thumb {
|
|
582
|
+
@apply -translate-x-1/2 translate-y-1/2;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.slider-thumb-active {
|
|
586
|
+
@apply cursor-grabbing;
|
|
587
|
+
@apply scale-110;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.slider-tooltip {
|
|
591
|
+
@apply absolute;
|
|
592
|
+
@apply px-2 py-1;
|
|
593
|
+
@apply bg-background dark:bg-background;
|
|
594
|
+
@apply border border-border dark:border-border;
|
|
595
|
+
@apply rounded;
|
|
596
|
+
@apply text-xs font-medium;
|
|
597
|
+
@apply shadow-md;
|
|
598
|
+
@apply whitespace-nowrap;
|
|
599
|
+
@apply z-20;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
.slider-horizontal .slider-tooltip {
|
|
603
|
+
@apply bottom-full mb-1.5;
|
|
604
|
+
@apply left-1/2 -translate-x-1/2;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
.slider-vertical .slider-tooltip {
|
|
608
|
+
@apply left-full ml-1.5;
|
|
609
|
+
@apply top-1/2 -translate-y-1/2;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.slider-values {
|
|
613
|
+
@apply flex justify-between;
|
|
614
|
+
@apply mt-2;
|
|
615
|
+
@apply text-sm text-muted dark:text-muted;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
.slider-vertical .slider-values {
|
|
619
|
+
@apply flex-col h-full justify-between;
|
|
620
|
+
@apply ml-6 mt-0;
|
|
621
|
+
}
|
|
622
|
+
</style>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export default Slider;
|
|
2
|
+
type Slider = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Slider - A component for selecting values from a range.
|
|
8
|
+
* Provides consistent styling, accessibility features, and interactive options.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <Slider value={50} min={0} max={100} />
|
|
13
|
+
*
|
|
14
|
+
* <Slider
|
|
15
|
+
* value={[20, 80]}
|
|
16
|
+
* min={0}
|
|
17
|
+
* max={100}
|
|
18
|
+
* step={5}
|
|
19
|
+
* showTicks
|
|
20
|
+
* showValue
|
|
21
|
+
* onchange={(e) => console.log(e.detail.value)}
|
|
22
|
+
* />
|
|
23
|
+
*
|
|
24
|
+
* <Slider
|
|
25
|
+
* value={25}
|
|
26
|
+
* min={0}
|
|
27
|
+
* max={100}
|
|
28
|
+
* disabled={false}
|
|
29
|
+
* variant="primary"
|
|
30
|
+
* orientation="horizontal"
|
|
31
|
+
* />
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare const Slider: import("svelte").Component<{
|
|
35
|
+
class?: string;
|
|
36
|
+
id?: any;
|
|
37
|
+
value?: number;
|
|
38
|
+
min?: number;
|
|
39
|
+
max?: number;
|
|
40
|
+
step?: number;
|
|
41
|
+
variant?: string;
|
|
42
|
+
orientation?: string;
|
|
43
|
+
disabled?: boolean;
|
|
44
|
+
showTicks?: boolean;
|
|
45
|
+
tickValues?: any[];
|
|
46
|
+
showValue?: boolean;
|
|
47
|
+
valueFormat?: string;
|
|
48
|
+
showTooltip?: boolean;
|
|
49
|
+
name: any;
|
|
50
|
+
ariaLabel: any;
|
|
51
|
+
onchange: any;
|
|
52
|
+
oninput: any;
|
|
53
|
+
}, {}, "">;
|
|
54
|
+
type $$ComponentProps = {
|
|
55
|
+
class?: string;
|
|
56
|
+
id?: any;
|
|
57
|
+
value?: number;
|
|
58
|
+
min?: number;
|
|
59
|
+
max?: number;
|
|
60
|
+
step?: number;
|
|
61
|
+
variant?: string;
|
|
62
|
+
orientation?: string;
|
|
63
|
+
disabled?: boolean;
|
|
64
|
+
showTicks?: boolean;
|
|
65
|
+
tickValues?: any[];
|
|
66
|
+
showValue?: boolean;
|
|
67
|
+
valueFormat?: string;
|
|
68
|
+
showTooltip?: boolean;
|
|
69
|
+
name: any;
|
|
70
|
+
ariaLabel: any;
|
|
71
|
+
onchange: any;
|
|
72
|
+
oninput: any;
|
|
73
|
+
};
|