@seed-design/lynx-react 0.7.1 → 0.9.0
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/lib/components/Accordion/Accordion.jsx +2 -2
- package/lib/components/ActionButton/ActionButton.jsx +1 -1
- package/lib/components/AlertDialog/AlertDialog.d.ts +64 -0
- package/lib/components/AlertDialog/AlertDialog.d.ts.map +1 -0
- package/lib/components/AlertDialog/AlertDialog.jsx +138 -0
- package/lib/components/AlertDialog/AlertDialog.namespace.d.ts +2 -0
- package/lib/components/AlertDialog/AlertDialog.namespace.d.ts.map +1 -0
- package/lib/components/AlertDialog/AlertDialog.namespace.js +17 -0
- package/lib/components/AlertDialog/index.d.ts +3 -0
- package/lib/components/AlertDialog/index.d.ts.map +1 -0
- package/lib/components/AppBar/AppBar.d.ts +14 -1
- package/lib/components/AppBar/AppBar.d.ts.map +1 -1
- package/lib/components/AppBar/AppBar.jsx +42 -16
- package/lib/components/AppBar/AppBar.namespace.d.ts +1 -1
- package/lib/components/AppBar/AppBar.namespace.d.ts.map +1 -1
- package/lib/components/AppBar/context.d.ts +2 -1
- package/lib/components/AppBar/context.d.ts.map +1 -1
- package/lib/components/AppBar/index.d.ts +1 -1
- package/lib/components/AppBar/index.d.ts.map +1 -1
- package/lib/components/AppBar/useAppBar.d.ts +2 -1
- package/lib/components/AppBar/useAppBar.d.ts.map +1 -1
- package/lib/components/AppBar/useAppBar.js +17 -15
- package/lib/components/AttachmentDisplay/AttachmentDisplay.d.ts +182 -0
- package/lib/components/AttachmentDisplay/AttachmentDisplay.d.ts.map +1 -0
- package/lib/components/AttachmentDisplay/AttachmentDisplay.jsx +444 -0
- package/lib/components/AttachmentDisplay/index.d.ts +2 -0
- package/lib/components/AttachmentDisplay/index.d.ts.map +1 -0
- package/lib/components/AttachmentInput/AttachmentInput.d.ts +179 -0
- package/lib/components/AttachmentInput/AttachmentInput.d.ts.map +1 -0
- package/lib/components/AttachmentInput/AttachmentInput.jsx +520 -0
- package/lib/components/AttachmentInput/index.d.ts +2 -0
- package/lib/components/AttachmentInput/index.d.ts.map +1 -0
- package/lib/components/BottomSheet/BottomSheet.d.ts +1 -1
- package/lib/components/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/lib/components/BottomSheet/BottomSheet.jsx +1 -7
- package/lib/components/Box/Box.d.ts +3 -3
- package/lib/components/Box/Box.d.ts.map +1 -1
- package/lib/components/Callout/Callout.jsx +2 -2
- package/lib/components/Checkbox/Checkbox.jsx +2 -2
- package/lib/components/Chip/Chip.jsx +2 -2
- package/lib/components/ChipTabs/ChipTabs.d.ts +41 -0
- package/lib/components/ChipTabs/ChipTabs.d.ts.map +1 -0
- package/lib/components/ChipTabs/ChipTabs.jsx +39 -0
- package/lib/components/ChipTabs/ChipTabs.namespace.d.ts +2 -0
- package/lib/components/ChipTabs/ChipTabs.namespace.d.ts.map +1 -0
- package/lib/components/ChipTabs/ChipTabs.namespace.js +13 -0
- package/lib/components/ChipTabs/index.d.ts +3 -0
- package/lib/components/ChipTabs/index.d.ts.map +1 -0
- package/lib/components/ContextualFloatingButton/ContextualFloatingButton.d.ts +18 -0
- package/lib/components/ContextualFloatingButton/ContextualFloatingButton.d.ts.map +1 -0
- package/lib/components/ContextualFloatingButton/ContextualFloatingButton.jsx +113 -0
- package/lib/components/ContextualFloatingButton/index.d.ts +2 -0
- package/lib/components/ContextualFloatingButton/index.d.ts.map +1 -0
- package/lib/components/Dialog/Dialog.d.ts +87 -0
- package/lib/components/Dialog/Dialog.d.ts.map +1 -0
- package/lib/components/Dialog/Dialog.jsx +147 -0
- package/lib/components/Dialog/Dialog.namespace.d.ts +2 -0
- package/lib/components/Dialog/Dialog.namespace.d.ts.map +1 -0
- package/lib/components/Dialog/Dialog.namespace.js +18 -0
- package/lib/components/Dialog/index.d.ts +3 -0
- package/lib/components/Dialog/index.d.ts.map +1 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.d.ts +23 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.d.ts.map +1 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.jsx +76 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.namespace.d.ts +2 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.namespace.d.ts.map +1 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.namespace.js +10 -0
- package/lib/components/FloatingActionButton/index.d.ts +3 -0
- package/lib/components/FloatingActionButton/index.d.ts.map +1 -0
- package/lib/components/HelpBubble/HelpBubble.d.ts +67 -0
- package/lib/components/HelpBubble/HelpBubble.d.ts.map +1 -0
- package/lib/components/HelpBubble/HelpBubble.jsx +600 -0
- package/lib/components/HelpBubble/HelpBubble.namespace.d.ts +2 -0
- package/lib/components/HelpBubble/HelpBubble.namespace.d.ts.map +1 -0
- package/lib/components/HelpBubble/HelpBubble.namespace.js +18 -0
- package/lib/components/HelpBubble/index.d.ts +3 -0
- package/lib/components/HelpBubble/index.d.ts.map +1 -0
- package/lib/components/Icon/Icon.d.ts +1 -0
- package/lib/components/Icon/Icon.d.ts.map +1 -1
- package/lib/components/Icon/Icon.jsx +2 -1
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.d.ts +28 -0
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.d.ts.map +1 -0
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.jsx +37 -0
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.d.ts +2 -0
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.d.ts.map +1 -0
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.js +9 -0
- package/lib/components/IdentityPlaceholder/identity-placeholder-business.js +4 -0
- package/lib/components/IdentityPlaceholder/identity-placeholder-person.js +4 -0
- package/lib/components/IdentityPlaceholder/index.d.ts +3 -0
- package/lib/components/IdentityPlaceholder/index.d.ts.map +1 -0
- package/lib/components/InputButton/InputButton.d.ts +2 -0
- package/lib/components/InputButton/InputButton.d.ts.map +1 -1
- package/lib/components/InputButton/InputButton.jsx +40 -8
- package/lib/components/List/List.d.ts +1 -1
- package/lib/components/List/List.d.ts.map +1 -1
- package/lib/components/List/List.jsx +26 -12
- package/lib/components/Menu/Menu.d.ts.map +1 -1
- package/lib/components/Menu/Menu.jsx +15 -5
- package/lib/components/PageBanner/PageBanner.d.ts +3 -0
- package/lib/components/PageBanner/PageBanner.d.ts.map +1 -1
- package/lib/components/PageBanner/PageBanner.jsx +49 -11
- package/lib/components/QuantityPicker/QuantityPicker.d.ts +53 -0
- package/lib/components/QuantityPicker/QuantityPicker.d.ts.map +1 -0
- package/lib/components/QuantityPicker/QuantityPicker.jsx +282 -0
- package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts +2 -0
- package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts.map +1 -0
- package/lib/components/QuantityPicker/QuantityPicker.namespace.js +11 -0
- package/lib/components/QuantityPicker/index.d.ts +3 -0
- package/lib/components/QuantityPicker/index.d.ts.map +1 -0
- package/lib/components/RadioGroup/RadioGroup.jsx +2 -2
- package/lib/components/ReactionButton/ReactionButton.d.ts +1 -1
- package/lib/components/ReactionButton/ReactionButton.d.ts.map +1 -1
- package/lib/components/ReactionButton/ReactionButton.jsx +22 -13
- package/lib/components/ScrollFog/ScrollFog.d.ts +41 -0
- package/lib/components/ScrollFog/ScrollFog.d.ts.map +1 -0
- package/lib/components/ScrollFog/ScrollFog.jsx +65 -0
- package/lib/components/ScrollFog/index.d.ts +2 -0
- package/lib/components/ScrollFog/index.d.ts.map +1 -0
- package/lib/components/SegmentedControl/SegmentedControl.jsx +2 -2
- package/lib/components/Select/Select.d.ts +112 -0
- package/lib/components/Select/Select.d.ts.map +1 -0
- package/lib/components/Select/Select.jsx +885 -0
- package/lib/components/Select/Select.namespace.d.ts +2 -0
- package/lib/components/Select/Select.namespace.d.ts.map +1 -0
- package/lib/components/Select/Select.namespace.js +23 -0
- package/lib/components/Select/index.d.ts +3 -0
- package/lib/components/Select/index.d.ts.map +1 -0
- package/lib/components/Skeleton/Skeleton.d.ts +15 -0
- package/lib/components/Skeleton/Skeleton.d.ts.map +1 -0
- package/lib/components/Skeleton/Skeleton.jsx +18 -0
- package/lib/components/Skeleton/index.d.ts +2 -0
- package/lib/components/Skeleton/index.d.ts.map +1 -0
- package/lib/components/Slider/Slider.d.ts +101 -0
- package/lib/components/Slider/Slider.d.ts.map +1 -0
- package/lib/components/Slider/Slider.jsx +573 -0
- package/lib/components/Slider/Slider.namespace.d.ts +2 -0
- package/lib/components/Slider/Slider.namespace.d.ts.map +1 -0
- package/lib/components/Slider/Slider.namespace.js +19 -0
- package/lib/components/Slider/Slider.utils.d.ts +19 -0
- package/lib/components/Slider/Slider.utils.d.ts.map +1 -0
- package/lib/components/Slider/Slider.utils.js +106 -0
- package/lib/components/Slider/index.d.ts +3 -0
- package/lib/components/Slider/index.d.ts.map +1 -0
- package/lib/components/Stack/Stack.d.ts +7 -9
- package/lib/components/Stack/Stack.d.ts.map +1 -1
- package/lib/components/SwipeableMenuSheet/SwipeableMenuSheet.d.ts.map +1 -1
- package/lib/components/SwipeableMenuSheet/SwipeableMenuSheet.jsx +22 -8
- package/lib/components/Switch/Switch.d.ts.map +1 -1
- package/lib/components/Switch/Switch.jsx +5 -3
- package/lib/components/Tabs/Tabs.d.ts +34 -2
- package/lib/components/Tabs/Tabs.d.ts.map +1 -1
- package/lib/components/Tabs/Tabs.jsx +186 -56
- package/lib/components/Tabs/Tabs.utils.d.ts +14 -1
- package/lib/components/Tabs/Tabs.utils.d.ts.map +1 -1
- package/lib/components/Tabs/Tabs.utils.js +24 -3
- package/lib/components/Tabs/index.d.ts +1 -1
- package/lib/components/Tabs/index.d.ts.map +1 -1
- package/lib/components/index.d.ts +14 -0
- package/lib/components/index.d.ts.map +1 -1
- package/lib/hooks/useControllableState.d.ts +1 -14
- package/lib/hooks/useControllableState.d.ts.map +1 -1
- package/lib/hooks/usePressTap.d.ts +1 -27
- package/lib/hooks/usePressTap.d.ts.map +1 -1
- package/lib/hooks/useSafeArea.d.ts +8 -4
- package/lib/hooks/useSafeArea.d.ts.map +1 -1
- package/lib/hooks/useSafeArea.js +22 -20
- package/lib/index.js +29 -6
- package/lib/{hooks/useControllableState.js → packages/lynx-react-headless/use-controllable-state/lib/index.js} +2 -3
- package/lib/{hooks/usePressTap.js → packages/lynx-react-headless/use-press-tap/lib/index.js} +13 -10
- package/lib/types.d.ts +1 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/utils/styled.d.ts +46 -6
- package/lib/utils/styled.d.ts.map +1 -1
- package/lib/utils/styled.js +19 -4
- package/package.json +9 -5
- package/src/components/AlertDialog/AlertDialog.namespace.ts +22 -0
- package/src/components/AlertDialog/AlertDialog.test.tsx +226 -0
- package/src/components/AlertDialog/AlertDialog.tsx +374 -0
- package/src/components/AlertDialog/index.ts +24 -0
- package/src/components/AppBar/AppBar.namespace.ts +1 -0
- package/src/components/AppBar/AppBar.test.tsx +252 -3
- package/src/components/AppBar/AppBar.tsx +108 -25
- package/src/components/AppBar/context.ts +3 -1
- package/src/components/AppBar/index.ts +1 -0
- package/src/components/AppBar/useAppBar.ts +21 -15
- package/src/components/AttachmentDisplay/AttachmentDisplay.tsx +886 -0
- package/src/components/AttachmentDisplay/index.ts +48 -0
- package/src/components/AttachmentInput/AttachmentInput.tsx +1001 -0
- package/src/components/AttachmentInput/index.ts +49 -0
- package/src/components/BottomSheet/BottomSheet.test.tsx +22 -7
- package/src/components/BottomSheet/BottomSheet.tsx +1 -19
- package/src/components/Box/Box.test.tsx +104 -0
- package/src/components/Box/Box.tsx +9 -6
- package/src/components/ChipTabs/ChipTabs.namespace.ts +14 -0
- package/src/components/ChipTabs/ChipTabs.tsx +119 -0
- package/src/components/ChipTabs/index.ts +16 -0
- package/src/components/ContextualFloatingButton/ContextualFloatingButton.test.tsx +63 -0
- package/src/components/ContextualFloatingButton/ContextualFloatingButton.tsx +232 -0
- package/src/components/ContextualFloatingButton/index.ts +4 -0
- package/src/components/Dialog/Dialog.namespace.ts +24 -0
- package/src/components/Dialog/Dialog.test.tsx +172 -0
- package/src/components/Dialog/Dialog.tsx +373 -0
- package/src/components/Dialog/index.ts +26 -0
- package/src/components/FloatingActionButton/FloatingActionButton.namespace.ts +8 -0
- package/src/components/FloatingActionButton/FloatingActionButton.test.tsx +59 -0
- package/src/components/FloatingActionButton/FloatingActionButton.tsx +207 -0
- package/src/components/FloatingActionButton/index.ts +10 -0
- package/src/components/HelpBubble/HelpBubble.namespace.ts +24 -0
- package/src/components/HelpBubble/HelpBubble.tsx +998 -0
- package/src/components/HelpBubble/index.ts +26 -0
- package/src/components/Icon/Icon.test.tsx +0 -3
- package/src/components/Icon/Icon.tsx +11 -1
- package/src/components/IdentityPlaceholder/IdentityPlaceholder.namespace.ts +6 -0
- package/src/components/IdentityPlaceholder/IdentityPlaceholder.tsx +103 -0
- package/src/components/IdentityPlaceholder/assets.d.ts +4 -0
- package/src/components/IdentityPlaceholder/identity-placeholder-business.webp +0 -0
- package/src/components/IdentityPlaceholder/identity-placeholder-person.webp +0 -0
- package/src/components/IdentityPlaceholder/index.ts +8 -0
- package/src/components/InputButton/InputButton.test.tsx +128 -1
- package/src/components/InputButton/InputButton.tsx +60 -9
- package/src/components/List/List.test.tsx +54 -2
- package/src/components/List/List.tsx +43 -10
- package/src/components/Menu/Menu.tsx +14 -4
- package/src/components/Menu/__tests__/Menu.test.tsx +34 -0
- package/src/components/PageBanner/PageBanner.test.tsx +110 -3
- package/src/components/PageBanner/PageBanner.tsx +83 -19
- package/src/components/QuantityPicker/QuantityPicker.namespace.ts +10 -0
- package/src/components/QuantityPicker/QuantityPicker.test.tsx +235 -0
- package/src/components/QuantityPicker/QuantityPicker.tsx +605 -0
- package/src/components/QuantityPicker/index.ts +14 -0
- package/src/components/ReactionButton/ReactionButton.feedback.test.tsx +50 -0
- package/src/components/ReactionButton/ReactionButton.test.tsx +5 -3
- package/src/components/ReactionButton/ReactionButton.tsx +20 -12
- package/src/components/ScrollFog/ScrollFog.test.tsx +222 -0
- package/src/components/ScrollFog/ScrollFog.tsx +172 -0
- package/src/components/ScrollFog/index.ts +1 -0
- package/src/components/Select/Select.namespace.ts +34 -0
- package/src/components/Select/Select.test.tsx +297 -0
- package/src/components/Select/Select.tsx +1483 -0
- package/src/components/Select/index.ts +39 -0
- package/src/components/Skeleton/Skeleton.test.tsx +64 -0
- package/src/components/Skeleton/Skeleton.tsx +45 -0
- package/src/components/Skeleton/index.ts +1 -0
- package/src/components/Slider/Slider.namespace.ts +26 -0
- package/src/components/Slider/Slider.test.tsx +260 -0
- package/src/components/Slider/Slider.tsx +897 -0
- package/src/components/Slider/Slider.utils.ts +167 -0
- package/src/components/Slider/index.ts +30 -0
- package/src/components/Stack/Stack.test.tsx +7 -0
- package/src/components/Stack/Stack.tsx +11 -10
- package/src/components/SwipeableMenuSheet/SwipeableMenuSheet.test.tsx +21 -1
- package/src/components/SwipeableMenuSheet/SwipeableMenuSheet.tsx +30 -7
- package/src/components/Switch/Switch.tsx +14 -13
- package/src/components/Tabs/Tabs.test.tsx +218 -1
- package/src/components/Tabs/Tabs.tsx +346 -75
- package/src/components/Tabs/Tabs.utils.ts +51 -1
- package/src/components/Tabs/index.ts +17 -1
- package/src/components/index.ts +14 -0
- package/src/hooks/useControllableState.ts +1 -43
- package/src/hooks/usePressTap.test.ts +23 -11
- package/src/hooks/usePressTap.ts +1 -60
- package/src/hooks/useSafeArea.test.ts +13 -1
- package/src/hooks/useSafeArea.ts +25 -23
- package/src/types.ts +1 -0
- package/src/utils/styled.ts +127 -9
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
export interface SliderGeometry {
|
|
2
|
+
left: number;
|
|
3
|
+
width: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function clamp(value: number, min: number, max: number): number {
|
|
7
|
+
return Math.min(max, Math.max(min, value));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function percentageForValue(value: number, min: number, max: number): number {
|
|
11
|
+
if (max === min) return 0;
|
|
12
|
+
return clamp(((value - min) / (max - min)) * 100, 0, 100);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function valueForPercentage(
|
|
16
|
+
percent: number,
|
|
17
|
+
min: number,
|
|
18
|
+
max: number,
|
|
19
|
+
dir: "ltr" | "rtl",
|
|
20
|
+
): number {
|
|
21
|
+
const ratio = clamp(percent, 0, 100) / 100;
|
|
22
|
+
return dir === "rtl" ? max - ratio * (max - min) : min + ratio * (max - min);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function decimalCount(value: number): number {
|
|
26
|
+
const text = String(value);
|
|
27
|
+
const exponent = text.toLowerCase().split("e");
|
|
28
|
+
const fraction = exponent[0].split(".")[1]?.length ?? 0;
|
|
29
|
+
return fraction + (exponent[1] ? Math.max(0, -Number(exponent[1])) : 0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function roundValue(value: number, decimals: number): number {
|
|
33
|
+
const factor = 10 ** decimals;
|
|
34
|
+
return Math.round(value * factor) / factor;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function closestAllowedValue(value: number, allowedValues: readonly number[]): number {
|
|
38
|
+
if (allowedValues.length === 0) return value;
|
|
39
|
+
let closest = allowedValues[0];
|
|
40
|
+
let distance = Math.abs(value - closest);
|
|
41
|
+
for (let index = 1; index < allowedValues.length; index += 1) {
|
|
42
|
+
const candidate = allowedValues[index];
|
|
43
|
+
const candidateDistance = Math.abs(value - candidate);
|
|
44
|
+
if (candidateDistance < distance) {
|
|
45
|
+
closest = candidate;
|
|
46
|
+
distance = candidateDistance;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return closest;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function normalizeValue(
|
|
53
|
+
value: number,
|
|
54
|
+
min: number,
|
|
55
|
+
max: number,
|
|
56
|
+
step: number,
|
|
57
|
+
allowedValues?: readonly number[],
|
|
58
|
+
): number {
|
|
59
|
+
const safeMin = Math.min(min, max);
|
|
60
|
+
const safeMax = Math.max(min, max);
|
|
61
|
+
const candidate = Number.isFinite(value) ? value : safeMin;
|
|
62
|
+
if (allowedValues && allowedValues.length > 0) {
|
|
63
|
+
return closestAllowedValue(candidate, allowedValues);
|
|
64
|
+
}
|
|
65
|
+
const safeStep = Number.isFinite(step) && step > 0 ? step : 1;
|
|
66
|
+
const decimals = Math.max(decimalCount(safeStep), decimalCount(safeMin));
|
|
67
|
+
return clamp(
|
|
68
|
+
roundValue(Math.round((candidate - safeMin) / safeStep) * safeStep + safeMin, decimals),
|
|
69
|
+
safeMin,
|
|
70
|
+
safeMax,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function normalizeValues(
|
|
75
|
+
values: readonly number[] | undefined,
|
|
76
|
+
min: number,
|
|
77
|
+
max: number,
|
|
78
|
+
step: number,
|
|
79
|
+
allowedValues?: readonly number[],
|
|
80
|
+
): number[] {
|
|
81
|
+
const source = values && values.length > 0 ? values : [(min + max) / 2];
|
|
82
|
+
return source
|
|
83
|
+
.map((value) => normalizeValue(value, min, max, step, allowedValues))
|
|
84
|
+
.sort((a, b) => a - b);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function nearestValueIndex(values: readonly number[], value: number): number {
|
|
88
|
+
if (values.length < 2) return 0;
|
|
89
|
+
let index = 0;
|
|
90
|
+
let distance = Math.abs(values[0] - value);
|
|
91
|
+
for (let candidate = 1; candidate < values.length; candidate += 1) {
|
|
92
|
+
const candidateDistance = Math.abs(values[candidate] - value);
|
|
93
|
+
if (candidateDistance < distance) {
|
|
94
|
+
index = candidate;
|
|
95
|
+
distance = candidateDistance;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return index;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function hasMinimumSteps(
|
|
102
|
+
values: readonly number[],
|
|
103
|
+
minimumSteps: number,
|
|
104
|
+
step: number,
|
|
105
|
+
): boolean {
|
|
106
|
+
if (minimumSteps <= 0 || values.length < 2) return true;
|
|
107
|
+
const safeStep = Number.isFinite(step) && step > 0 ? step : 1;
|
|
108
|
+
const decimals = decimalCount(safeStep);
|
|
109
|
+
const required = roundValue(minimumSteps * safeStep, decimals);
|
|
110
|
+
for (let index = 1; index < values.length; index += 1) {
|
|
111
|
+
const difference = roundValue(values[index] - values[index - 1], decimals);
|
|
112
|
+
if (difference < required) return false;
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function getThumbInBoundsOffset(width: number, percent: number, direction: 1 | -1): number {
|
|
118
|
+
if (!width) return 0;
|
|
119
|
+
const halfWidth = width / 2;
|
|
120
|
+
const scaledOffset = (clamp(percent, 0, 100) / 50) * halfWidth;
|
|
121
|
+
return (halfWidth - scaledOffset * direction) * direction;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function getStickyLabelOffset(
|
|
125
|
+
labelWidth: number,
|
|
126
|
+
percent: number,
|
|
127
|
+
thumbWidth: number,
|
|
128
|
+
trackWidth: number,
|
|
129
|
+
direction: 1 | -1,
|
|
130
|
+
): number {
|
|
131
|
+
if (!labelWidth || !trackWidth) return 0;
|
|
132
|
+
const thumbOffset = getThumbInBoundsOffset(thumbWidth, percent, direction);
|
|
133
|
+
const naturalCenter = (percent / 100) * trackWidth + thumbOffset;
|
|
134
|
+
const halfLabel = labelWidth / 2;
|
|
135
|
+
const center = clamp(naturalCenter, halfLabel, trackWidth - halfLabel);
|
|
136
|
+
return (center - (percent / 100) * trackWidth) * direction;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function eventPageX(event: unknown): number {
|
|
140
|
+
const target = event as {
|
|
141
|
+
touches?: Array<{ pageX?: unknown; clientX?: unknown }>;
|
|
142
|
+
changedTouches?: Array<{ pageX?: unknown; clientX?: unknown }>;
|
|
143
|
+
pageX?: unknown;
|
|
144
|
+
clientX?: unknown;
|
|
145
|
+
detail?: { x?: unknown };
|
|
146
|
+
} | null;
|
|
147
|
+
const touch = target?.touches?.[0] ?? target?.changedTouches?.[0];
|
|
148
|
+
const candidates = [
|
|
149
|
+
touch?.pageX,
|
|
150
|
+
touch?.clientX,
|
|
151
|
+
target?.pageX,
|
|
152
|
+
target?.clientX,
|
|
153
|
+
target?.detail?.x,
|
|
154
|
+
];
|
|
155
|
+
for (const candidate of candidates) {
|
|
156
|
+
const number = Number(candidate);
|
|
157
|
+
if (Number.isFinite(number)) return number;
|
|
158
|
+
}
|
|
159
|
+
return Number.NaN;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function geometryFromRect(value: unknown): SliderGeometry | null {
|
|
163
|
+
const rect = value as { left?: unknown; width?: unknown } | null | undefined;
|
|
164
|
+
const left = Number(rect?.left);
|
|
165
|
+
const width = Number(rect?.width);
|
|
166
|
+
return Number.isFinite(left) && Number.isFinite(width) && width > 0 ? { left, width } : null;
|
|
167
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export {
|
|
2
|
+
SliderRoot,
|
|
3
|
+
SliderControl,
|
|
4
|
+
SliderTrack,
|
|
5
|
+
SliderRange,
|
|
6
|
+
SliderThumb,
|
|
7
|
+
SliderTick,
|
|
8
|
+
SliderMarkers,
|
|
9
|
+
SliderMarker,
|
|
10
|
+
SliderValueIndicatorRoot,
|
|
11
|
+
SliderValueIndicatorArrow,
|
|
12
|
+
SliderValueIndicatorArrowTip,
|
|
13
|
+
SliderValueIndicatorLabel,
|
|
14
|
+
type SliderClassNames,
|
|
15
|
+
type SliderValues,
|
|
16
|
+
type SliderRootProps,
|
|
17
|
+
type SliderControlProps,
|
|
18
|
+
type SliderTrackProps,
|
|
19
|
+
type SliderRangeProps,
|
|
20
|
+
type SliderThumbProps,
|
|
21
|
+
type SliderTickProps,
|
|
22
|
+
type SliderMarkersProps,
|
|
23
|
+
type SliderMarkerProps,
|
|
24
|
+
type SliderValueIndicatorRootProps,
|
|
25
|
+
type SliderValueIndicatorArrowProps,
|
|
26
|
+
type SliderValueIndicatorArrowTipProps,
|
|
27
|
+
type SliderValueIndicatorLabelProps,
|
|
28
|
+
} from "./Slider";
|
|
29
|
+
|
|
30
|
+
export * as Slider from "./Slider.namespace";
|
|
@@ -64,4 +64,11 @@ describe("Stack", () => {
|
|
|
64
64
|
|
|
65
65
|
expect(getRenderedRoot()).toHaveStyle({ rowGap: "24px" });
|
|
66
66
|
});
|
|
67
|
+
|
|
68
|
+
it("applies bleed as a negative margin", () => {
|
|
69
|
+
render(<HStack bleedX="16px" />);
|
|
70
|
+
|
|
71
|
+
expect(getRenderedRoot().style.getPropertyValue("margin-left")).toBe("calc(-16px)");
|
|
72
|
+
expect(getRenderedRoot().style.getPropertyValue("margin-right")).toBe("calc(-16px)");
|
|
73
|
+
});
|
|
67
74
|
});
|
|
@@ -2,7 +2,7 @@ import clsx from "clsx";
|
|
|
2
2
|
import * as React from "@lynx-js/react";
|
|
3
3
|
|
|
4
4
|
import type { LynxPressableProps, LynxStyledElementProps, LynxViewRef } from "../../types";
|
|
5
|
-
import { useStyleProps, type StyleProps } from "../../utils/styled";
|
|
5
|
+
import { useStyleProps, type MarginBleedStyleProps, type StyleProps } from "../../utils/styled";
|
|
6
6
|
import { mergeProps } from "../../utils/merge-props";
|
|
7
7
|
|
|
8
8
|
type StackStyleProps =
|
|
@@ -29,17 +29,18 @@ interface StackBaseProps extends StyleProps, LynxStyledElementProps, LynxPressab
|
|
|
29
29
|
* 패키지 컴포넌트 내부에서는 `Box`를 합성하지 않고 native tag와 recipe className을
|
|
30
30
|
* 사용해 primitive 컴포넌트 비용이 누적되지 않도록 합니다.
|
|
31
31
|
*/
|
|
32
|
-
export
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
export type StackProps = Omit<StackBaseProps, StackStyleProps> &
|
|
33
|
+
MarginBleedStyleProps & {
|
|
34
|
+
align?: StackBaseProps["alignItems"];
|
|
35
|
+
justify?: StackBaseProps["justifyContent"];
|
|
36
|
+
wrap?: StackBaseProps["flexWrap"];
|
|
37
|
+
grow?: StackBaseProps["flexGrow"];
|
|
38
|
+
shrink?: StackBaseProps["flexShrink"];
|
|
39
|
+
};
|
|
39
40
|
|
|
40
|
-
export
|
|
41
|
+
export type VStackProps = StackProps;
|
|
41
42
|
|
|
42
|
-
export
|
|
43
|
+
export type HStackProps = StackProps;
|
|
43
44
|
|
|
44
45
|
function getStackProps(props: StackProps) {
|
|
45
46
|
const { align, justify, wrap, grow, shrink, ...restProps } = props;
|
|
@@ -223,7 +223,9 @@ describe("SwipeableMenuSheet", () => {
|
|
|
223
223
|
(getByText("Second item") as HTMLElement).parentElement?.parentElement?.className,
|
|
224
224
|
).toContain("labelAlign_center");
|
|
225
225
|
|
|
226
|
-
const item = (getByText("First item") as HTMLElement).
|
|
226
|
+
const item = (getByText("First item") as HTMLElement).closest<HTMLElement>(
|
|
227
|
+
".seed-menu-sheet-item__root",
|
|
228
|
+
);
|
|
227
229
|
if (!item) throw new Error("Expected menu sheet item.");
|
|
228
230
|
fireEvent.tap(item);
|
|
229
231
|
|
|
@@ -255,4 +257,22 @@ describe("SwipeableMenuSheet", () => {
|
|
|
255
257
|
exitAnimation: { type: "tween", duration: 0 },
|
|
256
258
|
});
|
|
257
259
|
});
|
|
260
|
+
it("keeps item backgrounds outside the scale target and scales the whole close button", () => {
|
|
261
|
+
const { getByText } = render(
|
|
262
|
+
<SwipeableMenuSheet.Root>
|
|
263
|
+
<SwipeableMenuSheet.Item>
|
|
264
|
+
<SwipeableMenuSheet.ItemLabel>Choice</SwipeableMenuSheet.ItemLabel>
|
|
265
|
+
</SwipeableMenuSheet.Item>
|
|
266
|
+
<SwipeableMenuSheet.CloseButton>Close feedback</SwipeableMenuSheet.CloseButton>
|
|
267
|
+
</SwipeableMenuSheet.Root>,
|
|
268
|
+
);
|
|
269
|
+
const target = (getByText("Choice") as HTMLElement).parentElement!;
|
|
270
|
+
expect(target.classList.contains("seed-menu-sheet-item__scaleContent")).toBe(true);
|
|
271
|
+
expect(target.getAttribute("flatten")).toBe("false");
|
|
272
|
+
expect(target.parentElement!.classList.contains("seed-menu-sheet-item__root")).toBe(true);
|
|
273
|
+
expect(target.parentElement!.hasAttribute("flatten")).toBe(false);
|
|
274
|
+
const close = (getByText("Close feedback") as HTMLElement).parentElement!;
|
|
275
|
+
expect(close.classList.contains("seed-menu-sheet__closeButton")).toBe(true);
|
|
276
|
+
expect(close.getAttribute("flatten")).toBe("false");
|
|
277
|
+
});
|
|
258
278
|
});
|
|
@@ -7,6 +7,8 @@ import { forwardRef, isValidElement } from "@lynx-js/react";
|
|
|
7
7
|
import type { ForwardRefExoticComponent, PropsWithoutRef, RefAttributes } from "@lynx-js/react";
|
|
8
8
|
import clsx from "clsx";
|
|
9
9
|
|
|
10
|
+
import { useScaleFeedback } from "../../hooks/useScaleFeedback";
|
|
11
|
+
import { mergeProps } from "../../utils/merge-props";
|
|
10
12
|
import { usePressTap } from "../../hooks/usePressTap";
|
|
11
13
|
import { useSafeArea } from "../../hooks/useSafeArea";
|
|
12
14
|
import type {
|
|
@@ -54,6 +56,7 @@ interface SwipeableMenuSheetClassNames {
|
|
|
54
56
|
|
|
55
57
|
interface SwipeableMenuSheetItemClassNames {
|
|
56
58
|
root: string;
|
|
59
|
+
scaleContent: string;
|
|
57
60
|
content: string;
|
|
58
61
|
label: string;
|
|
59
62
|
description: string;
|
|
@@ -457,6 +460,7 @@ export const SwipeableMenuSheetCloseButton: LynxForwardRefComponent<
|
|
|
457
460
|
"accessibility-actions": accessibilityActions,
|
|
458
461
|
"accessibility-exclusive-focus": accessibilityExclusiveFocus,
|
|
459
462
|
"ios-platform-accessibility-id": iosPlatformAccessibilityId,
|
|
463
|
+
...nativeProps
|
|
460
464
|
} = props;
|
|
461
465
|
const { rootRef, setPendingReason, skipAnimation } = useSwipeableMenuSheetContext();
|
|
462
466
|
const handleTap = React.useCallback<NonNullable<LynxPressableProps["bindtap"]>>(
|
|
@@ -467,16 +471,26 @@ export const SwipeableMenuSheetCloseButton: LynxForwardRefComponent<
|
|
|
467
471
|
},
|
|
468
472
|
[rootRef, setPendingReason, skipAnimation, userBindtap],
|
|
469
473
|
);
|
|
470
|
-
const { pressed, ...pressHandlers } = usePressTap({
|
|
474
|
+
const { pressed, bindtouchstart, bindtouchend, bindtouchcancel, ...pressHandlers } = usePressTap({
|
|
471
475
|
onTap: handleTap,
|
|
472
476
|
mainThreadOnTap: userMainThreadBindtap,
|
|
473
477
|
});
|
|
478
|
+
const { scaleFeedbackTriggerProps, scaleFeedbackTargetProps } = useScaleFeedback({
|
|
479
|
+
onTouchStart: bindtouchstart,
|
|
480
|
+
onTouchEnd: bindtouchend,
|
|
481
|
+
onTouchCancel: bindtouchcancel,
|
|
482
|
+
});
|
|
474
483
|
const classNames = menuSheet({ skipAnimation, closeButtonPressed: pressed });
|
|
475
484
|
|
|
476
485
|
return (
|
|
477
486
|
<view
|
|
478
487
|
{...(ref ? ({ ref: ref as LynxViewRef } as Record<string, unknown>) : {})}
|
|
479
|
-
{...
|
|
488
|
+
{...mergeProps(
|
|
489
|
+
scaleFeedbackTriggerProps,
|
|
490
|
+
scaleFeedbackTargetProps,
|
|
491
|
+
pressHandlers,
|
|
492
|
+
nativeProps,
|
|
493
|
+
)}
|
|
480
494
|
className={clsx(classNames.closeButton, className)}
|
|
481
495
|
style={style as never}
|
|
482
496
|
accessibility-element={accessibilityElement}
|
|
@@ -541,14 +555,21 @@ export const SwipeableMenuSheetItem: LynxForwardRefComponent<unknown, SwipeableM
|
|
|
541
555
|
"accessibility-actions": accessibilityActions,
|
|
542
556
|
"accessibility-exclusive-focus": accessibilityExclusiveFocus,
|
|
543
557
|
"ios-platform-accessibility-id": iosPlatformAccessibilityId,
|
|
558
|
+
...nativeProps
|
|
544
559
|
} = props;
|
|
545
560
|
const groupLabelAlign = React.useContext(GroupLabelAlignContext);
|
|
546
561
|
const contentLabelAlign = React.useContext(ContentLabelAlignContext);
|
|
547
562
|
const { isLast } = React.useContext(SwipeableMenuSheetItemPositionContext);
|
|
548
563
|
const resolvedLabelAlign = labelAlign ?? groupLabelAlign ?? contentLabelAlign ?? "left";
|
|
549
|
-
const { pressed, ...pressHandlers } =
|
|
550
|
-
|
|
551
|
-
|
|
564
|
+
const { pressed, bindtouchstart, bindtouchend, bindtouchcancel, ...pressHandlers } =
|
|
565
|
+
usePressTap({
|
|
566
|
+
onTap: userBindtap,
|
|
567
|
+
mainThreadOnTap: userMainThreadBindtap,
|
|
568
|
+
});
|
|
569
|
+
const { scaleFeedbackTriggerProps, scaleFeedbackTargetProps } = useScaleFeedback({
|
|
570
|
+
onTouchStart: bindtouchstart,
|
|
571
|
+
onTouchEnd: bindtouchend,
|
|
572
|
+
onTouchCancel: bindtouchcancel,
|
|
552
573
|
});
|
|
553
574
|
const classNames = menuSheetItem({ tone, labelAlign: resolvedLabelAlign, pressed });
|
|
554
575
|
const itemContext = React.useMemo<SwipeableMenuSheetItemContextValue>(
|
|
@@ -566,7 +587,7 @@ export const SwipeableMenuSheetItem: LynxForwardRefComponent<unknown, SwipeableM
|
|
|
566
587
|
>
|
|
567
588
|
<view
|
|
568
589
|
{...(ref ? ({ ref: ref as LynxViewRef } as Record<string, unknown>) : {})}
|
|
569
|
-
{...pressHandlers}
|
|
590
|
+
{...mergeProps(scaleFeedbackTriggerProps, pressHandlers, nativeProps)}
|
|
570
591
|
className={clsx(classNames.root, className)}
|
|
571
592
|
style={style as never}
|
|
572
593
|
accessibility-element={accessibilityElement}
|
|
@@ -580,7 +601,9 @@ export const SwipeableMenuSheetItem: LynxForwardRefComponent<unknown, SwipeableM
|
|
|
580
601
|
accessibility-exclusive-focus={accessibilityExclusiveFocus}
|
|
581
602
|
ios-platform-accessibility-id={iosPlatformAccessibilityId}
|
|
582
603
|
>
|
|
583
|
-
{
|
|
604
|
+
<view className={classNames.scaleContent} {...scaleFeedbackTargetProps}>
|
|
605
|
+
{children}
|
|
606
|
+
</view>
|
|
584
607
|
</view>
|
|
585
608
|
{!isLast ? (
|
|
586
609
|
<view className={classNames.divider} accessibility-elements-hidden={true} />
|
|
@@ -15,11 +15,9 @@ import type {
|
|
|
15
15
|
LynxTextRef,
|
|
16
16
|
LynxViewRef,
|
|
17
17
|
} from "../../types";
|
|
18
|
-
import {
|
|
19
|
-
useScaleFeedback,
|
|
20
|
-
type ScaleFeedbackTargetProps,
|
|
21
|
-
} from "../../hooks/useScaleFeedback";
|
|
18
|
+
import { useScaleFeedback, type ScaleFeedbackTargetProps } from "../../hooks/useScaleFeedback";
|
|
22
19
|
import { mergeProps } from "../../utils/merge-props";
|
|
20
|
+
import { ScaleFeedbackContentContext } from "../../contexts";
|
|
23
21
|
|
|
24
22
|
/**
|
|
25
23
|
* @platform Lynx
|
|
@@ -110,13 +108,7 @@ export const SwitchRoot = React.forwardRef<unknown, SwitchRootProps>((props, ref
|
|
|
110
108
|
|
|
111
109
|
const toggle = React.useCallback(() => setChecked(!checked), [checked, setChecked]);
|
|
112
110
|
|
|
113
|
-
const {
|
|
114
|
-
pressed,
|
|
115
|
-
bindtouchstart,
|
|
116
|
-
bindtouchend,
|
|
117
|
-
bindtouchcancel,
|
|
118
|
-
...pressHandlers
|
|
119
|
-
} = usePressTap({
|
|
111
|
+
const { pressed, bindtouchstart, bindtouchend, bindtouchcancel, ...pressHandlers } = usePressTap({
|
|
120
112
|
disabled,
|
|
121
113
|
onTap: toggle,
|
|
122
114
|
});
|
|
@@ -139,7 +131,15 @@ export const SwitchRoot = React.forwardRef<unknown, SwitchRootProps>((props, ref
|
|
|
139
131
|
toggle,
|
|
140
132
|
scaleFeedbackTargetProps,
|
|
141
133
|
}),
|
|
142
|
-
[
|
|
134
|
+
[
|
|
135
|
+
checked,
|
|
136
|
+
disabled,
|
|
137
|
+
pressed,
|
|
138
|
+
switchVariantProps,
|
|
139
|
+
switchmarkVariantProps,
|
|
140
|
+
toggle,
|
|
141
|
+
scaleFeedbackTargetProps,
|
|
142
|
+
],
|
|
143
143
|
);
|
|
144
144
|
|
|
145
145
|
return (
|
|
@@ -175,6 +175,7 @@ export const SwitchControl = React.forwardRef<unknown, SwitchControlProps>((prop
|
|
|
175
175
|
const [variantProps, restProps] = switchmark.splitVariantProps(props);
|
|
176
176
|
const { children, className, ...nativeProps } = restProps;
|
|
177
177
|
const context = useSwitchContext("SwitchControl");
|
|
178
|
+
const hasScaledContent = React.useContext(ScaleFeedbackContentContext);
|
|
178
179
|
const switchmarkVariantProps: SwitchmarkVariantProps = {
|
|
179
180
|
...context.switchmarkVariantProps,
|
|
180
181
|
...variantProps,
|
|
@@ -190,7 +191,7 @@ export const SwitchControl = React.forwardRef<unknown, SwitchControlProps>((prop
|
|
|
190
191
|
<view
|
|
191
192
|
{...mergeProps(
|
|
192
193
|
ref ? { ref: ref as LynxViewRef } : {},
|
|
193
|
-
context.scaleFeedbackTargetProps,
|
|
194
|
+
!hasScaledContent ? context.scaleFeedbackTargetProps : {},
|
|
194
195
|
nativeProps,
|
|
195
196
|
)}
|
|
196
197
|
className={clsx(classes.root, className)}
|