@seed-design/lynx-react-scale-feedback 1.0.0 → 1.1.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.
@@ -0,0 +1,9 @@
1
+ import { type Context } from "@lynx-js/react";
2
+ /** 호스트가 선호하는 모션 강도. `"reduced"`이면 Scale Feedback을 끈다. */
3
+ export type PreferredMotion = "default" | "reduced";
4
+ /**
5
+ * @internal `@seed-design/lynx-react`의 `SeedProvider`가 `preferredMotion`을 넣는 context다.
6
+ * 앱은 `SeedProvider`로 값을 넘긴다.
7
+ */
8
+ export declare const PreferredMotionContext: Context<PreferredMotion | undefined>;
9
+ //# sourceMappingURL=PreferredMotionContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreferredMotionContext.d.ts","sourceRoot":"","sources":["../src/PreferredMotionContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE7D,yDAAyD;AACzD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,OAAO,CAAC,eAAe,GAAG,SAAS,CAE5D,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { createContext } from "@lynx-js/react";
2
+ /**
3
+ * @internal `@seed-design/lynx-react`의 `SeedProvider`가 `preferredMotion`을 넣는 context다.
4
+ * 앱은 `SeedProvider`로 값을 넘긴다.
5
+ */
6
+ export const PreferredMotionContext = createContext(undefined);
@@ -0,0 +1,4 @@
1
+ export declare function warnDeprecatedMotionGlobalProp(): void;
2
+ /** @internal 테스트용. */
3
+ export declare function resetDeprecatedMotionWarning(): void;
4
+ //# sourceMappingURL=deprecated-global-props.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deprecated-global-props.d.ts","sourceRoot":"","sources":["../src/deprecated-global-props.ts"],"names":[],"mappings":"AAGA,wBAAgB,8BAA8B,IAAI,IAAI,CAOrD;AAED,sBAAsB;AACtB,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD"}
@@ -0,0 +1,12 @@
1
+ let warned = false;
2
+ // TODO(next major): `motion` global prop 읽기를 제거한다. 앱은 `SeedProvider`에 `preferredMotion`을 넘긴다.
3
+ export function warnDeprecatedMotionGlobalProp() {
4
+ if (process.env.NODE_ENV === "production" || warned)
5
+ return;
6
+ warned = true;
7
+ console.warn("[@seed-design/lynx-react-scale-feedback] Reading `lynx.__globalProps.motion` is deprecated and will be removed in the next major version. Pass `preferredMotion` to `SeedProvider` instead.");
8
+ }
9
+ /** @internal 테스트용. */
10
+ export function resetDeprecatedMotionWarning() {
11
+ warned = false;
12
+ }
package/lib/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./PreferredMotionContext.js";
1
2
  export * from "./useScaleFeedback.js";
2
3
  export * from "./ScaleFeedback.jsx";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC"}
package/lib/index.js CHANGED
@@ -1,2 +1,3 @@
1
+ export * from "./PreferredMotionContext.js";
1
2
  export * from "./useScaleFeedback.js";
2
3
  export * from "./ScaleFeedback.jsx";
@@ -0,0 +1,12 @@
1
+ import type { GlobalProps } from "@lynx-js/types";
2
+ /**
3
+ * Reads global props according to `globalPropsMode`.
4
+ *
5
+ * `__GLOBAL_PROPS_MODE__` is a constant replaced at app build time, so the chosen function never
6
+ * changes within a bundle. In `"event"` mode, `useGlobalProps()` subscribes to changes. In
7
+ * `"reactive"` mode, the whole page re-renders when the host changes a value, so this reads
8
+ * `lynx.__globalProps` directly: `useGlobalProps()` returns the same value there but warns on every
9
+ * call in development builds.
10
+ */
11
+ export declare const useHostGlobalProps: () => GlobalProps | undefined;
12
+ //# sourceMappingURL=use-host-global-props.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-host-global-props.d.ts","sourceRoot":"","sources":["../src/use-host-global-props.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,WAAW,GAAG,SAGvB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { useGlobalProps } from "@lynx-js/react";
2
+ /**
3
+ * Reads global props according to `globalPropsMode`.
4
+ *
5
+ * `__GLOBAL_PROPS_MODE__` is a constant replaced at app build time, so the chosen function never
6
+ * changes within a bundle. In `"event"` mode, `useGlobalProps()` subscribes to changes. In
7
+ * `"reactive"` mode, the whole page re-renders when the host changes a value, so this reads
8
+ * `lynx.__globalProps` directly: `useGlobalProps()` returns the same value there but warns on every
9
+ * call in development builds.
10
+ */
11
+ export const useHostGlobalProps = typeof __GLOBAL_PROPS_MODE__ !== "undefined" && __GLOBAL_PROPS_MODE__ === "event"
12
+ ? useGlobalProps
13
+ : () => lynx.__globalProps;
@@ -40,9 +40,10 @@ export interface UseScaleFeedbackReturn {
40
40
  * The target's transform is owned by this hook. Use a separate content layer
41
41
  * when the element already uses translate, rotate, or another transform.
42
42
  *
43
- * Supported on Lynx Engine 3.6 and later. Missing or unknown
44
- * `GlobalProps.motion` values preserve the default motion; only the exact
45
- * `"reduced"` value disables scaling.
43
+ * Supported on Lynx Engine 3.6 and later. `preferredMotion: "reduced"` on
44
+ * `SeedProvider` disables scaling. Without it, the deprecated
45
+ * `GlobalProps.motion` fallback is used; only the exact `"reduced"` value
46
+ * disables scaling.
46
47
  */
47
48
  export declare function useScaleFeedback(options?: UseScaleFeedbackOptions): UseScaleFeedbackReturn;
48
49
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"useScaleFeedback.d.ts","sourceRoot":"","sources":["../src/useScaleFeedback.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,iBAAiB,EAAc,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQ/E,KAAK,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;AAE3D,KAAK,6BAA6B,GAAG,WAAW,CAAC,aAAa,CAAC,8BAA8B,CAAC,CAAC,CAAC;AAChG,KAAK,sBAAsB,GAAG,WAAW,CAAC,aAAa,CAAC,4BAA4B,CAAC,CAAC,CAAC;AAUvF,MAAM,WAAW,uBAAuB;IACtC,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,yBAAyB;IACxC,4BAA4B,EAAE,sBAAsB,CAAC;IACrD,0BAA0B,EAAE,sBAAsB,CAAC;IACnD,6BAA6B,EAAE,sBAAsB,CAAC;CACvD;AAED,oGAAoG;AACpG,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,KAAK,CAAC;IACf,iBAAiB,EAAE,WAAW,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACjE,8BAA8B,EAAE,6BAA6B,CAAC;CAC/D;AAED,MAAM,WAAW,sBAAsB;IACrC,0DAA0D;IAC1D,yBAAyB,EAAE,yBAAyB,CAAC;IACrD,2DAA2D;IAC3D,wBAAwB,EAAE,wBAAwB,CAAC;CACpD;AAoDD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,sBAAsB,CAyE9F"}
1
+ {"version":3,"file":"useScaleFeedback.d.ts","sourceRoot":"","sources":["../src/useScaleFeedback.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,iBAAiB,EAAc,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAW/E,KAAK,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;AAE3D,KAAK,6BAA6B,GAAG,WAAW,CAAC,aAAa,CAAC,8BAA8B,CAAC,CAAC,CAAC;AAChG,KAAK,sBAAsB,GAAG,WAAW,CAAC,aAAa,CAAC,4BAA4B,CAAC,CAAC,CAAC;AAUvF,MAAM,WAAW,uBAAuB;IACtC,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,yBAAyB;IACxC,4BAA4B,EAAE,sBAAsB,CAAC;IACrD,0BAA0B,EAAE,sBAAsB,CAAC;IACnD,6BAA6B,EAAE,sBAAsB,CAAC;CACvD;AAED,oGAAoG;AACpG,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,KAAK,CAAC;IACf,iBAAiB,EAAE,WAAW,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACjE,8BAA8B,EAAE,6BAA6B,CAAC;CAC/D;AAED,MAAM,WAAW,sBAAsB;IACrC,0DAA0D;IAC1D,yBAAyB,EAAE,yBAAyB,CAAC;IACrD,2DAA2D;IAC3D,wBAAwB,EAAE,wBAAwB,CAAC;CACpD;AAyDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,sBAAsB,CA6E9F"}
@@ -1,6 +1,9 @@
1
- import { runOnMainThread, runOnBackground, useEffect, useGlobalProps, useMainThreadRef, useRef, } from "@lynx-js/react";
1
+ import { runOnMainThread, runOnBackground, useContext, useEffect, useMainThreadRef, useRef, } from "@lynx-js/react";
2
2
  import { feedbackScaleDuration, feedbackScaleTimingFunction, } from "@seed-design/lynx-css/scale-feedback";
3
3
  import { calculateScaleFeedback, isReducedMotion } from "./calculate-scale-feedback.js";
4
+ import { warnDeprecatedMotionGlobalProp } from "./deprecated-global-props.js";
5
+ import { PreferredMotionContext } from "./PreferredMotionContext.js";
6
+ import { useHostGlobalProps } from "./use-host-global-props.js";
4
7
  function runScaleFeedback(targetRef, animationRef, scale, duration) {
5
8
  "main thread";
6
9
  const target = targetRef.current;
@@ -39,6 +42,11 @@ function readScaleFeedbackScale(target) {
39
42
  return null;
40
43
  return calculateScaleFeedback(width, height);
41
44
  }
45
+ function readDeprecatedReducedMotion(motion) {
46
+ if (motion !== undefined)
47
+ warnDeprecatedMotionGlobalProp();
48
+ return isReducedMotion(motion);
49
+ }
42
50
  /**
43
51
  * Applies SEED Scale Feedback on the Lynx Main Thread.
44
52
  *
@@ -50,14 +58,18 @@ function readScaleFeedbackScale(target) {
50
58
  * The target's transform is owned by this hook. Use a separate content layer
51
59
  * when the element already uses translate, rotate, or another transform.
52
60
  *
53
- * Supported on Lynx Engine 3.6 and later. Missing or unknown
54
- * `GlobalProps.motion` values preserve the default motion; only the exact
55
- * `"reduced"` value disables scaling.
61
+ * Supported on Lynx Engine 3.6 and later. `preferredMotion: "reduced"` on
62
+ * `SeedProvider` disables scaling. Without it, the deprecated
63
+ * `GlobalProps.motion` fallback is used; only the exact `"reduced"` value
64
+ * disables scaling.
56
65
  */
57
66
  export function useScaleFeedback(options = {}) {
58
67
  const { disabled = false, onTouchStart, onTouchEnd, onTouchCancel } = options;
59
- const globalProps = useGlobalProps();
60
- const reducedMotion = isReducedMotion(globalProps?.motion);
68
+ const preferredMotion = useContext(PreferredMotionContext);
69
+ const globalProps = useHostGlobalProps();
70
+ const reducedMotion = preferredMotion !== undefined
71
+ ? preferredMotion === "reduced"
72
+ : readDeprecatedReducedMotion(globalProps?.motion);
61
73
  const targetRef = useMainThreadRef(null);
62
74
  const animationRef = useMainThreadRef(null);
63
75
  const scaleRef = useMainThreadRef(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seed-design/lynx-react-scale-feedback",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/daangn/seed-design.git",
@@ -31,16 +31,16 @@
31
31
  "peerDependencies": {
32
32
  "@lynx-js/react": ">=0.117.0",
33
33
  "@lynx-js/types": ">=3.9.0",
34
- "@seed-design/lynx-css": "^1.0.0"
34
+ "@seed-design/lynx-css": "^1.2.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@lynx-js/react": "^0.117.0",
38
38
  "@lynx-js/types": "^3.9.0",
39
- "@seed-design/lynx-css": "1.0.0",
39
+ "@seed-design/lynx-css": "1.2.0",
40
40
  "@seed-design/lynx-vitest-config": "0.0.0",
41
41
  "@testing-library/jest-dom": "^6.9.1",
42
42
  "jsdom": "^29.0.2",
43
- "vitest": "^3.2.4"
43
+ "vitest": "^5.0.0"
44
44
  },
45
45
  "publishConfig": {
46
46
  "access": "public"
@@ -0,0 +1,12 @@
1
+ import { createContext, type Context } from "@lynx-js/react";
2
+
3
+ /** 호스트가 선호하는 모션 강도. `"reduced"`이면 Scale Feedback을 끈다. */
4
+ export type PreferredMotion = "default" | "reduced";
5
+
6
+ /**
7
+ * @internal `@seed-design/lynx-react`의 `SeedProvider`가 `preferredMotion`을 넣는 context다.
8
+ * 앱은 `SeedProvider`로 값을 넘긴다.
9
+ */
10
+ export const PreferredMotionContext: Context<PreferredMotion | undefined> = createContext<
11
+ PreferredMotion | undefined
12
+ >(undefined);
@@ -0,0 +1,16 @@
1
+ let warned = false;
2
+
3
+ // TODO(next major): `motion` global prop 읽기를 제거한다. 앱은 `SeedProvider`에 `preferredMotion`을 넘긴다.
4
+ export function warnDeprecatedMotionGlobalProp(): void {
5
+ if (process.env.NODE_ENV === "production" || warned) return;
6
+
7
+ warned = true;
8
+ console.warn(
9
+ "[@seed-design/lynx-react-scale-feedback] Reading `lynx.__globalProps.motion` is deprecated and will be removed in the next major version. Pass `preferredMotion` to `SeedProvider` instead.",
10
+ );
11
+ }
12
+
13
+ /** @internal 테스트용. */
14
+ export function resetDeprecatedMotionWarning(): void {
15
+ warned = false;
16
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
+ export * from "./PreferredMotionContext.js";
1
2
  export * from "./useScaleFeedback.js";
2
3
  export * from "./ScaleFeedback.jsx";
@@ -0,0 +1,18 @@
1
+ import { useGlobalProps } from "@lynx-js/react";
2
+ import type { GlobalProps } from "@lynx-js/types";
3
+
4
+ declare const __GLOBAL_PROPS_MODE__: "reactive" | "event" | undefined;
5
+
6
+ /**
7
+ * Reads global props according to `globalPropsMode`.
8
+ *
9
+ * `__GLOBAL_PROPS_MODE__` is a constant replaced at app build time, so the chosen function never
10
+ * changes within a bundle. In `"event"` mode, `useGlobalProps()` subscribes to changes. In
11
+ * `"reactive"` mode, the whole page re-renders when the host changes a value, so this reads
12
+ * `lynx.__globalProps` directly: `useGlobalProps()` returns the same value there but warns on every
13
+ * call in development builds.
14
+ */
15
+ export const useHostGlobalProps: () => GlobalProps | undefined =
16
+ typeof __GLOBAL_PROPS_MODE__ !== "undefined" && __GLOBAL_PROPS_MODE__ === "event"
17
+ ? useGlobalProps
18
+ : () => lynx.__globalProps;
@@ -1,10 +1,33 @@
1
- import { runOnMainThread } from "@lynx-js/react";
1
+ import { createElement, runOnMainThread, type ReactNode } from "@lynx-js/react";
2
2
  import { renderHook, waitSchedule } from "@lynx-js/react/testing-library";
3
- import { describe, expect, expectTypeOf, it } from "vitest";
3
+ import { afterEach, describe, expect, expectTypeOf, it, vi } from "vitest";
4
4
 
5
5
  import { calculateScaleFeedback, isReducedMotion } from "./calculate-scale-feedback";
6
+ import { resetDeprecatedMotionWarning } from "./deprecated-global-props";
7
+ import { PreferredMotionContext } from "./PreferredMotionContext";
6
8
  import { useScaleFeedback, type UseScaleFeedbackOptions } from "./useScaleFeedback";
7
9
 
10
+ interface TestLynxGlobal {
11
+ lynx?: { __globalProps?: Record<string, unknown> };
12
+ lynxTestingEnv?: {
13
+ backgroundThread: { globalThis: TestLynxGlobal };
14
+ mainThread: { globalThis: TestLynxGlobal };
15
+ };
16
+ }
17
+
18
+ function setGlobalProps(globalProps: Record<string, unknown>) {
19
+ const env = (globalThis as unknown as TestLynxGlobal).lynxTestingEnv;
20
+ const globals = [
21
+ globalThis as unknown as TestLynxGlobal,
22
+ env?.backgroundThread.globalThis,
23
+ env?.mainThread.globalThis,
24
+ ].filter((global): global is TestLynxGlobal => Boolean(global));
25
+
26
+ for (const global of globals) {
27
+ global.lynx = { ...global.lynx, __globalProps: globalProps };
28
+ }
29
+ }
30
+
8
31
  describe("useScaleFeedback", () => {
9
32
  it("keeps the animation target from being flattened", () => {
10
33
  const { result } = renderHook(() => useScaleFeedback());
@@ -24,6 +47,37 @@ describe("useScaleFeedback", () => {
24
47
  });
25
48
  });
26
49
 
50
+ describe("useScaleFeedback deprecated motion global prop", () => {
51
+ afterEach(() => {
52
+ setGlobalProps({});
53
+ resetDeprecatedMotionWarning();
54
+ vi.restoreAllMocks();
55
+ });
56
+
57
+ it("warns once when it falls back to GlobalProps.motion", () => {
58
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
59
+ setGlobalProps({ motion: "reduced" });
60
+
61
+ renderHook(() => useScaleFeedback());
62
+ renderHook(() => useScaleFeedback());
63
+
64
+ expect(warn).toHaveBeenCalledTimes(1);
65
+ expect(warn.mock.calls[0]?.[0]).toContain("lynx.__globalProps.motion");
66
+ });
67
+
68
+ it("uses the provider value without reading GlobalProps.motion", () => {
69
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
70
+ setGlobalProps({ motion: "reduced" });
71
+
72
+ renderHook(() => useScaleFeedback(), {
73
+ wrapper: ({ children }: { children: ReactNode }) =>
74
+ createElement(PreferredMotionContext.Provider, { value: "default" }, children),
75
+ });
76
+
77
+ expect(warn).not.toHaveBeenCalled();
78
+ });
79
+ });
80
+
27
81
  describe("calculateScaleFeedback", () => {
28
82
  it.each([
29
83
  { width: 32, height: 32, expected: 30 / 32 },
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  runOnMainThread,
3
3
  runOnBackground,
4
+ useContext,
4
5
  useEffect,
5
- useGlobalProps,
6
6
  useMainThreadRef,
7
7
  useRef,
8
8
  } from "@lynx-js/react";
@@ -14,6 +14,9 @@ import {
14
14
  } from "@seed-design/lynx-css/scale-feedback";
15
15
 
16
16
  import { calculateScaleFeedback, isReducedMotion } from "./calculate-scale-feedback.js";
17
+ import { warnDeprecatedMotionGlobalProp } from "./deprecated-global-props.js";
18
+ import { PreferredMotionContext } from "./PreferredMotionContext.js";
19
+ import { useHostGlobalProps } from "./use-host-global-props.js";
17
20
 
18
21
  type LynxViewProps = IntrinsicElements["view"] & ViewProps;
19
22
 
@@ -109,6 +112,11 @@ function readScaleFeedbackScale(target: ScaleFeedbackElement | null): number | n
109
112
  return calculateScaleFeedback(width, height);
110
113
  }
111
114
 
115
+ function readDeprecatedReducedMotion(motion: unknown): boolean {
116
+ if (motion !== undefined) warnDeprecatedMotionGlobalProp();
117
+ return isReducedMotion(motion);
118
+ }
119
+
112
120
  /**
113
121
  * Applies SEED Scale Feedback on the Lynx Main Thread.
114
122
  *
@@ -120,14 +128,19 @@ function readScaleFeedbackScale(target: ScaleFeedbackElement | null): number | n
120
128
  * The target's transform is owned by this hook. Use a separate content layer
121
129
  * when the element already uses translate, rotate, or another transform.
122
130
  *
123
- * Supported on Lynx Engine 3.6 and later. Missing or unknown
124
- * `GlobalProps.motion` values preserve the default motion; only the exact
125
- * `"reduced"` value disables scaling.
131
+ * Supported on Lynx Engine 3.6 and later. `preferredMotion: "reduced"` on
132
+ * `SeedProvider` disables scaling. Without it, the deprecated
133
+ * `GlobalProps.motion` fallback is used; only the exact `"reduced"` value
134
+ * disables scaling.
126
135
  */
127
136
  export function useScaleFeedback(options: UseScaleFeedbackOptions = {}): UseScaleFeedbackReturn {
128
137
  const { disabled = false, onTouchStart, onTouchEnd, onTouchCancel } = options;
129
- const globalProps = useGlobalProps() as SeedMotionGlobalProps | undefined;
130
- const reducedMotion = isReducedMotion(globalProps?.motion);
138
+ const preferredMotion = useContext(PreferredMotionContext);
139
+ const globalProps = useHostGlobalProps() as SeedMotionGlobalProps | undefined;
140
+ const reducedMotion =
141
+ preferredMotion !== undefined
142
+ ? preferredMotion === "reduced"
143
+ : readDeprecatedReducedMotion(globalProps?.motion);
131
144
  const targetRef = useMainThreadRef<ScaleFeedbackElement | null>(null);
132
145
  const animationRef = useMainThreadRef<MainThread.Animation>(null);
133
146
  const scaleRef = useMainThreadRef<number | null>(null);