@use-gesture/core
Advanced tools
Comparing version 10.1.6 to 10.2.0
@@ -5,3 +5,3 @@ 'use strict'; | ||
var actions_dist_useGestureCoreActions = require('../../dist/actions-8a44751d.cjs.dev.js'); | ||
var actions_dist_useGestureCoreActions = require('../../dist/actions-37e715c3.cjs.dev.js'); | ||
require('../../dist/maths-125ca19a.cjs.dev.js'); | ||
@@ -8,0 +8,0 @@ |
@@ -5,3 +5,3 @@ 'use strict'; | ||
var actions_dist_useGestureCoreActions = require('../../dist/actions-9447c7f3.cjs.prod.js'); | ||
var actions_dist_useGestureCoreActions = require('../../dist/actions-4eed1aa2.cjs.prod.js'); | ||
require('../../dist/maths-a42ecce1.cjs.prod.js'); | ||
@@ -8,0 +8,0 @@ |
@@ -1,2 +0,2 @@ | ||
export { C as ConfigResolverMap, E as EngineMap, e as dragAction, h as hoverAction, m as moveAction, p as pinchAction, r as registerAction, s as scrollAction, w as wheelAction } from '../../dist/actions-d9485484.esm.js'; | ||
export { C as ConfigResolverMap, E as EngineMap, e as dragAction, h as hoverAction, m as moveAction, p as pinchAction, r as registerAction, s as scrollAction, w as wheelAction } from '../../dist/actions-9c309a79.esm.js'; | ||
import '../../dist/maths-b2a210f4.esm.js'; |
# @use-gesture/core | ||
## 10.2.0 | ||
### Minor Changes | ||
- b4e6181e7: Fix: should fix `transform` function doesn't have [0,0] origin. This required some pretty drastic internal changes hence the minor version bump. | ||
## 10.1.6 | ||
@@ -4,0 +10,0 @@ |
@@ -0,2 +1,4 @@ | ||
import { InternalGestureOptions } from '../types'; | ||
import { Vector2, State, GenericOptions } from '../types'; | ||
export declare const identity: (v: Vector2) => Vector2; | ||
export declare const DEFAULT_RUBBERBAND = 0.15; | ||
@@ -9,3 +11,3 @@ export declare const commonConfigResolver: { | ||
from(value: number | Vector2 | ((s: State) => Vector2)): [number, number] | ((s: State) => Vector2) | undefined; | ||
transform(value: any, _k: string, config: { | ||
transform(this: InternalGestureOptions, value: any, _k: string, config: { | ||
shared: GenericOptions; | ||
@@ -12,0 +14,0 @@ }): any; |
@@ -10,3 +10,3 @@ import { InternalCoordinatesOptions, CoordinatesConfig, DragBounds, State, Vector2 } from '../types'; | ||
from(value: number | Vector2 | ((s: State) => Vector2)): [number, number] | ((s: State) => Vector2) | undefined; | ||
transform(value: any, _k: string, config: { | ||
transform(this: import("../types").InternalGestureOptions<import("../types").GestureKey>, value: any, _k: string, config: { | ||
shared: import("../types").GenericOptions; | ||
@@ -13,0 +13,0 @@ }): any; |
@@ -38,5 +38,5 @@ import { DragConfig, InternalDragOptions, Vector2 } from '../types'; | ||
from(value: number | Vector2 | ((s: import("../types").State) => Vector2)): [number, number] | ((s: import("../types").State) => Vector2) | undefined; | ||
transform(value: any, _k: string, config: { | ||
transform(this: import("../types").InternalGestureOptions<import("../types").GestureKey>, value: any, _k: string, config: { | ||
shared: import("../types").GenericOptions; | ||
}): any; | ||
}; |
@@ -10,3 +10,3 @@ export declare const hoverConfigResolver: { | ||
from(value: number | import("../types").Vector2 | ((s: import("../types").State) => import("../types").Vector2)): [number, number] | ((s: import("../types").State) => import("../types").Vector2) | undefined; | ||
transform(value: any, _k: string, config: { | ||
transform(this: import("../types").InternalGestureOptions<import("../types").GestureKey>, value: any, _k: string, config: { | ||
shared: import("../types").GenericOptions; | ||
@@ -13,0 +13,0 @@ }): any; |
@@ -10,3 +10,3 @@ export declare const moveConfigResolver: { | ||
from(value: number | import("../types").Vector2 | ((s: import("../types").State) => import("../types").Vector2)): [number, number] | ((s: import("../types").State) => import("../types").Vector2) | undefined; | ||
transform(value: any, _k: string, config: { | ||
transform(this: import("../types").InternalGestureOptions<import("../types").GestureKey>, value: any, _k: string, config: { | ||
shared: import("../types").GenericOptions; | ||
@@ -13,0 +13,0 @@ }): any; |
@@ -18,5 +18,5 @@ import { PinchConfig, GenericOptions, InternalPinchOptions, State, Vector2 } from '../types'; | ||
from(value: number | Vector2 | ((s: State) => Vector2)): [number, number] | ((s: State) => Vector2) | undefined; | ||
transform(value: any, _k: string, config: { | ||
transform(this: import("../types").InternalGestureOptions<import("../types").GestureKey>, value: any, _k: string, config: { | ||
shared: GenericOptions; | ||
}): any; | ||
}; |
@@ -9,3 +9,3 @@ export declare const scrollConfigResolver: { | ||
from(value: number | import("../types").Vector2 | ((s: import("../types").State) => import("../types").Vector2)): [number, number] | ((s: import("../types").State) => import("../types").Vector2) | undefined; | ||
transform(value: any, _k: string, config: { | ||
transform(this: import("../types").InternalGestureOptions<import("../types").GestureKey>, value: any, _k: string, config: { | ||
shared: import("../types").GenericOptions; | ||
@@ -12,0 +12,0 @@ }): any; |
@@ -1,3 +0,2 @@ | ||
import { Target, Vector2 } from '../types'; | ||
export declare const identity: (v: Vector2) => Vector2; | ||
import { Target } from '../types'; | ||
export declare const sharedConfigResolver: { | ||
@@ -14,3 +13,3 @@ target(value: Target): (() => EventTarget | null) | undefined; | ||
}; | ||
transform(value?: (v: Vector2) => Vector2): (v: Vector2) => Vector2; | ||
transform(value: any): any; | ||
}; |
@@ -9,3 +9,3 @@ export declare const wheelConfigResolver: { | ||
from(value: number | import("../types").Vector2 | ((s: import("../types").State) => import("../types").Vector2)): [number, number] | ((s: import("../types").State) => import("../types").Vector2) | undefined; | ||
transform(value: any, _k: string, config: { | ||
transform(this: import("../types").InternalGestureOptions<import("../types").GestureKey>, value: any, _k: string, config: { | ||
shared: import("../types").GenericOptions; | ||
@@ -12,0 +12,0 @@ }): any; |
@@ -111,2 +111,14 @@ import { Controller } from '../Controller'; | ||
/** | ||
* Assign raw values to `state._values` and transformed values to | ||
* `state.values`. | ||
* @param values | ||
*/ | ||
computeValues(values: Vector2): void; | ||
/** | ||
* Assign `state._values` to `state._initial` and transformed `state.values` to | ||
* `state.initial`. | ||
* @param values | ||
*/ | ||
computeInitial(): void; | ||
/** | ||
* Computes all sorts of state attributes, including kinematics. | ||
@@ -113,0 +125,0 @@ * @param event |
export declare class TimeoutStore { | ||
private _timeouts; | ||
add<FunctionType extends (...args: any) => any>(key: string, callback: FunctionType, ms?: number, ...args: Parameters<FunctionType>): void; | ||
add<FunctionType extends (...args: any[]) => any>(key: string, callback: FunctionType, ms?: number, ...args: Parameters<FunctionType>): void; | ||
remove(key: string): void; | ||
clean(): void; | ||
} |
@@ -9,5 +9,5 @@ import { GestureKey, CoordinatesKey } from './config'; | ||
enabled: boolean; | ||
transform: (v: Vector2) => Vector2; | ||
transform?: (v: Vector2) => Vector2; | ||
}; | ||
export declare type InternalGestureOptions<Key extends GestureKey> = { | ||
export declare type InternalGestureOptions<Key extends GestureKey = GestureKey> = { | ||
enabled: boolean; | ||
@@ -20,2 +20,3 @@ from: Vector2 | ((state: State[Key]) => Vector2); | ||
bounds: [Vector2, Vector2] | ((state: State[Key]) => [Vector2, Vector2]); | ||
hasCustomTransform: boolean; | ||
transform: (v: Vector2) => Vector2; | ||
@@ -22,0 +23,0 @@ }; |
@@ -71,2 +71,4 @@ import { GestureKey } from './config'; | ||
_step: [false | number, false | number]; | ||
_values: Vector2; | ||
_initial: Vector2; | ||
_movement: Vector2; | ||
@@ -76,3 +78,2 @@ _distance: Vector2; | ||
_bounds: [Vector2, Vector2]; | ||
_threshold: Vector2; | ||
/** | ||
@@ -79,0 +80,0 @@ * The event triggering the gesture. |
@@ -5,3 +5,3 @@ 'use strict'; | ||
var actions_dist_useGestureCoreActions = require('./actions-8a44751d.cjs.dev.js'); | ||
var actions_dist_useGestureCoreActions = require('./actions-37e715c3.cjs.dev.js'); | ||
require('./maths-125ca19a.cjs.dev.js'); | ||
@@ -43,3 +43,2 @@ | ||
const identity = v => v; | ||
const sharedConfigResolver = { | ||
@@ -72,3 +71,3 @@ target(value) { | ||
transform(value = identity) { | ||
transform(value) { | ||
return value; | ||
@@ -75,0 +74,0 @@ } |
@@ -5,3 +5,3 @@ 'use strict'; | ||
var actions_dist_useGestureCoreActions = require('./actions-9447c7f3.cjs.prod.js'); | ||
var actions_dist_useGestureCoreActions = require('./actions-4eed1aa2.cjs.prod.js'); | ||
require('./maths-a42ecce1.cjs.prod.js'); | ||
@@ -43,3 +43,2 @@ | ||
const identity = v => v; | ||
const sharedConfigResolver = { | ||
@@ -72,3 +71,3 @@ target(value) { | ||
transform(value = identity) { | ||
transform(value) { | ||
return value; | ||
@@ -75,0 +74,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { S as SUPPORT, C as ConfigResolverMap, _ as _objectSpread2, a as _defineProperty, t as toDomEventType, i as isTouch, b as touchIds, E as EngineMap, c as chain, d as toHandlerProp } from './actions-d9485484.esm.js'; | ||
import { S as SUPPORT, C as ConfigResolverMap, _ as _objectSpread2, a as _defineProperty, t as toDomEventType, i as isTouch, b as touchIds, E as EngineMap, c as chain, d as toHandlerProp } from './actions-9c309a79.esm.js'; | ||
import './maths-b2a210f4.esm.js'; | ||
@@ -38,3 +38,2 @@ | ||
const identity = v => v; | ||
const sharedConfigResolver = { | ||
@@ -67,3 +66,3 @@ target(value) { | ||
transform(value = identity) { | ||
transform(value) { | ||
return value; | ||
@@ -70,0 +69,0 @@ } |
{ | ||
"name": "@use-gesture/core", | ||
"version": "10.1.6", | ||
"version": "10.2.0", | ||
"description": "Core engine for receiving gestures", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -0,4 +1,6 @@ | ||
import { InternalGestureOptions } from '../types' | ||
import { Vector2, State, GenericOptions } from '../types' | ||
import { V } from '../utils/maths' | ||
export const identity = (v: Vector2) => v | ||
export const DEFAULT_RUBBERBAND = 0.15 | ||
@@ -31,4 +33,18 @@ | ||
}, | ||
transform(value: any, _k: string, config: { shared: GenericOptions }) { | ||
return value || config.shared.transform | ||
transform(this: InternalGestureOptions, value: any, _k: string, config: { shared: GenericOptions }) { | ||
const transform = value || config.shared.transform | ||
this.hasCustomTransform = !!transform | ||
if (process.env.NODE_ENV === 'development') { | ||
const originalTransform = transform || identity | ||
return (v: Vector2) => { | ||
const r = originalTransform(v) | ||
if (!isFinite(r[0]) || !isFinite(r[1])) { | ||
// eslint-disable-next-line no-console | ||
console.warn(`[@use-gesture]: config.transform() must produce a valid result, but it was: [${r[0]},${[1]}]`) | ||
} | ||
return r | ||
} | ||
} | ||
return transform || identity | ||
}, | ||
@@ -35,0 +51,0 @@ threshold(value: any) { |
@@ -32,2 +32,3 @@ import { sharedConfigResolver } from './sharedConfigResolver' | ||
const { target, eventOptions, window, enabled, transform, ...rest } = config as any | ||
const _config: any = { | ||
@@ -34,0 +35,0 @@ shared: resolveWith({ target, eventOptions, window, enabled, transform }, sharedConfigResolver) |
@@ -1,6 +0,4 @@ | ||
import { Target, Vector2 } from '../types' | ||
import { Target } from '../types' | ||
import { SUPPORT } from './support' | ||
export const identity = (v: Vector2) => v | ||
export const sharedConfigResolver = { | ||
@@ -22,5 +20,5 @@ target(value: Target) { | ||
}, | ||
transform(value = identity) { | ||
transform(value: any) { | ||
return value | ||
} | ||
} |
@@ -106,4 +106,4 @@ import { CoordinatesEngine } from './CoordinatesEngine' | ||
state.values = pointerValues(event) | ||
state.initial = state.values | ||
this.computeValues(pointerValues(event)) | ||
this.computeInitial() | ||
@@ -142,3 +142,3 @@ if (config.preventScroll) { | ||
const values = pointerValues(event) | ||
const _values = pointerValues(event) | ||
@@ -148,4 +148,4 @@ if (document.pointerLockElement === event.target) { | ||
} else { | ||
state._delta = V.sub(values, state.values) | ||
state.values = values | ||
state._delta = V.sub(_values, state._values) | ||
this.computeValues(_values) | ||
} | ||
@@ -301,4 +301,4 @@ | ||
const deltaFn = KEYS_DELTA_MAP[event.key] | ||
const state = this.state | ||
if (deltaFn) { | ||
const state = this.state | ||
const factor = event.shiftKey ? 10 : event.altKey ? 0.1 : 1 | ||
@@ -305,0 +305,0 @@ state._delta = deltaFn(factor) |
@@ -74,6 +74,6 @@ import { Controller } from '../Controller' | ||
if (!this.state) { | ||
this.state = { | ||
values: [0, 0], | ||
initial: [0, 0] | ||
} as any | ||
this.state = {} as any | ||
this.computeValues([0, 0]) | ||
this.computeInitial() | ||
if (this.init) this.init() | ||
@@ -154,4 +154,3 @@ this.reset() | ||
reset() { | ||
const { state, shared, config, ingKey, args } = this | ||
const { transform, threshold } = config | ||
const { state, shared, ingKey, args } = this | ||
shared[ingKey] = state._active = state.active = state._blocked = state._force = false | ||
@@ -163,5 +162,2 @@ state._step = [false, false] | ||
state._delta = [0, 0] | ||
// the _threshold is the difference between a [0,0] origin offset converted to | ||
// its new space coordinates | ||
state._threshold = V.sub(transform(threshold), transform([0, 0])).map(Math.abs) as Vector2 | ||
// prettier-ignore | ||
@@ -189,6 +185,7 @@ state._bounds = [[-Infinity, Infinity], [-Infinity, Infinity]] | ||
this.reset() | ||
this.computeInitial() | ||
state._active = true | ||
state.target = event.target! | ||
state.currentTarget = event.currentTarget! | ||
state.initial = state.values | ||
state.lastOffset = config.from ? call(config.from, state) : state.offset | ||
@@ -199,3 +196,27 @@ state.offset = state.lastOffset | ||
} | ||
/** | ||
* Assign raw values to `state._values` and transformed values to | ||
* `state.values`. | ||
* @param values | ||
*/ | ||
computeValues(values: Vector2) { | ||
const state = this.state | ||
state._values = values | ||
// transforming values into user-defined coordinates (#402) | ||
state.values = this.config.transform(values) | ||
} | ||
/** | ||
* Assign `state._values` to `state._initial` and transformed `state.values` to | ||
* `state.initial`. | ||
* @param values | ||
*/ | ||
computeInitial() { | ||
const state = this.state | ||
state._initial = state._values | ||
state.initial = state.values | ||
} | ||
/** | ||
* Computes all sorts of state attributes, including kinematics. | ||
@@ -235,32 +256,34 @@ * @param event | ||
const [_m0, _m1] = config.transform(state._movement) | ||
// _movement is calculated by each gesture engine | ||
const [_m0, _m1] = state._movement | ||
const [t0, t1] = config.threshold | ||
if (process.env.NODE_ENV === 'development') { | ||
const isNumberAndNotNaN = (v: any) => typeof v === 'number' && !Number.isNaN(v); | ||
if (!isNumberAndNotNaN(_m0) || !isNumberAndNotNaN(_m1)) { | ||
// eslint-disable-next-line no-console | ||
console.warn( | ||
`[@use-gesture]: config.transform() must produce a valid result, but it was: [${_m0},${_m1}]` | ||
) | ||
} | ||
const { _step, values } = state | ||
if (config.hasCustomTransform) { | ||
// When the user is using a custom transform, we're using _step to store | ||
// the first value passing the threshold. | ||
if (_step[0] === false) _step[0] = Math.abs(_m0) >= t0 && values[0] | ||
if (_step[1] === false) _step[1] = Math.abs(_m1) >= t1 && values[1] | ||
} else { | ||
// `_step` will hold the threshold at which point the gesture was triggered. | ||
// The threshold is signed depending on which direction triggered it. | ||
if (_step[0] === false) _step[0] = Math.abs(_m0) >= t0 && Math.sign(_m0) * t0 | ||
if (_step[1] === false) _step[1] = Math.abs(_m1) >= t1 && Math.sign(_m1) * t1 | ||
} | ||
const [_t0, _t1] = state._threshold | ||
// Step will hold the threshold at which point the gesture was triggered. The | ||
// threshold is signed depending on which direction triggered it. | ||
let [_s0, _s1] = state._step | ||
state.intentional = _step[0] !== false || _step[0] !== false | ||
if (_s0 === false) _s0 = Math.abs(_m0) >= _t0 && Math.sign(_m0) * _t0 | ||
if (_s1 === false) _s1 = Math.abs(_m1) >= _t1 && Math.sign(_m1) * _t1 | ||
state.intentional = _s0 !== false || _s1 !== false | ||
if (!state.intentional) return | ||
state._step = [_s0, _s1] | ||
const movement: Vector2 = [0, 0] | ||
movement[0] = _s0 !== false ? _m0 - _s0 : 0 | ||
movement[1] = _s1 !== false ? _m1 - _s1 : 0 | ||
if (config.hasCustomTransform) { | ||
const [v0, v1] = values | ||
movement[0] = _step[0] !== false ? v0 - _step[0] : 0 | ||
movement[1] = _step[1] !== false ? v1 - _step[1] : 0 | ||
} else { | ||
movement[0] = _step[0] !== false ? _m0 - _step[0] : 0 | ||
movement[1] = _step[1] !== false ? _m1 - _step[1] : 0 | ||
} | ||
@@ -316,3 +339,3 @@ // let's run intentionality check. | ||
// we don't trigger the handler if the gesture is blockedor non intentional, | ||
// we don't trigger the handler if the gesture is blocked or non intentional, | ||
// unless the `_force` flag was set or the `triggerAllEvents` option was set | ||
@@ -319,0 +342,0 @@ // to true in the config. |
@@ -11,3 +11,3 @@ import { CoordinatesEngine } from './CoordinatesEngine' | ||
this.start(event) | ||
this.state.values = pointerValues(event) | ||
this.computeValues(pointerValues(event)) | ||
@@ -26,6 +26,7 @@ this.compute(event) | ||
const values = pointerValues(event) | ||
state._movement = state._delta = V.sub(values, state.values) | ||
state.values = values | ||
state._movement = state._delta = V.sub(values, state._values) | ||
this.computeValues(values) | ||
this.compute(event) | ||
state.delta = state.movement | ||
@@ -32,0 +33,0 @@ this.emit() |
@@ -17,6 +17,5 @@ import { CoordinatesEngine } from './CoordinatesEngine' | ||
this.start(event) | ||
const state = this.state | ||
state.values = pointerValues(event) | ||
this.computeValues(pointerValues(event)) | ||
this.compute(event) | ||
state.initial = state.values | ||
this.computeInitial() | ||
this.emit() | ||
@@ -29,6 +28,7 @@ } | ||
const state = this.state | ||
state._delta = V.sub(values, state.values) | ||
state._delta = V.sub(values, state._values) | ||
V.addTo(state._movement, state._delta) | ||
state.values = values | ||
this.computeValues(values) | ||
this.compute(event) | ||
@@ -35,0 +35,0 @@ this.emit() |
@@ -121,4 +121,4 @@ import { Engine } from './Engine' | ||
state.origin = payload.origin | ||
state.values = [payload.distance, payload.angle] | ||
state.initial = state.values | ||
this.computeValues([payload.distance, payload.angle]) | ||
this.computeInitial() | ||
@@ -148,10 +148,14 @@ this.compute(event) | ||
const state = this.state | ||
const prev_a = state.values[1] | ||
const prev_a = state._values[1] | ||
const delta_a = payload.angle - prev_a | ||
let delta_turns = 0 | ||
if (Math.abs(delta_a) > 270) delta_turns += Math.sign(delta_a) | ||
state.values = [payload.distance, payload.angle - 360 * delta_turns] | ||
this.computeValues([payload.distance, payload.angle - 360 * delta_turns]) | ||
state.origin = payload.origin | ||
state.turns = delta_turns | ||
state._movement = [state.values[0] / state.initial[0] - 1, state.values[1] - state.initial[1]] | ||
state._movement = [state._values[0] / state._initial[0] - 1, state._values[1] - state._initial[1]] | ||
this.compute(event) | ||
@@ -201,3 +205,3 @@ this.emit() | ||
this.start(event) | ||
state.values = [event.scale, event.rotation] | ||
this.computeValues([event.scale, event.rotation]) | ||
state.origin = [event.clientX, event.clientY] | ||
@@ -215,3 +219,4 @@ this.compute(event) | ||
const state = this.state | ||
state.values = [event.scale, event.rotation] | ||
this.computeValues([event.scale, event.rotation]) | ||
state.origin = [event.clientX, event.clientY] | ||
@@ -218,0 +223,0 @@ const _previousMovement = state._movement |
@@ -18,7 +18,8 @@ import { CoordinatesEngine } from './CoordinatesEngine' | ||
const values = scrollValues(event) | ||
state._delta = V.sub(values, state.values) | ||
state._delta = V.sub(values, state._values) | ||
V.addTo(state._movement, state._delta) | ||
state.values = values | ||
this.computeValues(values) | ||
this.compute(event) | ||
this.emit() | ||
@@ -25,0 +26,0 @@ } |
export class TimeoutStore { | ||
private _timeouts = new Map<string, number>() | ||
add<FunctionType extends (...args: any) => any>( | ||
add<FunctionType extends (...args: any[]) => any>( | ||
key: string, | ||
@@ -6,0 +6,0 @@ callback: FunctionType, |
@@ -10,6 +10,6 @@ import { GestureKey, CoordinatesKey } from './config' | ||
enabled: boolean | ||
transform: (v: Vector2) => Vector2 | ||
transform?: (v: Vector2) => Vector2 | ||
} | ||
export type InternalGestureOptions<Key extends GestureKey> = { | ||
export type InternalGestureOptions<Key extends GestureKey = GestureKey> = { | ||
enabled: boolean | ||
@@ -22,2 +22,3 @@ from: Vector2 | ((state: State[Key]) => Vector2) | ||
bounds: [Vector2, Vector2] | ((state: State[Key]) => [Vector2, Vector2]) | ||
hasCustomTransform: boolean | ||
transform: (v: Vector2) => Vector2 | ||
@@ -24,0 +25,0 @@ } |
@@ -74,2 +74,4 @@ import { GestureKey } from './config' | ||
_step: [false | number, false | number] | ||
_values: Vector2 | ||
_initial: Vector2 | ||
_movement: Vector2 | ||
@@ -79,3 +81,2 @@ _distance: Vector2 | ||
_bounds: [Vector2, Vector2] | ||
_threshold: Vector2 | ||
/** | ||
@@ -82,0 +83,0 @@ * The event triggering the gesture. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
296550
8672