@once-ui-system/core 2.0.0-alpha.0 → 2.0.0-alpha.2
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/AGENTS.md +1 -1
- package/LICENSE.md +21 -0
- package/ai/catalog.json +11 -4
- package/ai/components/Effect.json +1 -1
- package/ai/components/Feedback.json +1 -0
- package/ai/components/Form.json +15 -0
- package/ai/components/Input.json +3 -2
- package/ai/components/{Particle.json → ParticleFx.json} +1 -1
- package/ai/components/ScrollContainer.json +9 -1
- package/ai/components/Textarea.json +3 -2
- package/ai/components/ThemeSwitcher.json +2 -1
- package/ai/eval-tasks.md +2 -1
- package/ai/examples/auth.tsx +1 -2
- package/ai/examples/blocks/Dashboard1.tsx +8 -8
- package/ai/examples/blocks/Feed3.tsx +4 -4
- package/ai/examples/blocks/Footer4.tsx +2 -2
- package/ai/examples/blocks/Header2.tsx +1 -1
- package/ai/examples/blocks/Header4.tsx +1 -2
- package/ai/examples/blocks/Productivity1.tsx +1 -1
- package/ai/examples/blocks/Roadmap1.tsx +3 -3
- package/ai/examples/blocks/Sidebar1.tsx +1 -1
- package/ai/examples/blocks/Sidebar2.tsx +1 -1
- package/ai/examples/blocks/Table1.tsx +3 -3
- package/ai/examples/blocks/manifest.json +2 -2
- package/ai/examples/dashboard.tsx +5 -5
- package/ai/examples/marketing-hero.tsx +2 -2
- package/ai/examples/pricing.tsx +3 -3
- package/ai/examples/settings.tsx +4 -4
- package/ai/gotchas.json +26 -2
- package/ai/manifest.json +2 -2
- package/ai/recipes.md +1 -1
- package/ai/rules.compact.md +8 -2
- package/ai/rules.md +18 -6
- package/ai/spec.json +35 -10
- package/ai/tasks/settings.json +1 -1
- package/dist/AGENTS.md +1 -1
- package/dist/ai/catalog.json +11 -4
- package/dist/ai/components/Effect.json +1 -1
- package/dist/ai/components/Feedback.json +1 -0
- package/dist/ai/components/Form.json +15 -0
- package/dist/ai/components/Input.json +3 -2
- package/dist/ai/components/{Particle.json → ParticleFx.json} +1 -1
- package/dist/ai/components/ScrollContainer.json +9 -1
- package/dist/ai/components/Textarea.json +3 -2
- package/dist/ai/components/ThemeSwitcher.json +2 -1
- package/dist/ai/eval-tasks.md +2 -1
- package/dist/ai/examples/blocks/manifest.json +2 -2
- package/dist/ai/gotchas.json +26 -2
- package/dist/ai/manifest.json +2 -2
- package/dist/ai/recipes.md +1 -1
- package/dist/ai/rules.compact.md +8 -2
- package/dist/ai/rules.md +18 -6
- package/dist/ai/spec.json +35 -10
- package/dist/ai/tasks/settings.json +1 -1
- package/dist/components/Animation.d.ts +1 -2
- package/dist/components/Animation.d.ts.map +1 -1
- package/dist/components/Animation.js +1 -1
- package/dist/components/Animation.js.map +1 -1
- package/dist/components/ArrowNavigationContext.d.ts.map +1 -1
- package/dist/components/ArrowNavigationContext.js +12 -3
- package/dist/components/ArrowNavigationContext.js.map +1 -1
- package/dist/components/Avatar.d.ts.map +1 -1
- package/dist/components/Avatar.js +1 -1
- package/dist/components/Avatar.js.map +1 -1
- package/dist/components/Carousel.js +1 -1
- package/dist/components/Carousel.js.map +1 -1
- package/dist/components/ContextMenu.d.ts +1 -1
- package/dist/components/ContextMenu.d.ts.map +1 -1
- package/dist/components/CountFx.d.ts.map +1 -1
- package/dist/components/CountFx.js +19 -7
- package/dist/components/CountFx.js.map +1 -1
- package/dist/components/CursorCard.d.ts +1 -1
- package/dist/components/CursorCard.d.ts.map +1 -1
- package/dist/components/DatePicker.d.ts.map +1 -1
- package/dist/components/DatePicker.js +9 -2
- package/dist/components/DatePicker.js.map +1 -1
- package/dist/components/DropdownWrapper.d.ts +1 -1
- package/dist/components/DropdownWrapper.d.ts.map +1 -1
- package/dist/components/DropdownWrapper.js +178 -35
- package/dist/components/DropdownWrapper.js.map +1 -1
- package/dist/components/DropdownWrapper.module.scss +3 -1
- package/dist/components/Effect.d.ts +2 -2
- package/dist/components/Effect.d.ts.map +1 -1
- package/dist/components/Effect.js +2 -2
- package/dist/components/Effect.js.map +1 -1
- package/dist/components/EmojiPicker.js +1 -1
- package/dist/components/EmojiPicker.js.map +1 -1
- package/dist/components/Feedback.d.ts +4 -0
- package/dist/components/Feedback.d.ts.map +1 -1
- package/dist/components/Feedback.js +2 -2
- package/dist/components/Feedback.js.map +1 -1
- package/dist/components/FocusTrap.d.ts +3 -3
- package/dist/components/FocusTrap.d.ts.map +1 -1
- package/dist/components/FocusTrap.js +10 -0
- package/dist/components/FocusTrap.js.map +1 -1
- package/dist/components/Form.d.ts +48 -0
- package/dist/components/Form.d.ts.map +1 -0
- package/dist/components/Form.js +191 -0
- package/dist/components/Form.js.map +1 -0
- package/dist/components/Form.module.scss +160 -0
- package/dist/components/FormContext.d.ts +20 -0
- package/dist/components/FormContext.d.ts.map +1 -0
- package/dist/components/FormContext.js +12 -0
- package/dist/components/FormContext.js.map +1 -0
- package/dist/components/Input.d.ts +3 -0
- package/dist/components/Input.d.ts.map +1 -1
- package/dist/components/Input.js +13 -2
- package/dist/components/Input.js.map +1 -1
- package/dist/components/Input.module.scss +27 -6
- package/dist/components/OgCard.d.ts.map +1 -1
- package/dist/components/OgCard.js +7 -4
- package/dist/components/OgCard.js.map +1 -1
- package/dist/components/{Particle.d.ts → ParticleFx.d.ts} +9 -4
- package/dist/components/ParticleFx.d.ts.map +1 -0
- package/dist/components/{Particle.js → ParticleFx.js} +9 -4
- package/dist/components/ParticleFx.js.map +1 -0
- package/dist/components/ScrollContainer.d.ts +69 -2
- package/dist/components/ScrollContainer.d.ts.map +1 -1
- package/dist/components/ScrollContainer.js +377 -46
- package/dist/components/ScrollContainer.js.map +1 -1
- package/dist/components/ScrollContainer.module.scss +131 -0
- package/dist/components/Select.d.ts +1 -1
- package/dist/components/Select.d.ts.map +1 -1
- package/dist/components/Select.js +1 -1
- package/dist/components/Select.js.map +1 -1
- package/dist/components/Setting.d.ts.map +1 -1
- package/dist/components/Setting.js +6 -1
- package/dist/components/Setting.js.map +1 -1
- package/dist/components/Table.js +2 -2
- package/dist/components/Table.js.map +1 -1
- package/dist/components/Textarea.d.ts +3 -0
- package/dist/components/Textarea.d.ts.map +1 -1
- package/dist/components/Textarea.js +22 -6
- package/dist/components/Textarea.js.map +1 -1
- package/dist/components/ThemeSwitcher.d.ts +16 -0
- package/dist/components/ThemeSwitcher.d.ts.map +1 -1
- package/dist/components/ThemeSwitcher.js +48 -9
- package/dist/components/ThemeSwitcher.js.map +1 -1
- package/dist/components/ThemeSwitcher.module.scss +112 -0
- package/dist/components/User.js +1 -1
- package/dist/components/User.js.map +1 -1
- package/dist/components/UserMenu.d.ts +1 -1
- package/dist/components/UserMenu.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -1
- package/dist/components/index.js.map +1 -1
- package/dist/data/emoji-data.json +10 -0
- package/dist/hooks/useArrowNavigation.d.ts.map +1 -1
- package/dist/hooks/useArrowNavigation.js +52 -7
- package/dist/hooks/useArrowNavigation.js.map +1 -1
- package/dist/modules/navigation/MegaMenu.d.ts.map +1 -1
- package/dist/modules/navigation/MegaMenu.js +76 -10
- package/dist/modules/navigation/MegaMenu.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/scripts/validate-ai-code.js +239 -21
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/scripts/validate-ai-code.js +239 -21
- package/dist/components/Particle.d.ts.map +0 -1
- package/dist/components/Particle.js.map +0 -1
|
@@ -1,66 +1,397 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
import { Column,
|
|
3
|
+
import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { Column, Flex, IconButton, Row } from ".";
|
|
5
|
+
import styles from "./ScrollContainer.module.scss";
|
|
5
6
|
const getHorizontalAlignment = (placement) => {
|
|
6
|
-
if (placement
|
|
7
|
-
return "start";
|
|
8
|
-
if (placement === "top-end" || placement === "bottom-end")
|
|
7
|
+
if (placement.endsWith("-end"))
|
|
9
8
|
return "end";
|
|
10
|
-
if (placement
|
|
9
|
+
if (placement.endsWith("-center"))
|
|
11
10
|
return "center";
|
|
12
|
-
if (placement
|
|
11
|
+
if (placement.endsWith("-between"))
|
|
13
12
|
return "between";
|
|
14
13
|
return "start";
|
|
15
14
|
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
/** Past this many pixels a pointer is dragging the track, not clicking a tile. */
|
|
16
|
+
const DRAG_THRESHOLD = 6;
|
|
17
|
+
/** Past this fraction of a tile, let go and the track advances rather than settling back. */
|
|
18
|
+
const COMMIT_RATIO = 0.2;
|
|
19
|
+
/** Past this speed the same is true however short the drag was. */
|
|
20
|
+
const FLICK_VELOCITY = 0.5;
|
|
21
|
+
/** How far a track can be pulled past its own end before it stops following. */
|
|
22
|
+
const RUBBER_BAND = 0.35;
|
|
23
|
+
/** How much smaller each whole step from the front is, when `proximity` is on. */
|
|
24
|
+
const PROXIMITY_FALLOFF = 0.08;
|
|
25
|
+
/** Tiles stop shrinking here, so a long run does not trail off into nothing. */
|
|
26
|
+
const PROXIMITY_FLOOR = 0.72;
|
|
27
|
+
/**
|
|
28
|
+
* A horizontal run of items with controls, drag, optional wrap-around,
|
|
29
|
+
* optional proximity scaling and optional markers.
|
|
30
|
+
*
|
|
31
|
+
* This moves a track with a transform rather than scrolling a box, which is
|
|
32
|
+
* the decision the rest of the component follows from. The previous version
|
|
33
|
+
* was an `overflow-x: auto` row, and a scroll box cannot do any of the three
|
|
34
|
+
* things asked of a carousel: its contents are clipped at its own edge by
|
|
35
|
+
* definition, so no tile can peek past it; its scroll range has two hard ends,
|
|
36
|
+
* so there is nowhere for a wrap-around to go; and the browser owns the
|
|
37
|
+
* easing, so a drag can only set `scrollLeft` and hope. A transform has none
|
|
38
|
+
* of those limits — the track is laid out once and moved, tiles paint wherever
|
|
39
|
+
* they land, the offset is free to run past either end, and the motion is a
|
|
40
|
+
* CSS transition this component controls.
|
|
41
|
+
*
|
|
42
|
+
* What it gives up is the browser's own scrolling: a trackpad's horizontal
|
|
43
|
+
* gesture no longer moves the track, and that is why `draggable` is on by
|
|
44
|
+
* default and the controls are never hidden. Both are real affordances rather
|
|
45
|
+
* than the invisible one a scroll box relies on.
|
|
46
|
+
*
|
|
47
|
+
* Tiles are unstyled. The wrapper each item sits in used to arrive with
|
|
48
|
+
* `aspectRatio="3/4"`, `border`, `radius="xl"` and a width range already set,
|
|
49
|
+
* so anything that was not a tall bordered portrait card had to override four
|
|
50
|
+
* properties before it could begin — and any prop passed to override them
|
|
51
|
+
* landed on every tile, since that is where the rest props go. The wrapper now
|
|
52
|
+
* contributes only what a track item cannot do without, which is refusing to
|
|
53
|
+
* shrink. Sizing stays with the caller, through those same rest props.
|
|
54
|
+
*/
|
|
55
|
+
const ScrollContainer = forwardRef(({ items, controlPlacement = "top-start", infinite = false, markers = false, draggable = true, step = 1, clip = false, proximity = false, active, onActiveChange, ...tile }, ref) => {
|
|
56
|
+
const count = items.length;
|
|
57
|
+
const viewportRef = useRef(null);
|
|
58
|
+
const trackRef = useRef(null);
|
|
59
|
+
const [index, setIndex] = useState(0);
|
|
60
|
+
const [tileStep, setTileStep] = useState(0);
|
|
61
|
+
const [perView, setPerView] = useState(1);
|
|
62
|
+
const [dragPx, setDragPx] = useState(0);
|
|
63
|
+
const [animated, setAnimated] = useState(true);
|
|
64
|
+
const [dragging, setDragging] = useState(false);
|
|
65
|
+
/**
|
|
66
|
+
* The last index that still fills the viewport.
|
|
67
|
+
*
|
|
68
|
+
* Without wrap-around there is no reason to advance into empty space once
|
|
69
|
+
* the final tile is already in view, so the end of the run is the last
|
|
70
|
+
* whole screenful rather than the last item.
|
|
71
|
+
*/
|
|
72
|
+
const maxIndex = infinite ? Number.POSITIVE_INFINITY : Math.max(0, count - perView);
|
|
73
|
+
/**
|
|
74
|
+
* Wrap-around is three copies of the run with the real one in the middle.
|
|
75
|
+
*
|
|
76
|
+
* Moving off either side of the middle copy lands on a real tile of the
|
|
77
|
+
* neighbouring copy, so the motion is continuous and in the direction of
|
|
78
|
+
* travel. `onTransitionEnd` then puts the index back in range with the
|
|
79
|
+
* transition switched off, which shifts the track by exactly one copy —
|
|
80
|
+
* the same tiles under the same pixels, so nothing moves on screen.
|
|
81
|
+
*/
|
|
82
|
+
const rendered = useMemo(() => (infinite && count > 0 ? [...items, ...items, ...items] : items), [infinite, items, count]);
|
|
83
|
+
const origin = infinite ? count : 0;
|
|
84
|
+
const measure = useCallback(() => {
|
|
85
|
+
const viewport = viewportRef.current;
|
|
86
|
+
const track = trackRef.current;
|
|
87
|
+
const first = track?.firstElementChild;
|
|
88
|
+
if (!viewport || !track || !first)
|
|
23
89
|
return;
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
90
|
+
const gap = Number.parseFloat(getComputedStyle(track).columnGap) || 0;
|
|
91
|
+
const width = first.offsetWidth + gap;
|
|
92
|
+
setTileStep(width);
|
|
93
|
+
setPerView(width > 0 ? Math.max(1, Math.round(viewport.clientWidth / width)) : 1);
|
|
27
94
|
}, []);
|
|
28
95
|
useEffect(() => {
|
|
29
|
-
|
|
30
|
-
|
|
96
|
+
measure();
|
|
97
|
+
const viewport = viewportRef.current;
|
|
98
|
+
if (!viewport || typeof ResizeObserver === "undefined") {
|
|
99
|
+
window.addEventListener("resize", measure);
|
|
100
|
+
return () => window.removeEventListener("resize", measure);
|
|
101
|
+
}
|
|
102
|
+
// Watches the track's own box too: a tile sized in percentages changes
|
|
103
|
+
// with the viewport, but one sized by its content changes when the
|
|
104
|
+
// content does, and only the track hears about that.
|
|
105
|
+
const observer = new ResizeObserver(measure);
|
|
106
|
+
observer.observe(viewport);
|
|
107
|
+
if (trackRef.current)
|
|
108
|
+
observer.observe(trackRef.current);
|
|
109
|
+
return () => observer.disconnect();
|
|
110
|
+
}, [measure]);
|
|
111
|
+
// A shorter list can leave the index past the end of it.
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
setIndex((current) => Math.min(current, infinite ? current : Math.max(0, count - 1)));
|
|
114
|
+
}, [count, infinite]);
|
|
115
|
+
const go = useCallback((delta) => {
|
|
116
|
+
setAnimated(true);
|
|
117
|
+
setIndex((current) => {
|
|
118
|
+
const next = current + delta;
|
|
119
|
+
return infinite ? next : Math.max(0, Math.min(maxIndex, next));
|
|
120
|
+
});
|
|
121
|
+
}, [infinite, maxIndex]);
|
|
122
|
+
const goTo = useCallback((target) => {
|
|
123
|
+
setAnimated(true);
|
|
124
|
+
setIndex((current) => {
|
|
125
|
+
if (!infinite)
|
|
126
|
+
return Math.max(0, Math.min(maxIndex, target));
|
|
127
|
+
// Take whichever way round is shorter, so a marker near the end of
|
|
128
|
+
// the run does not walk the whole track to reach a neighbour.
|
|
129
|
+
const here = ((current % count) + count) % count;
|
|
130
|
+
const forward = (((target - here) % count) + count) % count;
|
|
131
|
+
return current + (forward <= count - forward ? forward : forward - count);
|
|
132
|
+
});
|
|
133
|
+
}, [count, infinite, maxIndex]);
|
|
134
|
+
/**
|
|
135
|
+
* Which item is in front, counted in `items` rather than in the track.
|
|
136
|
+
*
|
|
137
|
+
* With wrap-around the internal index is free to run past either end —
|
|
138
|
+
* that is what makes the motion continuous — so it is not a number any
|
|
139
|
+
* caller could use. This folds it back into the range of the real run,
|
|
140
|
+
* and it is the only index this component reports or accepts.
|
|
141
|
+
*/
|
|
142
|
+
const activeIndex = count > 0 ? ((index % count) + count) % count : 0;
|
|
143
|
+
/**
|
|
144
|
+
* Report the front item, but never on mount.
|
|
145
|
+
*
|
|
146
|
+
* The callback is read through a ref so that a caller passing a fresh
|
|
147
|
+
* arrow function on every render — which is most of them — does not make
|
|
148
|
+
* this fire again for an index that has not moved.
|
|
149
|
+
*/
|
|
150
|
+
const onActiveChangeRef = useRef(onActiveChange);
|
|
151
|
+
onActiveChangeRef.current = onActiveChange;
|
|
152
|
+
const reportedRef = useRef(activeIndex);
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
if (reportedRef.current === activeIndex)
|
|
155
|
+
return;
|
|
156
|
+
reportedRef.current = activeIndex;
|
|
157
|
+
onActiveChangeRef.current?.(activeIndex);
|
|
158
|
+
}, [activeIndex]);
|
|
159
|
+
/**
|
|
160
|
+
* Move when `active` changes.
|
|
161
|
+
*
|
|
162
|
+
* Deliberately keyed on `active` alone. Were it to depend on where the run
|
|
163
|
+
* actually is, every drag would be undone a frame after it finished by an
|
|
164
|
+
* effect insisting on the last value the caller passed — the run would
|
|
165
|
+
* fight the pointer. `active` says go here; it does not say stay here.
|
|
166
|
+
*/
|
|
167
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: see above — reacting to the caller's command, not to our own position
|
|
168
|
+
useEffect(() => {
|
|
169
|
+
if (active === undefined || count === 0)
|
|
170
|
+
return;
|
|
171
|
+
goTo(active);
|
|
172
|
+
}, [active, count]);
|
|
173
|
+
/**
|
|
174
|
+
* Put the index back inside the real copy once the motion has finished.
|
|
175
|
+
*
|
|
176
|
+
* Switching the transition off for one frame is what makes the jump
|
|
177
|
+
* invisible: the index changes by a whole copy and the transform changes
|
|
178
|
+
* by exactly one copy's width, so the pixels are identical.
|
|
179
|
+
*/
|
|
180
|
+
const handleTransitionEnd = useCallback((event) => {
|
|
181
|
+
// `transitionend` bubbles, so a tile animating its own background would
|
|
182
|
+
// otherwise be read as the track arriving.
|
|
183
|
+
if (event.target !== trackRef.current || event.propertyName !== "transform")
|
|
184
|
+
return;
|
|
185
|
+
if (!infinite || count === 0)
|
|
186
|
+
return;
|
|
187
|
+
if (index >= 0 && index < count)
|
|
31
188
|
return;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
189
|
+
setAnimated(false);
|
|
190
|
+
setIndex(((index % count) + count) % count);
|
|
191
|
+
}, [count, index, infinite]);
|
|
192
|
+
/**
|
|
193
|
+
* Put the transition back one frame after the wrap-around jump — but not
|
|
194
|
+
* while a drag is in progress.
|
|
195
|
+
*
|
|
196
|
+
* Without the `dragging` guard this fires for any `animated === false`,
|
|
197
|
+
* and a drag is the other thing that sets it false. One frame in, the
|
|
198
|
+
* transition came back on, and every `dragPx` update after that was eased
|
|
199
|
+
* over `--transition-duration-macro-long` instead of applied: the track
|
|
200
|
+
* crawled toward the pointer at 0.6s a step and never caught up. Measured
|
|
201
|
+
* before the guard — a 164px drag moved the track 46px, in increments of
|
|
202
|
+
* 40, 1, 2, 3. It only looked right on release because the commit works
|
|
203
|
+
* from the raw pointer delta, not from where the track had got to.
|
|
204
|
+
*/
|
|
205
|
+
useEffect(() => {
|
|
206
|
+
if (animated || dragging)
|
|
207
|
+
return;
|
|
208
|
+
const frame = requestAnimationFrame(() => setAnimated(true));
|
|
209
|
+
return () => cancelAnimationFrame(frame);
|
|
210
|
+
}, [animated, dragging]);
|
|
211
|
+
const drag = useRef({
|
|
212
|
+
active: false,
|
|
213
|
+
axis: null,
|
|
214
|
+
startX: 0,
|
|
215
|
+
startY: 0,
|
|
216
|
+
lastX: 0,
|
|
217
|
+
lastT: 0,
|
|
218
|
+
velocity: 0,
|
|
219
|
+
moved: false,
|
|
220
|
+
});
|
|
221
|
+
const onPointerDown = (event) => {
|
|
222
|
+
if (!draggable || tileStep === 0 || event.button !== 0)
|
|
223
|
+
return;
|
|
224
|
+
drag.current = {
|
|
225
|
+
active: true,
|
|
226
|
+
axis: null,
|
|
227
|
+
startX: event.clientX,
|
|
228
|
+
startY: event.clientY,
|
|
229
|
+
lastX: event.clientX,
|
|
230
|
+
lastT: event.timeStamp,
|
|
231
|
+
velocity: 0,
|
|
232
|
+
moved: false,
|
|
38
233
|
};
|
|
39
|
-
}
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
if (!
|
|
234
|
+
};
|
|
235
|
+
const onPointerMove = (event) => {
|
|
236
|
+
const state = drag.current;
|
|
237
|
+
if (!state.active)
|
|
43
238
|
return;
|
|
44
|
-
const
|
|
45
|
-
|
|
239
|
+
const dx = event.clientX - state.startX;
|
|
240
|
+
const dy = event.clientY - state.startY;
|
|
241
|
+
/**
|
|
242
|
+
* Which axis this gesture belongs to is decided once, on the first
|
|
243
|
+
* movement past the threshold, and never revisited.
|
|
244
|
+
*
|
|
245
|
+
* A carousel that takes every gesture takes vertical ones too, and on a
|
|
246
|
+
* phone that means the page stops scrolling wherever a carousel happens
|
|
247
|
+
* to be. Deciding once rather than per-event also stops a diagonal drag
|
|
248
|
+
* from flickering between the two.
|
|
249
|
+
*/
|
|
250
|
+
if (state.axis === null) {
|
|
251
|
+
if (Math.abs(dx) < DRAG_THRESHOLD && Math.abs(dy) < DRAG_THRESHOLD)
|
|
252
|
+
return;
|
|
253
|
+
state.axis = Math.abs(dx) > Math.abs(dy) ? "x" : "y";
|
|
254
|
+
if (state.axis === "y") {
|
|
255
|
+
state.active = false;
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
259
|
+
setAnimated(false);
|
|
260
|
+
setDragging(true);
|
|
261
|
+
}
|
|
262
|
+
const elapsed = event.timeStamp - state.lastT;
|
|
263
|
+
if (elapsed > 0)
|
|
264
|
+
state.velocity = (event.clientX - state.lastX) / elapsed;
|
|
265
|
+
state.lastX = event.clientX;
|
|
266
|
+
state.lastT = event.timeStamp;
|
|
267
|
+
state.moved = true;
|
|
268
|
+
// Past either end there is nothing to show, so the track follows at a
|
|
269
|
+
// fraction of the pointer and springs back on release.
|
|
270
|
+
let offset = dx;
|
|
271
|
+
if (!infinite) {
|
|
272
|
+
const over = index - dx / tileStep;
|
|
273
|
+
if (over < 0)
|
|
274
|
+
offset = dx * RUBBER_BAND;
|
|
275
|
+
else if (over > maxIndex)
|
|
276
|
+
offset = dx * RUBBER_BAND;
|
|
277
|
+
}
|
|
278
|
+
setDragPx(offset);
|
|
279
|
+
};
|
|
280
|
+
const endDrag = (event) => {
|
|
281
|
+
const state = drag.current;
|
|
282
|
+
if (!state.active || state.axis !== "x") {
|
|
283
|
+
drag.current.active = false;
|
|
284
|
+
setDragging(false);
|
|
46
285
|
return;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
286
|
+
}
|
|
287
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
288
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
289
|
+
}
|
|
290
|
+
const dx = event.clientX - state.startX;
|
|
291
|
+
const travelled = -dx / tileStep;
|
|
292
|
+
const flicked = Math.abs(state.velocity) > FLICK_VELOCITY;
|
|
293
|
+
const committed = Math.abs(travelled) > COMMIT_RATIO || flicked;
|
|
294
|
+
// A flick is a direction, not a distance: it moves one tile whichever
|
|
295
|
+
// way it was thrown, even if the pointer barely left where it started.
|
|
296
|
+
const delta = committed
|
|
297
|
+
? Math.abs(travelled) < 1
|
|
298
|
+
? Math.sign(travelled) || -Math.sign(state.velocity)
|
|
299
|
+
: Math.round(travelled)
|
|
300
|
+
: 0;
|
|
301
|
+
state.active = false;
|
|
302
|
+
setDragging(false);
|
|
303
|
+
setDragPx(0);
|
|
304
|
+
go(delta);
|
|
305
|
+
};
|
|
306
|
+
/**
|
|
307
|
+
* A drag that ends on a tile must not also open it.
|
|
308
|
+
*
|
|
309
|
+
* The pointer goes down and up on the same anchor, so the browser fires a
|
|
310
|
+
* click regardless of how far it travelled in between. This swallows that
|
|
311
|
+
* one click during the capture phase, before it reaches the tile.
|
|
312
|
+
*/
|
|
313
|
+
const onClickCapture = (event) => {
|
|
314
|
+
if (!drag.current.moved)
|
|
315
|
+
return;
|
|
316
|
+
drag.current.moved = false;
|
|
317
|
+
event.preventDefault();
|
|
318
|
+
event.stopPropagation();
|
|
319
|
+
};
|
|
320
|
+
const onKeyDown = (event) => {
|
|
321
|
+
if (event.key === "ArrowLeft") {
|
|
322
|
+
event.preventDefault();
|
|
323
|
+
go(-step);
|
|
324
|
+
}
|
|
325
|
+
else if (event.key === "ArrowRight") {
|
|
326
|
+
event.preventDefault();
|
|
327
|
+
go(step);
|
|
328
|
+
}
|
|
54
329
|
};
|
|
330
|
+
const canGoBack = infinite || index > 0;
|
|
331
|
+
const canGoForward = infinite || index < maxIndex;
|
|
55
332
|
const isTopPlacement = controlPlacement.startsWith("top");
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
333
|
+
const markerSide = markers === true ? (isTopPlacement ? "bottom" : "top") : markers;
|
|
334
|
+
const controls = (_jsxs(Row, { fillWidth: true, gap: "8", horizontal: getHorizontalAlignment(controlPlacement), children: [_jsx(IconButton, { icon: "chevronLeft", "aria-label": "Previous", onClick: () => go(-step), disabled: !canGoBack, style: { border: "none" } }), _jsx(IconButton, { icon: "chevronRight", "aria-label": "Next", onClick: () => go(step), disabled: !canGoForward, style: { border: "none" } })] }));
|
|
335
|
+
const markerRow = markerSide ? (_jsx(Row, { fillWidth: true, gap: "8", horizontal: "center", vertical: "center", paddingY: "4", children: items.map((_, i) => (_jsx("button", { type: "button", className: styles.marker, "data-active": i === activeIndex ? "true" : undefined, "aria-label": `Go to item ${i + 1} of ${count}`, "aria-current": i === activeIndex ? "true" : undefined, onClick: () => goTo(i) }, i))) })) : null;
|
|
336
|
+
/**
|
|
337
|
+
* Where the track really is, between two indices, while it is being moved.
|
|
338
|
+
*
|
|
339
|
+
* The settled `index` is a whole number and would step the scaling from
|
|
340
|
+
* one tile to the next, which is the opposite of what this is for: the
|
|
341
|
+
* point is that a tile grows as you drag it towards the front rather than
|
|
342
|
+
* snapping when it arrives. `dragPx` is the live offset, so dividing it by
|
|
343
|
+
* the tile pitch gives the fraction of a step the track has travelled, and
|
|
344
|
+
* the sign is negative because dragging right shows earlier items.
|
|
345
|
+
*/
|
|
346
|
+
const falloff = proximity === true ? PROXIMITY_FALLOFF : typeof proximity === "number" ? proximity : 0;
|
|
347
|
+
const scaling = falloff > 0 && tileStep > 0;
|
|
348
|
+
const front = index - (tileStep > 0 ? dragPx / tileStep : 0);
|
|
349
|
+
const offset = -(index + origin) * tileStep + dragPx;
|
|
350
|
+
return (_jsxs(Column, { ref: ref, fillWidth: true, gap: "8", "aria-roledescription": "carousel", children: [markerSide === "top" && markerRow, isTopPlacement && controls, _jsx(Flex, { ref: viewportRef, fillWidth: true, className: clip ? styles.viewportClipped : styles.viewport, "data-dragging": dragging ? "true" : undefined, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: endDrag, onPointerCancel: endDrag, onClickCapture: onClickCapture, onKeyDown: onKeyDown,
|
|
351
|
+
// The track is the thing you move, so it is the thing that takes
|
|
352
|
+
// focus and answers the arrow keys.
|
|
353
|
+
tabIndex: 0, role: "group", "aria-label": "Items", children: _jsx(Row, { ref: trackRef, gap: "8", className: styles.track, onTransitionEnd: handleTransitionEnd, style: {
|
|
354
|
+
transform: `translate3d(${offset}px, 0, 0)`,
|
|
355
|
+
// Spread rather than `transition: animated ? undefined : "none"`.
|
|
356
|
+
// The style object is passed through before it reaches the DOM
|
|
357
|
+
// and an `undefined` value survives that trip as the string
|
|
358
|
+
// "undefined", which is not a valid transition and overrides the
|
|
359
|
+
// one on the class — so the track moved instantly, no
|
|
360
|
+
// `transitionend` ever fired, and the wrap-around never
|
|
361
|
+
// normalised. An absent key cannot be stringified.
|
|
362
|
+
...(animated ? {} : { transition: "none" }),
|
|
363
|
+
}, children: rendered.map((item, i) => {
|
|
364
|
+
const scale = scaling
|
|
365
|
+
? Math.max(PROXIMITY_FLOOR, 1 - falloff * Math.abs(i - origin - front))
|
|
366
|
+
: 1;
|
|
367
|
+
return (_jsx(Column
|
|
368
|
+
// Same as above, and with wrap-around the same item appears in
|
|
369
|
+
// three copies, so its own identity would not be unique either.
|
|
370
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: no stable id exists
|
|
371
|
+
, { className: styles.tile,
|
|
372
|
+
// The one sizing default that stays. A tile with no width of
|
|
373
|
+
// its own sizes to its content, which is fine for a card of
|
|
374
|
+
// text and collapses to nothing for anything that fills its
|
|
375
|
+
// parent — so the out-of-the-box carousel would depend on what
|
|
376
|
+
// was put in it. `minWidth` is a floor, not a shape: content
|
|
377
|
+
// wider than this still sets the tile's width.
|
|
378
|
+
minWidth: 20, "aria-hidden": infinite && (i < origin || i >= origin + count) ? "true" : undefined, ...tile, style: {
|
|
379
|
+
...tile.style,
|
|
380
|
+
// Only when asked. Off, a tile carries no transform at all,
|
|
381
|
+
// so it never becomes a containing block for whatever the
|
|
382
|
+
// caller positioned inside it.
|
|
383
|
+
...(scaling
|
|
384
|
+
? {
|
|
385
|
+
transform: `scale(${scale})`,
|
|
386
|
+
// Follows the pointer during a drag and eases with the
|
|
387
|
+
// track afterwards, the same rule the track itself
|
|
388
|
+
// uses — and for the same reason, spread rather than
|
|
389
|
+
// set to `undefined`.
|
|
390
|
+
...(animated ? {} : { transition: "none" }),
|
|
391
|
+
}
|
|
392
|
+
: {}),
|
|
393
|
+
}, children: item }, i));
|
|
394
|
+
}) }) }), !isTopPlacement && controls, markerSide === "bottom" && markerRow] }));
|
|
64
395
|
});
|
|
65
396
|
ScrollContainer.displayName = "ScrollContainer";
|
|
66
397
|
export { ScrollContainer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScrollContainer.js","sourceRoot":"","sources":["../../src/components/ScrollContainer.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ScrollContainer.js","sourceRoot":"","sources":["../../src/components/ScrollContainer.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACtF,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC;AAClD,OAAO,MAAM,MAAM,+BAA+B,CAAC;AAuDnD,MAAM,sBAAsB,GAAG,CAAC,SAA0C,EAAE,EAAE;IAC5E,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,IAAI,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IACnD,IAAI,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,SAAS,CAAC;IACrD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,kFAAkF;AAClF,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB,6FAA6F;AAC7F,MAAM,YAAY,GAAG,GAAG,CAAC;AACzB,mEAAmE;AACnE,MAAM,cAAc,GAAG,GAAG,CAAC;AAC3B,gFAAgF;AAChF,MAAM,WAAW,GAAG,IAAI,CAAC;AACzB,kFAAkF;AAClF,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAC/B,gFAAgF;AAChF,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,eAAe,GAAG,UAAU,CAChC,CACE,EACE,KAAK,EACL,gBAAgB,GAAG,WAAW,EAC9B,QAAQ,GAAG,KAAK,EAChB,OAAO,GAAG,KAAK,EACf,SAAS,GAAG,IAAI,EAChB,IAAI,GAAG,CAAC,EACR,IAAI,GAAG,KAAK,EACZ,SAAS,GAAG,KAAK,EACjB,MAAM,EACN,cAAc,EACd,GAAG,IAAI,EACR,EACD,GAAG,EACH,EAAE;IACF,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3B,MAAM,WAAW,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAE9C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC1C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEhD;;;;;;OAMG;IACH,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,CAAC;IAEpF;;;;;;;;OAQG;IACH,MAAM,QAAQ,GAAG,OAAO,CACtB,GAAG,EAAE,CAAC,CAAC,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EACtE,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CACzB,CAAC;IACF,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpC,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;QAC/B,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC;QACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC;QAC/B,MAAM,KAAK,GAAG,KAAK,EAAE,iBAAuC,CAAC;QAC7D,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK;YAAE,OAAO;QAE1C,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACtE,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC;QACtC,WAAW,CAAC,KAAK,CAAC,CAAC;QACnB,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,EAAE,CAAC;QACV,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC;QACrC,IAAI,CAAC,QAAQ,IAAI,OAAO,cAAc,KAAK,WAAW,EAAE,CAAC;YACvD,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC3C,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC7D,CAAC;QACD,uEAAuE;QACvE,mEAAmE;QACnE,qDAAqD;QACrD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;QAC7C,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3B,IAAI,QAAQ,CAAC,OAAO;YAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACzD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,yDAAyD;IACzD,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEtB,MAAM,EAAE,GAAG,WAAW,CACpB,CAAC,KAAa,EAAE,EAAE;QAChB,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE;YACnB,MAAM,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC;YAC7B,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;IACL,CAAC,EACD,CAAC,QAAQ,EAAE,QAAQ,CAAC,CACrB,CAAC;IAEF,MAAM,IAAI,GAAG,WAAW,CACtB,CAAC,MAAc,EAAE,EAAE;QACjB,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE;YACnB,IAAI,CAAC,QAAQ;gBAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;YAC9D,mEAAmE;YACnE,8DAA8D;YAC9D,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;YACjD,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;YAC5D,OAAO,OAAO,GAAG,CAAC,OAAO,IAAI,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;IACL,CAAC,EACD,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAC5B,CAAC;IAEF;;;;;;;OAOG;IACH,MAAM,WAAW,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtE;;;;;;OAMG;IACH,MAAM,iBAAiB,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;IACjD,iBAAiB,CAAC,OAAO,GAAG,cAAc,CAAC;IAC3C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACxC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,WAAW,CAAC,OAAO,KAAK,WAAW;YAAE,OAAO;QAChD,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC;QAClC,iBAAiB,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB;;;;;;;OAOG;IACH,iIAAiI;IACjI,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,KAAK,SAAS,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO;QAChD,IAAI,CAAC,MAAM,CAAC,CAAC;IACf,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAEpB;;;;;;OAMG;IACH,MAAM,mBAAmB,GAAG,WAAW,CACrC,CAAC,KAA4C,EAAE,EAAE;QAC/C,wEAAwE;QACxE,2CAA2C;QAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC,YAAY,KAAK,WAAW;YAAE,OAAO;QACpF,IAAI,CAAC,QAAQ,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO;QACrC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,KAAK;YAAE,OAAO;QACxC,WAAW,CAAC,KAAK,CAAC,CAAC;QACnB,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;IAC9C,CAAC,EACD,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,CACzB,CAAC;IAEF;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,QAAQ,IAAI,QAAQ;YAAE,OAAO;QACjC,MAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7D,OAAO,GAAG,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEzB,MAAM,IAAI,GAAG,MAAM,CAAC;QAClB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,IAAwB;QAC9B,MAAM,EAAE,CAAC;QACT,MAAM,EAAE,CAAC;QACT,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,CAAC;QACR,QAAQ,EAAE,CAAC;QACX,KAAK,EAAE,KAAK;KACb,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,CAAC,KAAyC,EAAE,EAAE;QAClE,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/D,IAAI,CAAC,OAAO,GAAG;YACb,MAAM,EAAE,IAAI;YACZ,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,KAAK,CAAC,OAAO;YACrB,MAAM,EAAE,KAAK,CAAC,OAAO;YACrB,KAAK,EAAE,KAAK,CAAC,OAAO;YACpB,KAAK,EAAE,KAAK,CAAC,SAAS;YACtB,QAAQ,EAAE,CAAC;YACX,KAAK,EAAE,KAAK;SACb,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,KAAyC,EAAE,EAAE;QAClE,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,OAAO;QAE1B,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC;QACxC,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC;QAExC;;;;;;;;WAQG;QACH,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc;gBAAE,OAAO;YAC3E,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YACrD,IAAI,KAAK,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;gBACvB,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACvD,WAAW,CAAC,KAAK,CAAC,CAAC;YACnB,WAAW,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;QAC9C,IAAI,OAAO,GAAG,CAAC;YAAE,KAAK,CAAC,QAAQ,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;QAC1E,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC;QAC5B,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC;QAC9B,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QAEnB,sEAAsE;QACtE,uDAAuD;QACvD,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,GAAG,KAAK,GAAG,EAAE,GAAG,QAAQ,CAAC;YACnC,IAAI,IAAI,GAAG,CAAC;gBAAE,MAAM,GAAG,EAAE,GAAG,WAAW,CAAC;iBACnC,IAAI,IAAI,GAAG,QAAQ;gBAAE,MAAM,GAAG,EAAE,GAAG,WAAW,CAAC;QACtD,CAAC;QACD,SAAS,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,KAAyC,EAAE,EAAE;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC;YAC5B,WAAW,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3D,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC;QACxC,MAAM,SAAS,GAAG,CAAC,EAAE,GAAG,QAAQ,CAAC;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC;QAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,YAAY,IAAI,OAAO,CAAC;QAChE,sEAAsE;QACtE,uEAAuE;QACvE,MAAM,KAAK,GAAG,SAAS;YACrB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC;gBACvB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;gBACpD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;YACzB,CAAC,CAAC,CAAC,CAAC;QAEN,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;QACrB,WAAW,CAAC,KAAK,CAAC,CAAC;QACnB,SAAS,CAAC,CAAC,CAAC,CAAC;QACb,EAAE,CAAC,KAAK,CAAC,CAAC;IACZ,CAAC,CAAC;IAEF;;;;;;OAMG;IACH,MAAM,cAAc,GAAG,CAAC,KAAuB,EAAE,EAAE;QACjD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK;YAAE,OAAO;QAChC,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;QAC3B,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,eAAe,EAAE,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,KAA0B,EAAE,EAAE;QAC/C,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;YAC9B,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACZ,CAAC;aAAM,IAAI,KAAK,CAAC,GAAG,KAAK,YAAY,EAAE,CAAC;YACtC,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,EAAE,CAAC,IAAI,CAAC,CAAC;QACX,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC;IACxC,MAAM,YAAY,GAAG,QAAQ,IAAI,KAAK,GAAG,QAAQ,CAAC;IAElD,MAAM,cAAc,GAAG,gBAAgB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAEpF,MAAM,QAAQ,GAAG,CACf,MAAC,GAAG,IAAC,SAAS,QAAC,GAAG,EAAC,GAAG,EAAC,UAAU,EAAE,sBAAsB,CAAC,gBAAgB,CAAC,aACzE,KAAC,UAAU,IACT,IAAI,EAAC,aAAa,gBACP,UAAU,EACrB,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EACxB,QAAQ,EAAE,CAAC,SAAS,EACpB,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GACzB,EACF,KAAC,UAAU,IACT,IAAI,EAAC,cAAc,gBACR,MAAM,EACjB,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EACvB,QAAQ,EAAE,CAAC,YAAY,EACvB,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GACzB,IACE,CACP,CAAC;IAEF,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,CAC7B,KAAC,GAAG,IAAC,SAAS,QAAC,GAAG,EAAC,GAAG,EAAC,UAAU,EAAC,QAAQ,EAAC,QAAQ,EAAC,QAAQ,EAAC,QAAQ,EAAC,GAAG,YACtE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CACnB,iBAKE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,iBACX,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,gBACvC,cAAc,CAAC,GAAG,CAAC,OAAO,KAAK,EAAE,kBAC/B,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACpD,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IANjB,CAAC,CAON,CACH,CAAC,GACE,CACP,CAAC,CAAC,CAAC,IAAI,CAAC;IAET;;;;;;;;;OASG;IACH,MAAM,OAAO,GACX,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IACzF,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7D,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,QAAQ,GAAG,MAAM,CAAC;IAErD,OAAO,CACL,MAAC,MAAM,IAAC,GAAG,EAAE,GAAG,EAAE,SAAS,QAAC,GAAG,EAAC,GAAG,0BAAsB,UAAU,aAQhE,UAAU,KAAK,KAAK,IAAI,SAAS,EACjC,cAAc,IAAI,QAAQ,EAE3B,KAAC,IAAI,IACH,GAAG,EAAE,WAAW,EAChB,SAAS,QACT,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,mBAC3C,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAC5C,aAAa,EAAE,aAAa,EAC5B,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,OAAO,EACpB,eAAe,EAAE,OAAO,EACxB,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,SAAS;gBACpB,iEAAiE;gBACjE,oCAAoC;gBACpC,QAAQ,EAAE,CAAC,EACX,IAAI,EAAC,OAAO,gBACD,OAAO,YAElB,KAAC,GAAG,IACF,GAAG,EAAE,QAAQ,EACb,GAAG,EAAC,GAAG,EACP,SAAS,EAAE,MAAM,CAAC,KAAK,EACvB,eAAe,EAAE,mBAAmB,EACpC,KAAK,EAAE;wBACL,SAAS,EAAE,eAAe,MAAM,WAAW;wBAC3C,kEAAkE;wBAClE,+DAA+D;wBAC/D,4DAA4D;wBAC5D,iEAAiE;wBACjE,sDAAsD;wBACtD,wDAAwD;wBACxD,mDAAmD;wBACnD,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;qBAC5C,YAEA,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;wBACxB,MAAM,KAAK,GAAG,OAAO;4BACnB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,CAAC;4BACvE,CAAC,CAAC,CAAC,CAAC;wBACN,OAAO,CACL,KAAC,MAAM;wBACL,+DAA+D;wBAC/D,gEAAgE;wBAChE,oEAAoE;4BAEpE,SAAS,EAAE,MAAM,CAAC,IAAI;4BACtB,6DAA6D;4BAC7D,4DAA4D;4BAC5D,4DAA4D;4BAC5D,+DAA+D;4BAC/D,6DAA6D;4BAC7D,+CAA+C;4BAC/C,QAAQ,EAAE,EAAE,iBAGC,QAAQ,IAAI,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,KAC7E,IAAI,EACR,KAAK,EAAE;gCACL,GAAG,IAAI,CAAC,KAAK;gCACb,4DAA4D;gCAC5D,0DAA0D;gCAC1D,+BAA+B;gCAC/B,GAAG,CAAC,OAAO;oCACT,CAAC,CAAC;wCACE,SAAS,EAAE,SAAS,KAAK,GAAG;wCAC5B,uDAAuD;wCACvD,mDAAmD;wCACnD,qDAAqD;wCACrD,sBAAsB;wCACtB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;qCAC5C;oCACH,CAAC,CAAC,EAAE,CAAC;6BACR,YAEA,IAAI,IA9BA,CAAC,CA+BC,CACV,CAAC;oBACJ,CAAC,CAAC,GACE,GACD,EAEN,CAAC,cAAc,IAAI,QAAQ,EAC3B,UAAU,KAAK,QAAQ,IAAI,SAAS,IAC9B,CACV,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,eAAe,CAAC,WAAW,GAAG,iBAAiB,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The track paints past the viewport by default.
|
|
3
|
+
*
|
|
4
|
+
* This is the point of moving a transform instead of scrolling a box: tiles
|
|
5
|
+
* either side of the ones in front stay visible, so the run reads as something
|
|
6
|
+
* continuous that has been moved along rather than a window with two hard cuts
|
|
7
|
+
* in it.
|
|
8
|
+
*
|
|
9
|
+
* `overflow: clip` with a large `overflow-clip-margin` rather than
|
|
10
|
+
* `overflow: visible`, because visible overflow is not confined to the
|
|
11
|
+
* direction it is wanted in: a track wider than the page would extend the
|
|
12
|
+
* document's scrollable area and give the whole page a horizontal scrollbar,
|
|
13
|
+
* which is a page-level bug produced by a component that cannot see the page.
|
|
14
|
+
* A clip margin is the same effect with a boundary — tiles paint well past the
|
|
15
|
+
* edges, and nothing reaches far enough to push the document out.
|
|
16
|
+
*
|
|
17
|
+
* `clip` is not `hidden`: `hidden` makes the element a scroll container, which
|
|
18
|
+
* would let a stray focus or a wheel gesture scroll the track sideways and put
|
|
19
|
+
* the transform and the scroll offset into disagreement about where the track
|
|
20
|
+
* is. `clip` cannot scroll, which is what this needs.
|
|
21
|
+
*/
|
|
22
|
+
.viewport {
|
|
23
|
+
overflow: clip;
|
|
24
|
+
overflow-clip-margin: 100vw;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Self-contained: nothing paints outside the component's own box. */
|
|
28
|
+
.viewportClipped {
|
|
29
|
+
overflow: clip;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.viewport,
|
|
33
|
+
.viewportClipped {
|
|
34
|
+
/*
|
|
35
|
+
* Horizontal gestures belong to the track and vertical ones to the page.
|
|
36
|
+
* Without this the browser claims the whole gesture before the pointer
|
|
37
|
+
* handler can decide, and a carousel becomes a place where the page stops
|
|
38
|
+
* scrolling.
|
|
39
|
+
*/
|
|
40
|
+
touch-action: pan-y;
|
|
41
|
+
cursor: grab;
|
|
42
|
+
|
|
43
|
+
&:focus-visible {
|
|
44
|
+
outline: var(--static-space-2) solid var(--brand-border-strong);
|
|
45
|
+
outline-offset: var(--static-space-2);
|
|
46
|
+
border-radius: var(--radius-m);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&[data-dragging="true"] {
|
|
50
|
+
cursor: grabbing;
|
|
51
|
+
/* A drag across tiles selects their text otherwise, and the selection
|
|
52
|
+
highlight follows the pointer across the whole run. */
|
|
53
|
+
user-select: none;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.track {
|
|
58
|
+
/*
|
|
59
|
+
* `width: max-content` is what makes a transform track possible at all:
|
|
60
|
+
* the row lays out at the sum of its tiles rather than at the width of its
|
|
61
|
+
* parent, so there is something to move. Without it the tiles would be
|
|
62
|
+
* squeezed into one viewport's width and the transform would move an
|
|
63
|
+
* already-complete layout off the screen.
|
|
64
|
+
*/
|
|
65
|
+
width: max-content;
|
|
66
|
+
will-change: transform;
|
|
67
|
+
transition: transform var(--transition-duration-macro-long) var(--transition-eased);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.tile {
|
|
71
|
+
/* A track item that can shrink is a track item that has no width of its own
|
|
72
|
+
once the row is wider than its parent. */
|
|
73
|
+
flex-shrink: 0;
|
|
74
|
+
|
|
75
|
+
/*
|
|
76
|
+
* For `proximity`. The scale itself is set per tile from the distance to the
|
|
77
|
+
* front, which only the component can know; the easing belongs here so it
|
|
78
|
+
* matches the track's, and so a tile settles into its new size on the same
|
|
79
|
+
* curve the track settles onto its new offset. During a drag the component
|
|
80
|
+
* turns this off inline and the size follows the pointer.
|
|
81
|
+
*
|
|
82
|
+
* `transform-origin: center` keeps a shrinking tile in its own slot instead
|
|
83
|
+
* of pulling away from one side of the gap.
|
|
84
|
+
*/
|
|
85
|
+
transform-origin: center;
|
|
86
|
+
transition: transform var(--transition-duration-macro-long) var(--transition-eased);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.marker {
|
|
90
|
+
appearance: none;
|
|
91
|
+
border: 0;
|
|
92
|
+
padding: 0;
|
|
93
|
+
width: var(--static-space-8);
|
|
94
|
+
height: var(--static-space-8);
|
|
95
|
+
border-radius: var(--radius-full);
|
|
96
|
+
background: var(--neutral-alpha-medium);
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
transition:
|
|
99
|
+
background var(--transition-duration-micro-medium) var(--transition-eased),
|
|
100
|
+
width var(--transition-duration-micro-medium) var(--transition-eased);
|
|
101
|
+
|
|
102
|
+
&:hover {
|
|
103
|
+
background: var(--neutral-alpha-strong);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&:focus-visible {
|
|
107
|
+
outline: var(--static-space-2) solid var(--brand-border-strong);
|
|
108
|
+
outline-offset: var(--static-space-2);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* The one in front is a bar rather than a brighter dot: the difference
|
|
112
|
+
survives being small, and being colour-blind. */
|
|
113
|
+
&[data-active="true"] {
|
|
114
|
+
width: var(--static-space-20);
|
|
115
|
+
background: var(--brand-solid-strong);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@media (prefers-reduced-motion: reduce) {
|
|
120
|
+
.track {
|
|
121
|
+
transition: none;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.tile {
|
|
125
|
+
transition: none;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.marker {
|
|
129
|
+
transition: none;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { ReactNode } from "react";
|
|
2
2
|
import { InputProps, OptionProps, DropdownWrapperProps } from ".";
|
|
3
|
-
import { Placement } from "
|
|
3
|
+
import type { Placement } from "../types";
|
|
4
4
|
type SelectOptionType = Omit<OptionProps, "selected">;
|
|
5
5
|
interface SelectProps extends Omit<InputProps, "onSelect" | "value">, Pick<DropdownWrapperProps, "minHeight" | "minWidth" | "maxWidth"> {
|
|
6
6
|
options: SelectOptionType[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../src/components/Select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAA2C,SAAS,EAAS,MAAM,OAAO,CAAC;AAEzF,OAAO,EAML,UAAU,EAEV,WAAW,EACX,oBAAoB,EAIrB,MAAM,GAAG,CAAC;AACX,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../src/components/Select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAA2C,SAAS,EAAS,MAAM,OAAO,CAAC;AAEzF,OAAO,EAML,UAAU,EAEV,WAAW,EACX,oBAAoB,EAIrB,MAAM,GAAG,CAAC;AACX,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C,KAAK,gBAAgB,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AAEtD,UAAU,WACR,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,EAC5C,IAAI,CAAC,oBAAoB,EAAE,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;IACnE,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9C,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAoFD,QAAA,MAAM,MAAM,oFA+QX,CAAC;AAGF,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -7,7 +7,7 @@ import inputStyles from "./Input.module.scss";
|
|
|
7
7
|
// Inner component that uses the arrow navigation context
|
|
8
8
|
const SearchInput = ({ searchInputId, searchQuery, setSearchQuery, setIsDropdownOpen, handleClearSearch, handleBlur, selectRef, }) => {
|
|
9
9
|
const { handleKeyDown: navKeyDown } = useArrowNavigationContext();
|
|
10
|
-
return (_jsx(Input, { "data-scaling": "90", id: `select-search-${searchInputId}`, placeholder: "Search",
|
|
10
|
+
return (_jsx(Input, { "data-scaling": "90", id: `select-search-${searchInputId}`, placeholder: "Search", size: "s", suffix: searchQuery ? (_jsx(IconButton, { tooltip: "Clear", tooltipPosition: "left", icon: "close", variant: "ghost", size: "s", onClick: handleClearSearch })) : undefined, prefix: _jsx(Icon, { name: "search", size: "xs" }), value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onClick: (e) => {
|
|
11
11
|
e.stopPropagation();
|
|
12
12
|
e.preventDefault();
|
|
13
13
|
setIsDropdownOpen(true);
|