@x33025/sveltely 0.1.17 → 0.1.19
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/dist/actions/LoaderOverlay.svelte +33 -8
- package/dist/actions/LoaderOverlay.svelte.d.ts +3 -0
- package/dist/actions/loader.d.ts +3 -0
- package/dist/actions/loader.js +20 -7
- package/dist/components/Library/AnimatedNumber/AnimatedNumber.demo.svelte +3 -9
- package/dist/components/Library/ArticleEditor/ArticleEditor.svelte +3 -3
- package/dist/components/Library/ArticleEditor/ArticleEditorBody.svelte +59 -74
- package/dist/components/Library/ArticleEditor/ArticleEditorHeader.svelte +21 -31
- package/dist/components/Library/ArticleEditor/{ArticleBlockCode.svelte → Blocks/Code.svelte} +2 -3
- package/dist/components/Library/ArticleEditor/Blocks/Code.svelte.d.ts +8 -0
- package/dist/components/Library/ArticleEditor/{ArticleBlockFAQ.svelte → Blocks/FAQ.svelte} +3 -3
- package/dist/components/Library/ArticleEditor/Blocks/FAQ.svelte.d.ts +8 -0
- package/dist/components/Library/ArticleEditor/{ArticleBlockHeading.svelte → Blocks/Heading.svelte} +9 -9
- package/dist/components/Library/ArticleEditor/{ArticleBlockHeading.svelte.d.ts → Blocks/Heading.svelte.d.ts} +4 -4
- package/dist/components/Library/ArticleEditor/Blocks/Image.svelte +32 -0
- package/dist/components/Library/ArticleEditor/Blocks/Image.svelte.d.ts +10 -0
- package/dist/components/Library/ArticleEditor/{ArticleBlockList.svelte → Blocks/List.svelte} +4 -4
- package/dist/components/Library/ArticleEditor/{ArticleBlockList.svelte.d.ts → Blocks/List.svelte.d.ts} +4 -4
- package/dist/components/Library/ArticleEditor/{ArticleBlockParagraph.svelte → Blocks/Paragraph.svelte} +3 -3
- package/dist/components/Library/ArticleEditor/{ArticleBlockFallback.svelte.d.ts → Blocks/Paragraph.svelte.d.ts} +4 -4
- package/dist/components/Library/ArticleEditor/{ArticleBlockTable.svelte → Blocks/Table.svelte} +1 -1
- package/dist/components/Library/ArticleEditor/{ArticleBlockTable.svelte.d.ts → Blocks/Table.svelte.d.ts} +4 -4
- package/dist/components/Library/ArticleEditor/Blocks/index.d.ts +7 -0
- package/dist/components/Library/ArticleEditor/Blocks/index.js +7 -0
- package/dist/components/Library/ArticleEditor/index.d.ts +1 -9
- package/dist/components/Library/ArticleEditor/index.js +1 -9
- package/dist/components/Library/AsyncButton/AsyncButton.demo.svelte +2 -6
- package/dist/components/Library/AsyncButton/AsyncButton.svelte +9 -5
- package/dist/components/Library/AsyncButton/AsyncButton.svelte.d.ts +2 -1
- package/dist/components/Library/Button/Button.demo.svelte +2 -17
- package/dist/components/Library/Button/Button.demo.svelte.d.ts +0 -1
- package/dist/components/Library/Button/Button.svelte +15 -16
- package/dist/components/Library/Button/Button.svelte.d.ts +2 -1
- package/dist/components/Library/Calendar/Calendar.svelte +17 -27
- package/dist/components/Library/Checkbox/Checkbox.demo.svelte +7 -4
- package/dist/components/Library/Checkbox/Checkbox.svelte +24 -61
- package/dist/components/Library/Checkbox/Checkbox.svelte.d.ts +2 -4
- package/dist/components/Library/ChipInput/ChipInput.demo.svelte +2 -2
- package/dist/components/Library/ChipInput/ChipInput.svelte +7 -11
- package/dist/components/Library/ChipInput/ChipInput.svelte.d.ts +3 -2
- package/dist/components/Library/Dropdown/Action.svelte +1 -1
- package/dist/components/Library/Dropdown/Dropdown.demo.svelte +10 -10
- package/dist/components/Library/Dropdown/Dropdown.svelte +2 -6
- package/dist/components/Library/Dropdown/Item.svelte +2 -2
- package/dist/components/Library/Dropdown/Section.svelte +1 -1
- package/dist/components/Library/Dropdown/Trigger.svelte +3 -7
- package/dist/components/Library/Image/Image.demo.svelte +3 -3
- package/dist/components/Library/Image/Image.svelte +57 -12
- package/dist/components/Library/Image/Image.svelte.d.ts +1 -2
- package/dist/components/Library/Image/ImagePlaceholder.demo.svelte +12 -0
- package/dist/components/Library/Image/ImagePlaceholder.demo.svelte.d.ts +23 -0
- package/dist/components/Library/Image/ImagePlaceholder.svelte +28 -4
- package/dist/components/Library/Image/ImagePlaceholder.svelte.d.ts +1 -1
- package/dist/components/Library/Image/index.d.ts +1 -0
- package/dist/components/Library/Image/index.js +1 -0
- package/dist/components/Library/ImageMask/BrushPreview.svelte +6 -6
- package/dist/components/Library/ImageMask/ImageMask.demo.svelte +10 -8
- package/dist/components/Library/ImageMask/ImageMask.svelte +14 -6
- package/dist/components/Library/ImageMask/ImageMask.svelte.d.ts +1 -2
- package/dist/components/Library/ImageMask/MaskLayer.svelte +12 -6
- package/dist/components/Library/Label/Label.demo.svelte +9 -3
- package/dist/components/Library/Label/Label.svelte +8 -2
- package/dist/components/Library/Link/Link.svelte +10 -22
- package/dist/components/Library/Link/Link.svelte.d.ts +2 -3
- package/dist/components/Library/Loader/Loader.demo.svelte +9 -3
- package/dist/components/Library/NavigationStack/Link.svelte +8 -12
- package/dist/components/Library/NavigationStack/Link.svelte.d.ts +1 -3
- package/dist/components/Library/NavigationStack/SidebarToggle.svelte +8 -2
- package/dist/components/Library/NumberField/NumberField.svelte +21 -17
- package/dist/components/Library/NumberField/NumberField.svelte.d.ts +4 -2
- package/dist/components/Library/Pagination/Pagination.svelte +3 -3
- package/dist/components/Library/Popover/Popover.svelte +2 -7
- package/dist/components/Library/ScrollView/ScrollView.demo.svelte +50 -0
- package/dist/components/Library/ScrollView/ScrollView.demo.svelte.d.ts +10 -0
- package/dist/components/Library/ScrollView/ScrollView.svelte +414 -67
- package/dist/components/Library/ScrollView/ScrollView.svelte.d.ts +17 -1
- package/dist/components/Library/ScrollView/index.d.ts +1 -1
- package/dist/components/Library/SearchField/SearchField.demo.svelte +2 -2
- package/dist/components/Library/SearchField/SearchField.svelte +9 -4
- package/dist/components/Library/SearchField/SearchField.svelte.d.ts +2 -1
- package/dist/components/Library/SegmentedPicker/SegmentedPicker.demo.svelte +2 -2
- package/dist/components/Library/SegmentedPicker/SegmentedPicker.svelte +7 -7
- package/dist/components/Library/Sheet/Sheet.demo.svelte +1 -1
- package/dist/components/Library/Sheet/Sheet.svelte +2 -7
- package/dist/components/Library/Slider/Slider.demo.svelte +1 -1
- package/dist/components/Library/Slider/Slider.svelte +11 -7
- package/dist/components/Library/Slider/Slider.svelte.d.ts +2 -1
- package/dist/components/Library/Spinner/Spinner.demo.svelte +1 -1
- package/dist/components/Library/Switch/Switch.demo.svelte +7 -4
- package/dist/components/Library/Switch/Switch.svelte +28 -68
- package/dist/components/Library/Switch/Switch.svelte.d.ts +2 -4
- package/dist/components/Library/Table/Column.svelte +81 -0
- package/dist/components/Library/Table/Column.svelte.d.ts +39 -0
- package/dist/components/Library/Table/Table.demo.svelte +148 -0
- package/dist/components/Library/Table/Table.demo.svelte.d.ts +10 -0
- package/dist/components/Library/Table/Table.svelte +624 -0
- package/dist/components/Library/Table/Table.svelte.d.ts +42 -0
- package/dist/components/Library/Table/context.d.ts +5 -0
- package/dist/components/Library/Table/context.js +2 -0
- package/dist/components/Library/Table/index.js +5 -0
- package/dist/components/Library/Table/types.d.ts +37 -0
- package/dist/components/Library/Table/types.js +1 -0
- package/dist/components/Library/Text/Text.demo.svelte +21 -0
- package/dist/components/Library/Text/Text.demo.svelte.d.ts +24 -0
- package/dist/components/Library/Text/Text.svelte +41 -0
- package/dist/components/Library/Text/Text.svelte.d.ts +9 -0
- package/dist/components/Library/Text/index.d.ts +1 -0
- package/dist/components/Library/Text/index.js +1 -0
- package/dist/components/Library/TextEditor/TextEditor.svelte +15 -9
- package/dist/components/Library/TextEditor/TextEditor.svelte.d.ts +2 -4
- package/dist/components/Library/TextField/TextField.demo.svelte +1 -1
- package/dist/components/Library/TextField/TextField.svelte +21 -18
- package/dist/components/Library/TextField/TextField.svelte.d.ts +4 -2
- package/dist/components/Library/TextShimmer/TextShimmer.demo.svelte +1 -1
- package/dist/components/Library/TimePicker/TimePicker.demo.svelte +10 -2
- package/dist/components/Library/TimePicker/TimePicker.svelte +10 -5
- package/dist/components/Library/TokenSearchField/TokenSearchField.demo.svelte +4 -2
- package/dist/components/Library/TokenSearchField/TokenSearchField.svelte +11 -11
- package/dist/components/Library/TokenSearchField/TokenSearchField.svelte.d.ts +2 -1
- package/dist/components/Library/WheelPicker/WheelColumn.svelte +183 -126
- package/dist/components/Library/WheelPicker/WheelPicker.svelte +4 -4
- package/dist/components/Library/WheelPicker/WheelPicker.svelte.d.ts +2 -2
- package/dist/components/Library/WheelPicker/index.d.ts +1 -1
- package/dist/components/Library/WheelPicker/types.d.ts +6 -0
- package/dist/components/Local/ColorStyleControls.svelte +201 -0
- package/dist/components/Local/ColorStyleControls.svelte.d.ts +13 -0
- package/dist/components/Local/HeroCard.svelte +3 -3
- package/dist/components/Local/LayoutStyleControls.svelte +67 -0
- package/dist/components/Local/LayoutStyleControls.svelte.d.ts +11 -0
- package/dist/components/Local/StyleControls.svelte +48 -124
- package/dist/components/Local/StyleControls.svelte.d.ts +7 -5
- package/dist/index.d.ts +9 -2
- package/dist/index.js +5 -1
- package/dist/style/index.css +7 -12
- package/dist/style/label.d.ts +2 -1
- package/dist/style/label.js +2 -1
- package/dist/style/surface.js +4 -0
- package/dist/style/text-editor.d.ts +2 -13
- package/dist/style/text-editor.js +1 -12
- package/dist/style/text.d.ts +26 -0
- package/dist/style/text.js +69 -0
- package/dist/style/tooltip.d.ts +4 -0
- package/dist/style/tooltip.js +1 -0
- package/dist/style.css +41 -114
- package/package.json +1 -1
- package/dist/components/Library/ArticleEditor/ArticleBlockCode.svelte.d.ts +0 -8
- package/dist/components/Library/ArticleEditor/ArticleBlockFAQ.svelte.d.ts +0 -8
- package/dist/components/Library/ArticleEditor/ArticleBlockFallback.svelte +0 -79
- package/dist/components/Library/ArticleEditor/ArticleBlockImage.svelte +0 -48
- package/dist/components/Library/ArticleEditor/ArticleBlockImage.svelte.d.ts +0 -9
- package/dist/components/Library/ArticleEditor/ArticleBlockParagraph.svelte.d.ts +0 -15
- package/dist/components/Library/ArticleEditor/ArticleImagePreview.svelte +0 -71
- package/dist/components/Library/ArticleEditor/ArticleImagePreview.svelte.d.ts +0 -8
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
<script lang="ts" generics="T extends string | number">
|
|
2
|
-
import { tick } from 'svelte';
|
|
2
|
+
import { tick, untrack } from 'svelte';
|
|
3
|
+
import ScrollView, {
|
|
4
|
+
type ScrollGeometry,
|
|
5
|
+
type ScrollViewHandle
|
|
6
|
+
} from '../ScrollView';
|
|
3
7
|
import type { WheelOption } from './types';
|
|
4
8
|
|
|
5
9
|
type Props = {
|
|
@@ -10,17 +14,49 @@
|
|
|
10
14
|
|
|
11
15
|
let { options, value = $bindable<T>(), onChange }: Props = $props();
|
|
12
16
|
|
|
13
|
-
let viewport = $state<
|
|
17
|
+
let viewport = $state<ScrollViewHandle | null>(null);
|
|
14
18
|
let optionRefs = $state<(HTMLButtonElement | null)[]>([]);
|
|
15
19
|
let scrollTimeout = $state<ReturnType<typeof setTimeout> | null>(null);
|
|
16
|
-
let scrollingLockTimeout = $state<ReturnType<typeof setTimeout> | null>(null);
|
|
17
20
|
let isUserScrolling = $state(false);
|
|
18
21
|
let scrollAnimationFrame = $state<number | null>(null);
|
|
19
|
-
let
|
|
22
|
+
let spacerSize = $state(0);
|
|
23
|
+
let optionHeight = $state(0);
|
|
24
|
+
let scrollOffsetY = $state(0);
|
|
25
|
+
let optionPointer: { id: number; x: number; y: number; moved: boolean } | null = null;
|
|
20
26
|
|
|
21
27
|
const easeOutCubic = (t: number) => 1 - Math.pow(1 - t, 3);
|
|
22
28
|
|
|
23
|
-
const
|
|
29
|
+
const resolveOptionHeight = (nextViewport = viewport) => {
|
|
30
|
+
const measuredOptionHeight = optionRefs.find((element) => element !== null)?.clientHeight;
|
|
31
|
+
const cssOptionHeight =
|
|
32
|
+
typeof document === 'undefined'
|
|
33
|
+
? 0
|
|
34
|
+
: parseFloat(
|
|
35
|
+
getComputedStyle(nextViewport?.element ?? document.documentElement).getPropertyValue(
|
|
36
|
+
'--wheel-picker-option-height'
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return measuredOptionHeight && measuredOptionHeight > 0
|
|
41
|
+
? measuredOptionHeight
|
|
42
|
+
: Number.isFinite(cssOptionHeight)
|
|
43
|
+
? cssOptionHeight
|
|
44
|
+
: 0;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const measureSpacerSize = (nextViewport = viewport) => {
|
|
48
|
+
if (!nextViewport) return;
|
|
49
|
+
const nextOptionHeight = resolveOptionHeight(nextViewport);
|
|
50
|
+
const nextSpacerSize = Math.max(0, (nextViewport.clientHeight - nextOptionHeight) / 2);
|
|
51
|
+
if (Math.abs(optionHeight - nextOptionHeight) > 0.5) {
|
|
52
|
+
optionHeight = nextOptionHeight;
|
|
53
|
+
}
|
|
54
|
+
if (Math.abs(spacerSize - nextSpacerSize) > 0.5) {
|
|
55
|
+
spacerSize = nextSpacerSize;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const animateScrollTo = (nextViewport: ScrollViewHandle, targetTop: number, duration = 220) => {
|
|
24
60
|
if (scrollAnimationFrame) cancelAnimationFrame(scrollAnimationFrame);
|
|
25
61
|
|
|
26
62
|
const startTop = nextViewport.scrollTop;
|
|
@@ -47,7 +83,7 @@
|
|
|
47
83
|
};
|
|
48
84
|
|
|
49
85
|
const scrollSelectedIntoView = async (
|
|
50
|
-
nextViewport:
|
|
86
|
+
nextViewport: ScrollViewHandle | null,
|
|
51
87
|
element: HTMLButtonElement | null
|
|
52
88
|
) => {
|
|
53
89
|
if (!nextViewport || !element) return;
|
|
@@ -63,7 +99,7 @@
|
|
|
63
99
|
};
|
|
64
100
|
|
|
65
101
|
const getCenteredIndex = (
|
|
66
|
-
nextViewport:
|
|
102
|
+
nextViewport: ScrollViewHandle | null,
|
|
67
103
|
elements: Array<HTMLButtonElement | null>
|
|
68
104
|
) => {
|
|
69
105
|
if (!nextViewport) return -1;
|
|
@@ -87,7 +123,7 @@
|
|
|
87
123
|
};
|
|
88
124
|
|
|
89
125
|
const getCenterDistance = (
|
|
90
|
-
nextViewport:
|
|
126
|
+
nextViewport: ScrollViewHandle | null,
|
|
91
127
|
element: HTMLButtonElement | null
|
|
92
128
|
) => {
|
|
93
129
|
if (!nextViewport || !element) return Number.POSITIVE_INFINITY;
|
|
@@ -98,30 +134,6 @@
|
|
|
98
134
|
return Math.abs(elementCenter - viewportCenter);
|
|
99
135
|
};
|
|
100
136
|
|
|
101
|
-
const updateVisualDepth = () => {
|
|
102
|
-
if (!viewport) return;
|
|
103
|
-
const viewportRect = viewport.getBoundingClientRect();
|
|
104
|
-
const viewportCenter = viewportRect.top + viewportRect.height / 2;
|
|
105
|
-
const maxDistance = Math.max(viewportRect.height / 2, 1);
|
|
106
|
-
|
|
107
|
-
for (const element of optionRefs) {
|
|
108
|
-
if (!element) continue;
|
|
109
|
-
const rect = element.getBoundingClientRect();
|
|
110
|
-
const center = rect.top + rect.height / 2;
|
|
111
|
-
const ratio = Math.min(1, Math.abs(center - viewportCenter) / maxDistance);
|
|
112
|
-
const emphasis = Math.pow(Math.cos(ratio * (Math.PI / 2)), 2);
|
|
113
|
-
element.style.setProperty('--wheel-column-emphasis', emphasis.toFixed(3));
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const scheduleVisualDepthUpdate = () => {
|
|
118
|
-
if (visualUpdateFrame) cancelAnimationFrame(visualUpdateFrame);
|
|
119
|
-
visualUpdateFrame = requestAnimationFrame(() => {
|
|
120
|
-
visualUpdateFrame = null;
|
|
121
|
-
updateVisualDepth();
|
|
122
|
-
});
|
|
123
|
-
};
|
|
124
|
-
|
|
125
137
|
const applyValue = (nextValue: T) => {
|
|
126
138
|
if (value === nextValue) return;
|
|
127
139
|
value = nextValue;
|
|
@@ -129,13 +141,39 @@
|
|
|
129
141
|
};
|
|
130
142
|
|
|
131
143
|
const selectOption = (option: WheelOption<T>, index: number) => {
|
|
144
|
+
if (scrollTimeout) clearTimeout(scrollTimeout);
|
|
145
|
+
isUserScrolling = false;
|
|
132
146
|
applyValue(option.value);
|
|
133
147
|
void scrollSelectedIntoView(viewport, optionRefs[index] ?? null);
|
|
134
|
-
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const handleOptionPointerdown = (event: PointerEvent) => {
|
|
151
|
+
optionPointer = {
|
|
152
|
+
id: event.pointerId,
|
|
153
|
+
x: event.clientX,
|
|
154
|
+
y: event.clientY,
|
|
155
|
+
moved: false
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const handleOptionPointermove = (event: PointerEvent) => {
|
|
160
|
+
if (!optionPointer || optionPointer.id !== event.pointerId) return;
|
|
161
|
+
const distance = Math.hypot(event.clientX - optionPointer.x, event.clientY - optionPointer.y);
|
|
162
|
+
if (distance > 6) optionPointer.moved = true;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const handleOptionClick = (option: WheelOption<T>, index: number) => {
|
|
166
|
+
if (optionPointer?.moved) {
|
|
167
|
+
optionPointer = null;
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
optionPointer = null;
|
|
171
|
+
selectOption(option, index);
|
|
135
172
|
};
|
|
136
173
|
|
|
137
174
|
const syncToCurrentValue = () => {
|
|
138
175
|
if (isUserScrolling || !viewport) return;
|
|
176
|
+
measureSpacerSize(viewport);
|
|
139
177
|
const index = options.findIndex((option) => option.value === value);
|
|
140
178
|
if (index < 0) return;
|
|
141
179
|
const element = optionRefs[index] ?? null;
|
|
@@ -143,67 +181,70 @@
|
|
|
143
181
|
if (getCenterDistance(viewport, element) > 1) {
|
|
144
182
|
void scrollSelectedIntoView(viewport, element);
|
|
145
183
|
}
|
|
146
|
-
scheduleVisualDepthUpdate();
|
|
147
184
|
};
|
|
148
185
|
|
|
149
|
-
const
|
|
150
|
-
|
|
186
|
+
const settleScroll = () => {
|
|
187
|
+
isUserScrolling = false;
|
|
188
|
+
const centeredIndex = getCenteredIndex(viewport, optionRefs);
|
|
189
|
+
if (centeredIndex < 0) return;
|
|
190
|
+
const centeredOption = options[centeredIndex];
|
|
191
|
+
const centeredElement = optionRefs[centeredIndex] ?? null;
|
|
192
|
+
if (!centeredOption || !centeredElement) return;
|
|
193
|
+
|
|
194
|
+
const centerDistance = getCenterDistance(viewport, centeredElement);
|
|
195
|
+
if (centerDistance > 1) {
|
|
196
|
+
void scrollSelectedIntoView(viewport, centeredElement);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
applyValue(centeredOption.value);
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const handleScroll = (geometry: ScrollGeometry) => {
|
|
203
|
+
scrollOffsetY = geometry.offset.y;
|
|
204
|
+
measureSpacerSize();
|
|
151
205
|
isUserScrolling = true;
|
|
152
|
-
if (scrollingLockTimeout) clearTimeout(scrollingLockTimeout);
|
|
153
|
-
scrollingLockTimeout = setTimeout(() => {
|
|
154
|
-
isUserScrolling = false;
|
|
155
|
-
}, 180);
|
|
156
206
|
|
|
157
207
|
if (scrollTimeout) clearTimeout(scrollTimeout);
|
|
158
|
-
scrollTimeout = setTimeout(
|
|
159
|
-
const centeredIndex = getCenteredIndex(viewport, optionRefs);
|
|
160
|
-
if (centeredIndex < 0) return;
|
|
161
|
-
const centeredOption = options[centeredIndex];
|
|
162
|
-
const centeredElement = optionRefs[centeredIndex] ?? null;
|
|
163
|
-
if (!centeredOption || !centeredElement) return;
|
|
164
|
-
|
|
165
|
-
const centerDistance = getCenterDistance(viewport, centeredElement);
|
|
166
|
-
if (centerDistance > 1) {
|
|
167
|
-
void scrollSelectedIntoView(viewport, centeredElement);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
applyValue(centeredOption.value);
|
|
171
|
-
scheduleVisualDepthUpdate();
|
|
172
|
-
}, 140);
|
|
208
|
+
scrollTimeout = setTimeout(settleScroll, 240);
|
|
173
209
|
};
|
|
174
210
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
211
|
+
$effect(() => {
|
|
212
|
+
const nextViewport = viewport;
|
|
213
|
+
const nextValue = value;
|
|
214
|
+
const nextOptions = options;
|
|
215
|
+
if (!nextViewport) return;
|
|
216
|
+
|
|
217
|
+
void tick().then(async () => {
|
|
218
|
+
if (viewport !== nextViewport || value !== nextValue || options !== nextOptions) return;
|
|
219
|
+
untrack(() => {
|
|
220
|
+
measureSpacerSize(nextViewport);
|
|
221
|
+
});
|
|
222
|
+
await tick();
|
|
223
|
+
if (viewport !== nextViewport || value !== nextValue || options !== nextOptions) return;
|
|
224
|
+
untrack(() => {
|
|
225
|
+
syncToCurrentValue();
|
|
226
|
+
});
|
|
180
227
|
});
|
|
228
|
+
});
|
|
181
229
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
scheduleVisualDepthUpdate();
|
|
187
|
-
});
|
|
188
|
-
},
|
|
189
|
-
destroy() {
|
|
190
|
-
if (scrollTimeout) clearTimeout(scrollTimeout);
|
|
191
|
-
if (scrollingLockTimeout) clearTimeout(scrollingLockTimeout);
|
|
192
|
-
if (scrollAnimationFrame) cancelAnimationFrame(scrollAnimationFrame);
|
|
193
|
-
if (visualUpdateFrame) cancelAnimationFrame(visualUpdateFrame);
|
|
194
|
-
viewport = null;
|
|
195
|
-
}
|
|
230
|
+
$effect(() => {
|
|
231
|
+
return () => {
|
|
232
|
+
if (scrollTimeout) clearTimeout(scrollTimeout);
|
|
233
|
+
if (scrollAnimationFrame) cancelAnimationFrame(scrollAnimationFrame);
|
|
196
234
|
};
|
|
197
|
-
};
|
|
235
|
+
});
|
|
198
236
|
</script>
|
|
199
237
|
|
|
200
|
-
<
|
|
201
|
-
|
|
202
|
-
bind:
|
|
203
|
-
|
|
204
|
-
|
|
238
|
+
<ScrollView
|
|
239
|
+
axis="vertical"
|
|
240
|
+
bind:viewport
|
|
241
|
+
scrollGradient={false}
|
|
242
|
+
showIndicators={false}
|
|
243
|
+
contentStyles={{ paddingX: 0, paddingY: 0 }}
|
|
244
|
+
onScroll={handleScroll}
|
|
205
245
|
>
|
|
206
246
|
<div class="wheel-column-options vstack">
|
|
247
|
+
<div class="wheel-column-spacer" style:height={`${spacerSize}px`} aria-hidden="true"></div>
|
|
207
248
|
{#each options as option, index (option.value)}
|
|
208
249
|
<button
|
|
209
250
|
bind:this={optionRefs[index]}
|
|
@@ -211,47 +252,58 @@
|
|
|
211
252
|
class="wheel-column-option"
|
|
212
253
|
class:wheel-column-option-selected={option.value === value}
|
|
213
254
|
aria-pressed={option.value === value}
|
|
214
|
-
|
|
255
|
+
onpointerdown={handleOptionPointerdown}
|
|
256
|
+
onpointermove={handleOptionPointermove}
|
|
257
|
+
onpointercancel={() => {
|
|
258
|
+
optionPointer = null;
|
|
259
|
+
}}
|
|
260
|
+
onclick={() => handleOptionClick(option, index)}
|
|
215
261
|
>
|
|
216
262
|
{option.label}
|
|
217
263
|
</button>
|
|
218
264
|
{/each}
|
|
265
|
+
<div class="wheel-column-spacer" style:height={`${spacerSize}px`} aria-hidden="true"></div>
|
|
266
|
+
</div>
|
|
267
|
+
</ScrollView>
|
|
268
|
+
|
|
269
|
+
<div
|
|
270
|
+
class="wheel-column-active-layer"
|
|
271
|
+
style:top={`${spacerSize}px`}
|
|
272
|
+
style:height={`${optionHeight}px`}
|
|
273
|
+
aria-hidden="true"
|
|
274
|
+
>
|
|
275
|
+
<div
|
|
276
|
+
class="wheel-column-active-options"
|
|
277
|
+
style:transform={`translateY(${-scrollOffsetY - spacerSize}px)`}
|
|
278
|
+
>
|
|
279
|
+
<div class="wheel-column-spacer" style:height={`${spacerSize}px`}></div>
|
|
280
|
+
{#each options as option (option.value)}
|
|
281
|
+
<div class="wheel-column-active-option">{option.label}</div>
|
|
282
|
+
{/each}
|
|
283
|
+
<div class="wheel-column-spacer" style:height={`${spacerSize}px`}></div>
|
|
219
284
|
</div>
|
|
220
285
|
</div>
|
|
221
286
|
|
|
222
287
|
<style>
|
|
223
|
-
.wheel-column
|
|
224
|
-
height: 100%;
|
|
225
|
-
display: flex;
|
|
226
|
-
flex-direction: column;
|
|
227
|
-
min-height: 0;
|
|
288
|
+
:global(.wheel-picker-column) {
|
|
228
289
|
position: relative;
|
|
229
|
-
overflow
|
|
230
|
-
overflow-x: hidden;
|
|
231
|
-
overscroll-behavior-y: contain;
|
|
232
|
-
scrollbar-width: none;
|
|
233
|
-
-ms-overflow-style: none;
|
|
234
|
-
z-index: 1;
|
|
290
|
+
overflow: hidden;
|
|
235
291
|
}
|
|
236
292
|
|
|
237
|
-
.wheel-column-
|
|
238
|
-
|
|
293
|
+
:global(.wheel-picker-column > .scroll-view) {
|
|
294
|
+
z-index: 1;
|
|
239
295
|
}
|
|
240
296
|
|
|
241
|
-
.wheel-column-
|
|
242
|
-
|
|
243
|
-
content: '';
|
|
244
|
-
display: block;
|
|
245
|
-
flex: 0 0 calc(50% - (var(--wheel-picker-option-height) / 2));
|
|
297
|
+
.wheel-column-options {
|
|
298
|
+
gap: 0;
|
|
246
299
|
}
|
|
247
300
|
|
|
248
|
-
.wheel-column-
|
|
301
|
+
.wheel-column-spacer {
|
|
249
302
|
flex: 0 0 auto;
|
|
250
|
-
|
|
303
|
+
min-height: 0;
|
|
251
304
|
}
|
|
252
305
|
|
|
253
306
|
.wheel-column-option {
|
|
254
|
-
--wheel-column-emphasis: 0;
|
|
255
307
|
width: 100%;
|
|
256
308
|
height: var(--wheel-picker-option-height);
|
|
257
309
|
border: none;
|
|
@@ -260,37 +312,42 @@
|
|
|
260
312
|
display: flex;
|
|
261
313
|
align-items: center;
|
|
262
314
|
justify-content: center;
|
|
263
|
-
padding:
|
|
315
|
+
padding: calc(var(--sveltely-padding-y) * 0.67 * var(--wheel-picker-scale))
|
|
316
|
+
calc(var(--sveltely-padding-x) * 0.67 * var(--wheel-picker-scale));
|
|
264
317
|
font-size: calc(var(--wheel-picker-font-size) * 0.875);
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
text-
|
|
268
|
-
|
|
269
|
-
position: relative;
|
|
270
|
-
z-index: 1;
|
|
271
|
-
opacity: calc(0.3 + (var(--wheel-column-emphasis) * 0.7));
|
|
272
|
-
transform: scale(calc(0.84 + (var(--wheel-column-emphasis) * 0.16)));
|
|
273
|
-
transform-origin: center;
|
|
318
|
+
font-variant-numeric: tabular-nums;
|
|
319
|
+
line-height: 1.2;
|
|
320
|
+
color: var(--sveltely-text-secondary-color);
|
|
321
|
+
font-weight: 400;
|
|
274
322
|
transition:
|
|
275
|
-
color
|
|
276
|
-
|
|
277
|
-
opacity 160ms,
|
|
278
|
-
transform 160ms;
|
|
323
|
+
color 120ms,
|
|
324
|
+
font-weight 120ms;
|
|
279
325
|
}
|
|
280
326
|
|
|
281
|
-
.wheel-column-
|
|
282
|
-
|
|
327
|
+
.wheel-column-active-layer {
|
|
328
|
+
position: absolute;
|
|
329
|
+
inset-inline: 0;
|
|
330
|
+
z-index: 2;
|
|
331
|
+
overflow: hidden;
|
|
332
|
+
pointer-events: none;
|
|
283
333
|
}
|
|
284
334
|
|
|
285
|
-
.wheel-column-
|
|
286
|
-
|
|
287
|
-
outline-offset: 2px;
|
|
335
|
+
.wheel-column-active-options {
|
|
336
|
+
will-change: transform;
|
|
288
337
|
}
|
|
289
338
|
|
|
290
|
-
.wheel-column-option
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
339
|
+
.wheel-column-active-option {
|
|
340
|
+
display: flex;
|
|
341
|
+
width: 100%;
|
|
342
|
+
height: var(--wheel-picker-option-height);
|
|
343
|
+
align-items: center;
|
|
344
|
+
justify-content: center;
|
|
345
|
+
padding: calc(var(--sveltely-padding-y) * 0.67 * var(--wheel-picker-scale))
|
|
346
|
+
calc(var(--sveltely-padding-x) * 0.67 * var(--wheel-picker-scale));
|
|
347
|
+
font-size: calc(var(--wheel-picker-font-size) * 0.875);
|
|
348
|
+
font-variant-numeric: tabular-nums;
|
|
349
|
+
line-height: 1.2;
|
|
350
|
+
color: var(--sveltely-text-primary-color);
|
|
351
|
+
font-weight: 600;
|
|
295
352
|
}
|
|
296
353
|
</style>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import WheelColumn from './WheelColumn.svelte';
|
|
3
3
|
import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
|
|
4
|
-
import type {
|
|
4
|
+
import type { AnyWheelColumn } from './types';
|
|
5
5
|
|
|
6
6
|
type Props = {
|
|
7
|
-
columns:
|
|
7
|
+
columns: AnyWheelColumn[];
|
|
8
8
|
height?: number | string;
|
|
9
9
|
} & StyleProps &
|
|
10
10
|
Record<string, unknown>;
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
height: var(--wheel-picker-option-height);
|
|
96
96
|
transform: translateY(-50%);
|
|
97
97
|
border-radius: var(--sveltely-border-radius);
|
|
98
|
-
background: color-mix(in oklab, var(--sveltely-inactive-color) 85%, white);
|
|
98
|
+
background: color-mix(in oklab, var(--sveltely-control-inactive-color) 85%, white);
|
|
99
99
|
pointer-events: none;
|
|
100
100
|
z-index: 0;
|
|
101
101
|
}
|
|
@@ -105,6 +105,6 @@
|
|
|
105
105
|
font-size: calc(var(--wheel-picker-font-size) * 0.75);
|
|
106
106
|
line-height: 1;
|
|
107
107
|
font-weight: 500;
|
|
108
|
-
color: var(--sveltely-secondary-color);
|
|
108
|
+
color: var(--sveltely-text-secondary-color);
|
|
109
109
|
}
|
|
110
110
|
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type StyleProps } from '../../../style/surface';
|
|
2
|
-
import type {
|
|
2
|
+
import type { AnyWheelColumn } from './types';
|
|
3
3
|
type Props = {
|
|
4
|
-
columns:
|
|
4
|
+
columns: AnyWheelColumn[];
|
|
5
5
|
height?: number | string;
|
|
6
6
|
} & StyleProps & Record<string, unknown>;
|
|
7
7
|
declare const WheelPicker: import("svelte").Component<Props, {}, "">;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default } from './WheelPicker.svelte';
|
|
2
|
-
export type { WheelColumn, WheelOption } from './types';
|
|
2
|
+
export type { AnyWheelColumn, WheelColumn, WheelOption } from './types';
|
|
@@ -8,3 +8,9 @@ export type WheelColumn<TValue extends string | number = string> = {
|
|
|
8
8
|
options: WheelOption<TValue>[];
|
|
9
9
|
onChange?: (value: TValue) => void;
|
|
10
10
|
};
|
|
11
|
+
export type AnyWheelColumn = {
|
|
12
|
+
label?: string;
|
|
13
|
+
value: string | number;
|
|
14
|
+
options: WheelOption<string | number>[];
|
|
15
|
+
onChange?: (value: string | number) => void;
|
|
16
|
+
};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Divider from '../Library/Divider';
|
|
3
|
+
import HStack from '../Library/HStack';
|
|
4
|
+
import Label from '../Library/Label';
|
|
5
|
+
import VStack from '../Library/VStack';
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
borderColor?: string;
|
|
9
|
+
textPrimaryColor?: string;
|
|
10
|
+
textSecondaryColor?: string;
|
|
11
|
+
textTertiaryColor?: string;
|
|
12
|
+
backgroundColor?: string;
|
|
13
|
+
controlActiveColor?: string;
|
|
14
|
+
controlInactiveColor?: string;
|
|
15
|
+
controlBackgroundColor?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
borderColor = $bindable('#e4e4e7'),
|
|
20
|
+
textPrimaryColor = $bindable('#18181b'),
|
|
21
|
+
textSecondaryColor = $bindable('#71717a'),
|
|
22
|
+
textTertiaryColor = $bindable('#a1a1aa'),
|
|
23
|
+
backgroundColor = $bindable('#ffffff'),
|
|
24
|
+
controlActiveColor = $bindable('#18181b'),
|
|
25
|
+
controlInactiveColor = $bindable('#f4f4f5'),
|
|
26
|
+
controlBackgroundColor = $bindable('#fafafa')
|
|
27
|
+
}: Props = $props();
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<VStack gap={5}>
|
|
31
|
+
<Label label="Text colors" color="var(--sveltely-text-tertiary-color)" fontSize={7.5} />
|
|
32
|
+
<Label
|
|
33
|
+
label="Text primary"
|
|
34
|
+
orientation="leading"
|
|
35
|
+
width="100%"
|
|
36
|
+
align="center"
|
|
37
|
+
justify="between"
|
|
38
|
+
gap={5}
|
|
39
|
+
>
|
|
40
|
+
<HStack width="100%" align="center" justify="end" gap={5}>
|
|
41
|
+
<span class="text-[var(--sveltely-text-secondary-color)]">{textPrimaryColor}</span>
|
|
42
|
+
<input
|
|
43
|
+
bind:value={textPrimaryColor}
|
|
44
|
+
type="color"
|
|
45
|
+
aria-label="Text primary"
|
|
46
|
+
class="color-input"
|
|
47
|
+
/>
|
|
48
|
+
</HStack>
|
|
49
|
+
</Label>
|
|
50
|
+
<Label
|
|
51
|
+
label="Text secondary"
|
|
52
|
+
orientation="leading"
|
|
53
|
+
width="100%"
|
|
54
|
+
align="center"
|
|
55
|
+
justify="between"
|
|
56
|
+
gap={5}
|
|
57
|
+
>
|
|
58
|
+
<HStack width="100%" align="center" justify="end" gap={5}>
|
|
59
|
+
<span class="text-[var(--sveltely-text-secondary-color)]">{textSecondaryColor}</span>
|
|
60
|
+
<input
|
|
61
|
+
bind:value={textSecondaryColor}
|
|
62
|
+
type="color"
|
|
63
|
+
aria-label="Text secondary"
|
|
64
|
+
class="color-input"
|
|
65
|
+
/>
|
|
66
|
+
</HStack>
|
|
67
|
+
</Label>
|
|
68
|
+
<Label
|
|
69
|
+
label="Text tertiary"
|
|
70
|
+
orientation="leading"
|
|
71
|
+
width="100%"
|
|
72
|
+
align="center"
|
|
73
|
+
justify="between"
|
|
74
|
+
gap={5}
|
|
75
|
+
>
|
|
76
|
+
<HStack width="100%" align="center" justify="end" gap={5}>
|
|
77
|
+
<span class="text-[var(--sveltely-text-secondary-color)]">{textTertiaryColor}</span>
|
|
78
|
+
<input
|
|
79
|
+
bind:value={textTertiaryColor}
|
|
80
|
+
type="color"
|
|
81
|
+
aria-label="Text tertiary"
|
|
82
|
+
class="color-input"
|
|
83
|
+
/>
|
|
84
|
+
</HStack>
|
|
85
|
+
</Label>
|
|
86
|
+
<Divider />
|
|
87
|
+
<Label label="Surface colors" color="var(--sveltely-text-tertiary-color)" fontSize={7.5} />
|
|
88
|
+
<Label
|
|
89
|
+
label="Background color"
|
|
90
|
+
orientation="leading"
|
|
91
|
+
width="100%"
|
|
92
|
+
align="center"
|
|
93
|
+
justify="between"
|
|
94
|
+
gap={5}
|
|
95
|
+
>
|
|
96
|
+
<HStack width="100%" align="center" justify="end" gap={5}>
|
|
97
|
+
<span class="text-[var(--sveltely-text-secondary-color)]">{backgroundColor}</span>
|
|
98
|
+
<input
|
|
99
|
+
bind:value={backgroundColor}
|
|
100
|
+
type="color"
|
|
101
|
+
aria-label="Background color"
|
|
102
|
+
class="color-input"
|
|
103
|
+
/>
|
|
104
|
+
</HStack>
|
|
105
|
+
</Label>
|
|
106
|
+
<Label
|
|
107
|
+
label="Border color"
|
|
108
|
+
orientation="leading"
|
|
109
|
+
width="100%"
|
|
110
|
+
align="center"
|
|
111
|
+
justify="between"
|
|
112
|
+
gap={5}
|
|
113
|
+
>
|
|
114
|
+
<HStack width="100%" align="center" justify="end" gap={5}>
|
|
115
|
+
<span class="text-[var(--sveltely-text-secondary-color)]">{borderColor}</span>
|
|
116
|
+
<input bind:value={borderColor} type="color" aria-label="Border color" class="color-input" />
|
|
117
|
+
</HStack>
|
|
118
|
+
</Label>
|
|
119
|
+
<Divider />
|
|
120
|
+
<Label label="Control colors" color="var(--sveltely-text-tertiary-color)" fontSize={7.5} />
|
|
121
|
+
<Label
|
|
122
|
+
label="Control active"
|
|
123
|
+
orientation="leading"
|
|
124
|
+
width="100%"
|
|
125
|
+
align="center"
|
|
126
|
+
justify="between"
|
|
127
|
+
gap={5}
|
|
128
|
+
>
|
|
129
|
+
<HStack width="100%" align="center" justify="end" gap={5}>
|
|
130
|
+
<span class="text-[var(--sveltely-text-secondary-color)]">{controlActiveColor}</span>
|
|
131
|
+
<input
|
|
132
|
+
bind:value={controlActiveColor}
|
|
133
|
+
type="color"
|
|
134
|
+
aria-label="Control active"
|
|
135
|
+
class="color-input"
|
|
136
|
+
/>
|
|
137
|
+
</HStack>
|
|
138
|
+
</Label>
|
|
139
|
+
<Label
|
|
140
|
+
label="Control background"
|
|
141
|
+
orientation="leading"
|
|
142
|
+
width="100%"
|
|
143
|
+
align="center"
|
|
144
|
+
justify="between"
|
|
145
|
+
gap={5}
|
|
146
|
+
>
|
|
147
|
+
<HStack width="100%" align="center" justify="end" gap={5}>
|
|
148
|
+
<span class="text-[var(--sveltely-text-secondary-color)]">{controlBackgroundColor}</span>
|
|
149
|
+
<input
|
|
150
|
+
bind:value={controlBackgroundColor}
|
|
151
|
+
type="color"
|
|
152
|
+
aria-label="Control background"
|
|
153
|
+
class="color-input"
|
|
154
|
+
/>
|
|
155
|
+
</HStack>
|
|
156
|
+
</Label>
|
|
157
|
+
<Label
|
|
158
|
+
label="Control inactive"
|
|
159
|
+
orientation="leading"
|
|
160
|
+
width="100%"
|
|
161
|
+
align="center"
|
|
162
|
+
justify="between"
|
|
163
|
+
gap={5}
|
|
164
|
+
>
|
|
165
|
+
<HStack width="100%" align="center" justify="end" gap={5}>
|
|
166
|
+
<span class="text-[var(--sveltely-text-secondary-color)]">{controlInactiveColor}</span>
|
|
167
|
+
<input
|
|
168
|
+
bind:value={controlInactiveColor}
|
|
169
|
+
type="color"
|
|
170
|
+
aria-label="Control inactive"
|
|
171
|
+
class="color-input"
|
|
172
|
+
/>
|
|
173
|
+
</HStack>
|
|
174
|
+
</Label>
|
|
175
|
+
</VStack>
|
|
176
|
+
|
|
177
|
+
<style>
|
|
178
|
+
.color-input {
|
|
179
|
+
width: 2.5rem;
|
|
180
|
+
height: 2.5rem;
|
|
181
|
+
flex: 0 0 2.5rem;
|
|
182
|
+
border: 1px solid var(--sveltely-border-color);
|
|
183
|
+
border-radius: 0.375rem;
|
|
184
|
+
background: white;
|
|
185
|
+
padding: 0.1875rem;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.color-input::-webkit-color-swatch-wrapper {
|
|
189
|
+
padding: 0;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.color-input::-webkit-color-swatch {
|
|
193
|
+
border: 0;
|
|
194
|
+
border-radius: 0.25rem;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.color-input::-moz-color-swatch {
|
|
198
|
+
border: 0;
|
|
199
|
+
border-radius: 0.25rem;
|
|
200
|
+
}
|
|
201
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
borderColor?: string;
|
|
3
|
+
textPrimaryColor?: string;
|
|
4
|
+
textSecondaryColor?: string;
|
|
5
|
+
textTertiaryColor?: string;
|
|
6
|
+
backgroundColor?: string;
|
|
7
|
+
controlActiveColor?: string;
|
|
8
|
+
controlInactiveColor?: string;
|
|
9
|
+
controlBackgroundColor?: string;
|
|
10
|
+
};
|
|
11
|
+
declare const ColorStyleControls: import("svelte").Component<Props, {}, "backgroundColor" | "borderColor" | "textPrimaryColor" | "textSecondaryColor" | "textTertiaryColor" | "controlActiveColor" | "controlInactiveColor" | "controlBackgroundColor">;
|
|
12
|
+
type ColorStyleControls = ReturnType<typeof ColorStyleControls>;
|
|
13
|
+
export default ColorStyleControls;
|