@pathscale/ui 2.3.1 → 2.3.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/dist/components/_shared/overlayPosition.d.ts +10 -0
- package/dist/components/_shared/overlayPosition.js +7 -4
- package/dist/components/collapsible/Collapsible.generated.js +37 -32
- package/dist/components/collapsible/Collapsible.mounting.d.ts +11 -0
- package/dist/components/collapsible/Collapsible.mounting.js +2 -0
- package/dist/components/popover/Popover.generated.d.ts +4 -1
- package/dist/components/popover/Popover.generated.js +5 -1
- package/dist/components/popover/index.d.ts +1 -0
- package/dist/components/slider/Slider.generated.d.ts +1 -0
- package/dist/components/slider/Slider.generated.js +67 -33
- package/dist/components/slider/Slider.interactions.d.ts +22 -0
- package/dist/components/slider/Slider.interactions.js +93 -0
- package/dist/components/tabs/Tabs.generated.d.ts +1 -1
- package/dist/components/tabs/Tabs.generated.js +6 -4
- package/dist/components/tabs/Tabs.measurement.d.ts +3 -0
- package/dist/components/tabs/Tabs.measurement.js +8 -0
- package/dist/index.d.ts +2 -1
- package/dist/layouts.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { type Accessor, type JSX } from "solid-js";
|
|
2
2
|
export type OverlayPlacement = "top" | "bottom" | "left" | "right";
|
|
3
3
|
export type OverlayAlign = "start" | "center" | "end";
|
|
4
|
+
export type OverlayAnchorRect = {
|
|
5
|
+
top: number;
|
|
6
|
+
left: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
right: number;
|
|
10
|
+
bottom: number;
|
|
11
|
+
};
|
|
4
12
|
export interface CreateOverlayPositionOptions {
|
|
5
13
|
open: Accessor<boolean>;
|
|
6
14
|
triggerRef: Accessor<HTMLElement | undefined>;
|
|
15
|
+
anchorRect?: Accessor<OverlayAnchorRect | undefined>;
|
|
7
16
|
overlayRef: Accessor<HTMLElement | undefined>;
|
|
8
17
|
placement: Accessor<OverlayPlacement>;
|
|
9
18
|
offset: Accessor<number>;
|
|
@@ -13,6 +22,7 @@ export interface CreateOverlayPositionOptions {
|
|
|
13
22
|
minWidth?: Accessor<number | undefined>;
|
|
14
23
|
viewportPadding?: Accessor<number>;
|
|
15
24
|
}
|
|
25
|
+
export declare const resolveOverlayAnchorRect: (trigger: Pick<HTMLElement, "getBoundingClientRect"> | undefined, anchorRect: OverlayAnchorRect | undefined) => OverlayAnchorRect | DOMRect | undefined;
|
|
16
26
|
export declare const createOverlayPosition: (options: CreateOverlayPositionOptions) => {
|
|
17
27
|
style: Accessor<JSX.CSSProperties>;
|
|
18
28
|
placement: Accessor<OverlayPlacement>;
|
|
@@ -30,6 +30,7 @@ const getCrossAxisCoordinate = (align, triggerStart, triggerSize, overlaySize)=>
|
|
|
30
30
|
return triggerStart + (triggerSize - overlaySize) / 2;
|
|
31
31
|
};
|
|
32
32
|
const round = (value)=>Math.round(100 * value) / 100;
|
|
33
|
+
const resolveOverlayAnchorRect = (trigger, anchorRect)=>anchorRect ?? trigger?.getBoundingClientRect();
|
|
33
34
|
const createOverlayPosition = (options)=>{
|
|
34
35
|
const [style, setStyle] = createSignal({
|
|
35
36
|
visibility: "hidden"
|
|
@@ -44,14 +45,16 @@ const createOverlayPosition = (options)=>{
|
|
|
44
45
|
return;
|
|
45
46
|
}
|
|
46
47
|
const trigger = options.triggerRef();
|
|
48
|
+
const anchorRect = options.anchorRect?.();
|
|
47
49
|
const overlay = options.overlayRef();
|
|
48
|
-
if (!trigger || !overlay) return;
|
|
50
|
+
if (!trigger && !anchorRect || !overlay) return;
|
|
49
51
|
const viewportPadding = options.viewportPadding?.() ?? 8;
|
|
50
52
|
const align = options.align?.() ?? "center";
|
|
51
53
|
const autoFlip = options.autoFlip?.() ?? true;
|
|
52
54
|
let frame = 0;
|
|
53
55
|
const update = ()=>{
|
|
54
|
-
const triggerRect = trigger.
|
|
56
|
+
const triggerRect = resolveOverlayAnchorRect(trigger, options.anchorRect?.());
|
|
57
|
+
if (!triggerRect) return;
|
|
55
58
|
const overlayRect = overlay.getBoundingClientRect();
|
|
56
59
|
const viewportWidth = window.innerWidth;
|
|
57
60
|
const viewportHeight = window.innerHeight;
|
|
@@ -98,7 +101,7 @@ const createOverlayPosition = (options)=>{
|
|
|
98
101
|
window.addEventListener("resize", schedule);
|
|
99
102
|
window.addEventListener("scroll", schedule, true);
|
|
100
103
|
const resizeObserver = "u" > typeof ResizeObserver ? new ResizeObserver(schedule) : void 0;
|
|
101
|
-
resizeObserver?.observe(trigger);
|
|
104
|
+
if (trigger) resizeObserver?.observe(trigger);
|
|
102
105
|
resizeObserver?.observe(overlay);
|
|
103
106
|
onCleanup(()=>{
|
|
104
107
|
cancelAnimationFrame(frame);
|
|
@@ -112,4 +115,4 @@ const createOverlayPosition = (options)=>{
|
|
|
112
115
|
placement: resolvedPlacement
|
|
113
116
|
};
|
|
114
117
|
};
|
|
115
|
-
export { createOverlayPosition };
|
|
118
|
+
export { createOverlayPosition, resolveOverlayAnchorRect };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createComponent, insert, mergeProps, spread, template } from "solid-js/web";
|
|
2
2
|
import { defineComponent } from "solid-layouts/application-boundary";
|
|
3
3
|
import "./Collapsible.css";
|
|
4
|
-
import { createContext, createMemo, createSignal, createUniqueId, splitProps, useContext } from "solid-js";
|
|
4
|
+
import { Show, createContext, createMemo, createSignal, createUniqueId, splitProps, useContext } from "solid-js";
|
|
5
5
|
import { twMerge } from "tailwind-merge";
|
|
6
6
|
import { CLASSES, componentRecipe } from "./Collapsible.recipe.js";
|
|
7
|
+
import { shouldMountCollapsibleContent } from "./Collapsible.mounting.js";
|
|
7
8
|
var _tmpl$ = /*#__PURE__*/ template("<div>"), _tmpl$2 = /*#__PURE__*/ template("<h3>"), _tmpl$3 = /*#__PURE__*/ template("<button>"), _tmpl$4 = /*#__PURE__*/ template("<div><div>"), _tmpl$5 = /*#__PURE__*/ template("<span>"), _tmpl$6 = /*#__PURE__*/ template('<svg fill=none role=presentation viewBox="0 0 24 24"width=100% height=100%><path d="M6 9L12 15L18 9"stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round>');
|
|
8
9
|
const CollapsibleContext = createContext();
|
|
9
10
|
const useCollapsibleContext = ()=>{
|
|
@@ -188,37 +189,41 @@ const __solidLayoutCollapsibleContent = (_stable, p)=>{
|
|
|
188
189
|
]);
|
|
189
190
|
const expanded = ()=>ctx.isExpanded();
|
|
190
191
|
const keepMounted = ()=>local.keepMounted ?? true;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
192
|
+
return createComponent(Show, {
|
|
193
|
+
get when () {
|
|
194
|
+
return shouldMountCollapsibleContent(keepMounted(), expanded());
|
|
195
|
+
},
|
|
196
|
+
get children () {
|
|
197
|
+
var _el$4 = _tmpl$();
|
|
198
|
+
spread(_el$4, mergeProps(others, {
|
|
199
|
+
get id () {
|
|
200
|
+
return ctx.contentId();
|
|
201
|
+
},
|
|
202
|
+
role: "region"
|
|
203
|
+
}, ()=>({
|
|
204
|
+
class: twMerge(CLASSES.slot.content, local.class)
|
|
205
|
+
}), {
|
|
206
|
+
"data-slot": "collapsible-content",
|
|
207
|
+
get ["data-expanded"] () {
|
|
208
|
+
return expanded() ? "true" : "false";
|
|
209
|
+
},
|
|
210
|
+
get ["data-theme"] () {
|
|
211
|
+
return local.dataTheme;
|
|
212
|
+
},
|
|
213
|
+
get style () {
|
|
214
|
+
return local.style;
|
|
215
|
+
},
|
|
216
|
+
get ["aria-hidden"] () {
|
|
217
|
+
return expanded() ? "false" : "true";
|
|
218
|
+
},
|
|
219
|
+
get ["aria-labelledby"] () {
|
|
220
|
+
return ctx.triggerId();
|
|
221
|
+
}
|
|
222
|
+
}), false, true);
|
|
223
|
+
insert(_el$4, ()=>local.children);
|
|
224
|
+
return _el$4;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
222
227
|
};
|
|
223
228
|
const CollapsibleContent = defineComponent({
|
|
224
229
|
recipe: componentRecipe,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the content element should exist in the DOM.
|
|
3
|
+
*
|
|
4
|
+
* Trivial, and a module of its own because the caller has to read it inside a
|
|
5
|
+
* tracked scope. The same expression written as an early `return null` in the
|
|
6
|
+
* component body reads both values exactly once: a collapsible that starts
|
|
7
|
+
* collapsed with `keepMounted={false}` then never appears, and one that starts
|
|
8
|
+
* expanded never goes away. Naming it makes the reactive read the obvious
|
|
9
|
+
* place to put it, and lets the behaviour be tested without a renderer.
|
|
10
|
+
*/
|
|
11
|
+
export declare const shouldMountCollapsibleContent: (keepMounted: boolean, expanded: boolean) => boolean;
|
|
@@ -2,8 +2,10 @@ import type { Component as __LayoutComponent } from "solid-js";
|
|
|
2
2
|
import "./Popover.css";
|
|
3
3
|
import { type JSX } from "solid-js";
|
|
4
4
|
import type { UIBaseProps } from "../vocabulary";
|
|
5
|
-
import { type OverlayPlacement } from "../_shared/overlayPosition";
|
|
5
|
+
import { type OverlayAnchorRect, type OverlayPlacement } from "../_shared/overlayPosition";
|
|
6
6
|
export type PopoverPlacement = OverlayPlacement;
|
|
7
|
+
export type PopoverAnchorRect = OverlayAnchorRect;
|
|
8
|
+
export type PopoverAnchor = PopoverAnchorRect | (() => PopoverAnchorRect | undefined);
|
|
7
9
|
export type PopoverRootProps = UIBaseProps & Omit<JSX.HTMLAttributes<HTMLDivElement>, "children"> & {
|
|
8
10
|
children: JSX.Element;
|
|
9
11
|
open?: boolean;
|
|
@@ -12,6 +14,7 @@ export type PopoverRootProps = UIBaseProps & Omit<JSX.HTMLAttributes<HTMLDivElem
|
|
|
12
14
|
placement?: PopoverPlacement;
|
|
13
15
|
autoFlip?: boolean;
|
|
14
16
|
offset?: number;
|
|
17
|
+
anchorRect?: PopoverAnchor;
|
|
15
18
|
closeOnOutsideClick?: boolean;
|
|
16
19
|
closeOnEscape?: boolean;
|
|
17
20
|
onInteractOutside?: (event: Event) => void;
|
|
@@ -24,6 +24,7 @@ const __solidLayoutPopoverRoot = (_stable, p)=>{
|
|
|
24
24
|
"placement",
|
|
25
25
|
"autoFlip",
|
|
26
26
|
"offset",
|
|
27
|
+
"anchorRect",
|
|
27
28
|
"closeOnOutsideClick",
|
|
28
29
|
"closeOnEscape",
|
|
29
30
|
"onInteractOutside"
|
|
@@ -45,6 +46,7 @@ const __solidLayoutPopoverRoot = (_stable, p)=>{
|
|
|
45
46
|
const placement = ()=>resolvedPlacement();
|
|
46
47
|
const offset = ()=>local.offset ?? 8;
|
|
47
48
|
const autoFlip = ()=>local.autoFlip ?? true;
|
|
49
|
+
const anchorRect = ()=>"function" == typeof local.anchorRect ? local.anchorRect() : local.anchorRect;
|
|
48
50
|
onMount(()=>{
|
|
49
51
|
const handlePointerDown = (event)=>{
|
|
50
52
|
if (!isOpen()) return;
|
|
@@ -81,6 +83,7 @@ const __solidLayoutPopoverRoot = (_stable, p)=>{
|
|
|
81
83
|
placement,
|
|
82
84
|
setPlacement: setResolvedPlacement,
|
|
83
85
|
autoFlip,
|
|
86
|
+
anchorRect,
|
|
84
87
|
triggerRef,
|
|
85
88
|
setTriggerRef,
|
|
86
89
|
contentRef,
|
|
@@ -194,6 +197,7 @@ const __solidLayoutPopoverContent = (_stable, p)=>{
|
|
|
194
197
|
const overlayPosition = createOverlayPosition({
|
|
195
198
|
open: ctx.isOpen,
|
|
196
199
|
triggerRef: ctx.triggerRef,
|
|
200
|
+
anchorRect: ctx.anchorRect,
|
|
197
201
|
overlayRef: ctx.contentRef,
|
|
198
202
|
placement: ctx.preferredPlacement,
|
|
199
203
|
offset: ()=>local.sideOffset ?? ctx.offset(),
|
|
@@ -245,7 +249,7 @@ const __solidLayoutPopoverContent = (_stable, p)=>{
|
|
|
245
249
|
return style();
|
|
246
250
|
},
|
|
247
251
|
get ["aria-labelledby"] () {
|
|
248
|
-
return ctx.triggerId();
|
|
252
|
+
return memo(()=>!!ctx.triggerRef())() ? ctx.triggerId() : void 0;
|
|
249
253
|
},
|
|
250
254
|
get ["aria-hidden"] () {
|
|
251
255
|
return ctx.isOpen() ? "false" : "true";
|
|
@@ -7,5 +7,6 @@ export type PopoverContentProps = ComponentProps<typeof PopoverContent>;
|
|
|
7
7
|
export type PopoverDialogProps = ComponentProps<typeof PopoverDialog>;
|
|
8
8
|
export type PopoverArrowProps = ComponentProps<typeof PopoverArrow>;
|
|
9
9
|
export type PopoverHeadingProps = ComponentProps<typeof PopoverHeading>;
|
|
10
|
+
export type { PopoverAnchor, PopoverAnchorRect } from "./Popover.generated";
|
|
10
11
|
export { PopoverRoot, PopoverTrigger, PopoverContent, PopoverDialog, PopoverArrow, PopoverHeading, };
|
|
11
12
|
export default Popover;
|
|
@@ -4,6 +4,7 @@ import "./Slider.css";
|
|
|
4
4
|
import { Show, createSignal, createUniqueId, splitProps } from "solid-js";
|
|
5
5
|
import { twMerge } from "tailwind-merge";
|
|
6
6
|
import { CLASSES, componentRecipe } from "./Slider.recipe.js";
|
|
7
|
+
import { createSliderInteractionHandlers } from "./Slider.interactions.js";
|
|
7
8
|
var _tmpl$ = /*#__PURE__*/ template("<span>"), _tmpl$2 = /*#__PURE__*/ template("<div><div><div></div><div>");
|
|
8
9
|
function clamp(val, min, max) {
|
|
9
10
|
return Math.min(Math.max(val, min), max);
|
|
@@ -14,10 +15,12 @@ function snapToStep(val, min, max, step) {
|
|
|
14
15
|
}
|
|
15
16
|
const __solidLayoutSlider = (_stable, p)=>{
|
|
16
17
|
let trackRef;
|
|
18
|
+
let thumbRef;
|
|
17
19
|
const [local] = splitProps(p, [
|
|
18
20
|
"label",
|
|
19
21
|
"value",
|
|
20
22
|
"onChange",
|
|
23
|
+
"onChangeEnd",
|
|
21
24
|
"min",
|
|
22
25
|
"max",
|
|
23
26
|
"step",
|
|
@@ -50,48 +53,48 @@ const __solidLayoutSlider = (_stable, p)=>{
|
|
|
50
53
|
const f = fraction();
|
|
51
54
|
return `calc(${f} * 100% + ${1 - f} * var(--slider-thumb-w) + ${2 - 2 * f} * var(--slider-pad))`;
|
|
52
55
|
};
|
|
56
|
+
const centreInset = ()=>{
|
|
57
|
+
if (!trackRef || !thumbRef) return 0;
|
|
58
|
+
const pad = Math.max(0, (trackRef.offsetHeight - thumbRef.offsetHeight) / 2);
|
|
59
|
+
return thumbRef.offsetWidth / 2 + pad;
|
|
60
|
+
};
|
|
61
|
+
let dragGeometry;
|
|
62
|
+
const measureTrack = ()=>{
|
|
63
|
+
if (!trackRef) return;
|
|
64
|
+
const rect = trackRef.getBoundingClientRect();
|
|
65
|
+
const inset = centreInset();
|
|
66
|
+
return {
|
|
67
|
+
left: rect.left,
|
|
68
|
+
inset,
|
|
69
|
+
usable: rect.width - 2 * inset
|
|
70
|
+
};
|
|
71
|
+
};
|
|
53
72
|
const getValueFromPosition = (clientX)=>{
|
|
54
73
|
if (!trackRef) return local.value;
|
|
55
|
-
const
|
|
56
|
-
|
|
74
|
+
const geometry = dragGeometry ?? measureTrack();
|
|
75
|
+
if (!geometry || geometry.usable <= 0) return local.value;
|
|
76
|
+
const frac = clamp((clientX - geometry.left - geometry.inset) / geometry.usable, 0, 1);
|
|
57
77
|
const raw = min() + frac * (max() - min());
|
|
58
78
|
return snapToStep(raw, min(), max(), step());
|
|
59
79
|
};
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
e.preventDefault();
|
|
63
|
-
e.currentTarget.setPointerCapture(e.pointerId);
|
|
64
|
-
setDragging(true);
|
|
65
|
-
const val = getValueFromPosition(e.clientX);
|
|
66
|
-
if (val !== local.value) local.onChange(val);
|
|
67
|
-
};
|
|
68
|
-
const handlePointerMove = (e)=>{
|
|
69
|
-
if (!dragging()) return;
|
|
70
|
-
const val = getValueFromPosition(e.clientX);
|
|
71
|
-
if (val !== local.value) local.onChange(val);
|
|
72
|
-
};
|
|
73
|
-
const handlePointerUp = ()=>{
|
|
74
|
-
setDragging(false);
|
|
75
|
-
};
|
|
76
|
-
const handleKeyDown = (e)=>{
|
|
77
|
-
if (isDisabled()) return;
|
|
78
|
-
let newVal = local.value;
|
|
80
|
+
const getValueFromKey = (key, currentValue)=>{
|
|
81
|
+
let newVal = currentValue;
|
|
79
82
|
const s = step();
|
|
80
83
|
const bigStep = (max() - min()) / 10;
|
|
81
|
-
switch(
|
|
84
|
+
switch(key){
|
|
82
85
|
case "ArrowRight":
|
|
83
86
|
case "ArrowUp":
|
|
84
|
-
newVal = clamp(
|
|
87
|
+
newVal = clamp(currentValue + s, min(), max());
|
|
85
88
|
break;
|
|
86
89
|
case "ArrowLeft":
|
|
87
90
|
case "ArrowDown":
|
|
88
|
-
newVal = clamp(
|
|
91
|
+
newVal = clamp(currentValue - s, min(), max());
|
|
89
92
|
break;
|
|
90
93
|
case "PageUp":
|
|
91
|
-
newVal = clamp(
|
|
94
|
+
newVal = clamp(currentValue + bigStep, min(), max());
|
|
92
95
|
break;
|
|
93
96
|
case "PageDown":
|
|
94
|
-
newVal = clamp(
|
|
97
|
+
newVal = clamp(currentValue - bigStep, min(), max());
|
|
95
98
|
break;
|
|
96
99
|
case "Home":
|
|
97
100
|
newVal = min();
|
|
@@ -102,9 +105,21 @@ const __solidLayoutSlider = (_stable, p)=>{
|
|
|
102
105
|
default:
|
|
103
106
|
return;
|
|
104
107
|
}
|
|
105
|
-
|
|
106
|
-
if (newVal !== local.value) local.onChange(snapToStep(newVal, min(), max(), s));
|
|
108
|
+
return snapToStep(newVal, min(), max(), s);
|
|
107
109
|
};
|
|
110
|
+
const interactions = createSliderInteractionHandlers({
|
|
111
|
+
isDisabled,
|
|
112
|
+
value: ()=>local.value,
|
|
113
|
+
valueFromPosition: getValueFromPosition,
|
|
114
|
+
valueFromKey: getValueFromKey,
|
|
115
|
+
onDragGeometry: (active)=>{
|
|
116
|
+
dragGeometry = active ? measureTrack() : void 0;
|
|
117
|
+
},
|
|
118
|
+
isThumb: (target)=>Boolean(thumbRef && target === thumbRef),
|
|
119
|
+
onChange: (value)=>local.onChange(value),
|
|
120
|
+
onChangeEnd: (value)=>local.onChangeEnd?.(value),
|
|
121
|
+
onDraggingChange: setDragging
|
|
122
|
+
});
|
|
108
123
|
const handleFocus = ()=>setFocusVisible(true);
|
|
109
124
|
const handleBlur = ()=>setFocusVisible(false);
|
|
110
125
|
return (()=>{
|
|
@@ -160,9 +175,18 @@ const __solidLayoutSlider = (_stable, p)=>{
|
|
|
160
175
|
class: CLASSES.track
|
|
161
176
|
}), {
|
|
162
177
|
"data-slot": "slider-track",
|
|
163
|
-
onPointerDown
|
|
164
|
-
|
|
165
|
-
|
|
178
|
+
get onPointerDown () {
|
|
179
|
+
return interactions.onPointerDown;
|
|
180
|
+
},
|
|
181
|
+
get onPointerMove () {
|
|
182
|
+
return interactions.onPointerMove;
|
|
183
|
+
},
|
|
184
|
+
get onPointerUp () {
|
|
185
|
+
return interactions.onPointerUp;
|
|
186
|
+
},
|
|
187
|
+
get onPointerCancel () {
|
|
188
|
+
return interactions.onPointerCancel;
|
|
189
|
+
}
|
|
166
190
|
}), false, true);
|
|
167
191
|
spread(_el$5, mergeProps(()=>({
|
|
168
192
|
class: CLASSES.fill
|
|
@@ -174,6 +198,8 @@ const __solidLayoutSlider = (_stable, p)=>{
|
|
|
174
198
|
};
|
|
175
199
|
}
|
|
176
200
|
}), false, false);
|
|
201
|
+
var _ref$2 = thumbRef;
|
|
202
|
+
"function" == typeof _ref$2 ? use(_ref$2, _el$6) : thumbRef = _el$6;
|
|
177
203
|
spread(_el$6, mergeProps(()=>({
|
|
178
204
|
class: CLASSES.thumb
|
|
179
205
|
}), {
|
|
@@ -214,9 +240,17 @@ const __solidLayoutSlider = (_stable, p)=>{
|
|
|
214
240
|
get ["aria-disabled"] () {
|
|
215
241
|
return isDisabled() ? "true" : void 0;
|
|
216
242
|
},
|
|
217
|
-
onKeyDown
|
|
243
|
+
get onKeyDown () {
|
|
244
|
+
return interactions.onKeyDown;
|
|
245
|
+
},
|
|
246
|
+
get onKeyUp () {
|
|
247
|
+
return interactions.onKeyUp;
|
|
248
|
+
},
|
|
218
249
|
onFocus: handleFocus,
|
|
219
|
-
onBlur:
|
|
250
|
+
onBlur: ()=>{
|
|
251
|
+
interactions.onBlur();
|
|
252
|
+
handleBlur();
|
|
253
|
+
}
|
|
220
254
|
}), false, false);
|
|
221
255
|
return _el$;
|
|
222
256
|
})();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type SliderInteractionOptions = {
|
|
2
|
+
isDisabled: () => boolean;
|
|
3
|
+
value: () => number;
|
|
4
|
+
valueFromPosition: (clientX: number) => number;
|
|
5
|
+
/** Called when a drag begins and ends, so geometry can be measured once. */
|
|
6
|
+
onDragGeometry?: (active: boolean) => void;
|
|
7
|
+
/** Whether a press landed on the thumb rather than on the bare track. */
|
|
8
|
+
isThumb?: (target: EventTarget | null) => boolean;
|
|
9
|
+
valueFromKey: (key: string, currentValue: number) => number | undefined;
|
|
10
|
+
onChange: (value: number) => void;
|
|
11
|
+
onChangeEnd: (value: number) => void;
|
|
12
|
+
onDraggingChange: (dragging: boolean) => void;
|
|
13
|
+
};
|
|
14
|
+
export declare const createSliderInteractionHandlers: (options: SliderInteractionOptions) => {
|
|
15
|
+
onPointerDown(event: PointerEvent): void;
|
|
16
|
+
onPointerMove(event: PointerEvent): void;
|
|
17
|
+
onPointerUp: (event: PointerEvent) => void;
|
|
18
|
+
onPointerCancel: (event: PointerEvent) => void;
|
|
19
|
+
onKeyDown(event: KeyboardEvent): void;
|
|
20
|
+
onKeyUp(event: KeyboardEvent): void;
|
|
21
|
+
onBlur: () => void;
|
|
22
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const sliderKeys = new Set([
|
|
2
|
+
"ArrowRight",
|
|
3
|
+
"ArrowUp",
|
|
4
|
+
"ArrowLeft",
|
|
5
|
+
"ArrowDown",
|
|
6
|
+
"PageUp",
|
|
7
|
+
"PageDown",
|
|
8
|
+
"Home",
|
|
9
|
+
"End"
|
|
10
|
+
]);
|
|
11
|
+
const releasePointerCapture = (target, pointerId)=>{
|
|
12
|
+
if (!("releasePointerCapture" in target)) return;
|
|
13
|
+
try {
|
|
14
|
+
if (!("hasPointerCapture" in target) || target.hasPointerCapture(pointerId)) target.releasePointerCapture(pointerId);
|
|
15
|
+
} catch {}
|
|
16
|
+
};
|
|
17
|
+
const createSliderInteractionHandlers = (options)=>{
|
|
18
|
+
let pointerId;
|
|
19
|
+
let pointerValue = 0;
|
|
20
|
+
let pointerChanged = false;
|
|
21
|
+
let keyboardActive = false;
|
|
22
|
+
let keyboardValue = 0;
|
|
23
|
+
let keyboardChanged = false;
|
|
24
|
+
const emitPointerValue = (nextValue)=>{
|
|
25
|
+
if (Object.is(nextValue, pointerValue)) return;
|
|
26
|
+
pointerValue = nextValue;
|
|
27
|
+
pointerChanged = true;
|
|
28
|
+
options.onChange(nextValue);
|
|
29
|
+
};
|
|
30
|
+
const finishPointer = (event)=>{
|
|
31
|
+
if (void 0 === pointerId || event.pointerId !== pointerId) return;
|
|
32
|
+
const finalValue = pointerValue;
|
|
33
|
+
const changed = pointerChanged;
|
|
34
|
+
const activePointerId = pointerId;
|
|
35
|
+
pointerId = void 0;
|
|
36
|
+
pointerChanged = false;
|
|
37
|
+
options.onDragGeometry?.(false);
|
|
38
|
+
options.onDraggingChange(false);
|
|
39
|
+
const target = event.currentTarget;
|
|
40
|
+
if (target) releasePointerCapture(target, activePointerId);
|
|
41
|
+
if (changed) options.onChangeEnd(finalValue);
|
|
42
|
+
};
|
|
43
|
+
const finishKeyboard = ()=>{
|
|
44
|
+
if (!keyboardActive) return;
|
|
45
|
+
const finalValue = keyboardValue;
|
|
46
|
+
const changed = keyboardChanged;
|
|
47
|
+
keyboardActive = false;
|
|
48
|
+
keyboardChanged = false;
|
|
49
|
+
if (changed) options.onChangeEnd(finalValue);
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
onPointerDown (event) {
|
|
53
|
+
if (options.isDisabled() || void 0 !== pointerId) return;
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
const target = event.currentTarget;
|
|
56
|
+
target.setPointerCapture(event.pointerId);
|
|
57
|
+
pointerId = event.pointerId;
|
|
58
|
+
pointerValue = options.value();
|
|
59
|
+
pointerChanged = false;
|
|
60
|
+
options.onDragGeometry?.(true);
|
|
61
|
+
options.onDraggingChange(true);
|
|
62
|
+
if (!options.isThumb?.(event.target)) emitPointerValue(options.valueFromPosition(event.clientX));
|
|
63
|
+
},
|
|
64
|
+
onPointerMove (event) {
|
|
65
|
+
if (void 0 === pointerId || event.pointerId !== pointerId) return;
|
|
66
|
+
emitPointerValue(options.valueFromPosition(event.clientX));
|
|
67
|
+
},
|
|
68
|
+
onPointerUp: finishPointer,
|
|
69
|
+
onPointerCancel: finishPointer,
|
|
70
|
+
onKeyDown (event) {
|
|
71
|
+
if (options.isDisabled()) return;
|
|
72
|
+
const currentValue = keyboardActive ? keyboardValue : options.value();
|
|
73
|
+
const nextValue = options.valueFromKey(event.key, currentValue);
|
|
74
|
+
if (void 0 === nextValue) return;
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
if (!keyboardActive) {
|
|
77
|
+
keyboardActive = true;
|
|
78
|
+
keyboardValue = currentValue;
|
|
79
|
+
keyboardChanged = false;
|
|
80
|
+
}
|
|
81
|
+
if (Object.is(nextValue, keyboardValue)) return;
|
|
82
|
+
keyboardValue = nextValue;
|
|
83
|
+
keyboardChanged = true;
|
|
84
|
+
options.onChange(nextValue);
|
|
85
|
+
},
|
|
86
|
+
onKeyUp (event) {
|
|
87
|
+
if (!sliderKeys.has(event.key)) return;
|
|
88
|
+
finishKeyboard();
|
|
89
|
+
},
|
|
90
|
+
onBlur: finishKeyboard
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
export { createSliderInteractionHandlers };
|
|
@@ -5,7 +5,7 @@ import type { State } from "../vocabulary";
|
|
|
5
5
|
type TabsOrientation = "horizontal" | "vertical";
|
|
6
6
|
type TabsVariant = "primary" | "secondary";
|
|
7
7
|
type TabKey = string | number;
|
|
8
|
-
type TabsRootProps = Omit<JSX.HTMLAttributes<HTMLDivElement>, "onChange"> & {
|
|
8
|
+
type TabsRootProps = Omit<JSX.HTMLAttributes<HTMLDivElement>, "onChange" | "onSelectionChange"> & {
|
|
9
9
|
children: JSX.Element;
|
|
10
10
|
orientation?: TabsOrientation;
|
|
11
11
|
variant?: TabsVariant;
|
|
@@ -4,6 +4,7 @@ import "./Tabs.css";
|
|
|
4
4
|
import { createContext, createEffect, createMemo, createSignal, createUniqueId, onCleanup, onMount, splitProps, useContext } from "solid-js";
|
|
5
5
|
import { twMerge } from "tailwind-merge";
|
|
6
6
|
import { CLASSES, componentRecipe } from "./Tabs.recipe.js";
|
|
7
|
+
import { observeTabIndicator } from "./Tabs.measurement.js";
|
|
7
8
|
var _tmpl$ = /*#__PURE__*/ template("<div>"), _tmpl$2 = /*#__PURE__*/ template("<div><span>"), _tmpl$3 = /*#__PURE__*/ template("<button>"), _tmpl$4 = /*#__PURE__*/ template("<span>");
|
|
8
9
|
const TabsContext = createContext();
|
|
9
10
|
const invokeEventHandler = (handler, event)=>{
|
|
@@ -168,10 +169,11 @@ const __solidLayoutTabList = (_stable, p)=>{
|
|
|
168
169
|
});
|
|
169
170
|
createEffect(()=>{
|
|
170
171
|
if (!listRef) return;
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
const disconnect = observeTabIndicator([
|
|
173
|
+
listRef,
|
|
174
|
+
...ctx.tabs().map((tab)=>tab.ref)
|
|
175
|
+
], scheduleMeasure);
|
|
176
|
+
onCleanup(disconnect);
|
|
175
177
|
});
|
|
176
178
|
onMount(()=>{
|
|
177
179
|
scheduleMeasure();
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
type ResizeObserverConstructor = new (callback: ResizeObserverCallback) => Pick<ResizeObserver, "observe" | "disconnect">;
|
|
2
|
+
export declare const observeTabIndicator: (targets: Element[], scheduleMeasure: () => void, Observer?: ResizeObserverConstructor | undefined) => () => void;
|
|
3
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const getResizeObserver = ()=>"u" < typeof ResizeObserver ? void 0 : ResizeObserver;
|
|
2
|
+
const observeTabIndicator = (targets, scheduleMeasure, Observer = getResizeObserver())=>{
|
|
3
|
+
if (!Observer) return ()=>{};
|
|
4
|
+
const observer = new Observer(()=>scheduleMeasure());
|
|
5
|
+
for (const target of targets)observer.observe(target);
|
|
6
|
+
return ()=>observer.disconnect();
|
|
7
|
+
};
|
|
8
|
+
export { observeTabIndicator };
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export { default as Address } from "./components/address";
|
|
|
11
11
|
export type { AddressProps, AddressTruncate, TruncateOptions } from "./components/address";
|
|
12
12
|
export { truncateAddress, copyAddress } from "./components/address";
|
|
13
13
|
export { default as Button } from "./components/button";
|
|
14
|
+
export type { ButtonProps } from "./components/button";
|
|
14
15
|
export { default as Calendar, type CalendarProps, type CalendarWeekdayFormat, type CalendarSelectionMode, type CalendarDaySelectHandler, type CalendarDayHoverHandler, } from "./components/calendar";
|
|
15
16
|
export { default as Card, Card as CardRoot, CardHeader, CardBody, CardFooter } from "./components/card";
|
|
16
17
|
export type { CardProps, CardSectionProps, CardMaterial, CardElevation } from "./components/card";
|
|
@@ -80,7 +81,7 @@ export type { PaginationProps } from "./components/pagination";
|
|
|
80
81
|
export { default as Progress } from "./components/progress";
|
|
81
82
|
export type { ProgressProps, ProgressSize, ProgressColor, } from "./components/progress";
|
|
82
83
|
export { default as Popover } from "./components/popover";
|
|
83
|
-
export type { PopoverProps, PopoverRootProps, PopoverTriggerProps, PopoverContentProps, PopoverDialogProps, PopoverArrowProps, PopoverHeadingProps, } from "./components/popover";
|
|
84
|
+
export type { PopoverProps, PopoverRootProps, PopoverTriggerProps, PopoverContentProps, PopoverDialogProps, PopoverArrowProps, PopoverHeadingProps, PopoverAnchor, PopoverAnchorRect, } from "./components/popover";
|
|
84
85
|
export { default as Radio } from "./components/radio";
|
|
85
86
|
export { RadioGroup, type RadioGroupProps, type RadioGroupOrientation, type RadioGroupVariant, } from "./components/radio-group";
|
|
86
87
|
export { default as Select } from "./components/select";
|