@reactuses/core 2.2.9 → 3.0.1

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/index.cjs CHANGED
@@ -2974,18 +2974,19 @@ function getTargetElement(target, defaultElement) {
2974
2974
  return targetElement;
2975
2975
  }
2976
2976
  function useLatestElement(target, defaultElement) {
2977
- const ref = React.useRef(getTargetElement(target, defaultElement));
2977
+ const [latestElement, setLatestElement] = React.useState(
2978
+ getTargetElement(target, defaultElement)
2979
+ );
2978
2980
  React.useEffect(() => {
2979
- ref.current = getTargetElement(target, defaultElement);
2980
- });
2981
- return ref;
2981
+ setLatestElement(getTargetElement(target, defaultElement));
2982
+ }, [target, defaultElement]);
2983
+ return latestElement;
2982
2984
  }
2983
2985
 
2984
2986
  function useEventListener(eventName, handler, element, options) {
2985
2987
  const savedHandler = useLatest(handler);
2986
- const targetElementRef = useLatestElement(element, defaultWindow);
2988
+ const targetElement = useLatestElement(element, defaultWindow);
2987
2989
  useDeepCompareEffect(() => {
2988
- const targetElement = targetElementRef.current;
2989
2990
  if (!(targetElement && targetElement.addEventListener)) {
2990
2991
  return;
2991
2992
  }
@@ -2997,7 +2998,7 @@ function useEventListener(eventName, handler, element, options) {
2997
2998
  }
2998
2999
  off(targetElement, eventName, eventListener);
2999
3000
  };
3000
- }, [eventName, targetElementRef.current, options, savedHandler]);
3001
+ }, [eventName, targetElement, options, savedHandler]);
3001
3002
  }
3002
3003
 
3003
3004
  function useCounter(initialValue = 0, max = null, min = null) {
@@ -3149,13 +3150,13 @@ function useMutationObserver(callback, target, options = {}) {
3149
3150
  }
3150
3151
  }, []);
3151
3152
  useDeepCompareEffect(() => {
3152
- if (!element.current) {
3153
+ if (!element) {
3153
3154
  return;
3154
3155
  }
3155
3156
  observerRef.current = new MutationObserver(callbackRef.current);
3156
- observerRef.current.observe(element.current, options);
3157
+ observerRef.current.observe(element, options);
3157
3158
  return stop;
3158
- }, [options, element.current]);
3159
+ }, [options, element]);
3159
3160
  return stop;
3160
3161
  }
3161
3162
 
@@ -3411,34 +3412,95 @@ function useIdle(ms = oneMinute, initialState = false, events = defaultEvents$1)
3411
3412
  return state;
3412
3413
  }
3413
3414
 
3414
- function useMediaDevices() {
3415
+ function useSupported(callback, sync = false) {
3416
+ const [supported, setSupported] = React.useState(false);
3417
+ const effect = sync ? useIsomorphicLayoutEffect : React.useEffect;
3418
+ effect(() => {
3419
+ setSupported(Boolean(callback()));
3420
+ }, []);
3421
+ return supported;
3422
+ }
3423
+
3424
+ var __async$4 = (__this, __arguments, generator) => {
3425
+ return new Promise((resolve, reject) => {
3426
+ var fulfilled = (value) => {
3427
+ try {
3428
+ step(generator.next(value));
3429
+ } catch (e) {
3430
+ reject(e);
3431
+ }
3432
+ };
3433
+ var rejected = (value) => {
3434
+ try {
3435
+ step(generator.throw(value));
3436
+ } catch (e) {
3437
+ reject(e);
3438
+ }
3439
+ };
3440
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
3441
+ step((generator = generator.apply(__this, __arguments)).next());
3442
+ });
3443
+ };
3444
+ function useMediaDevices(options = {}) {
3445
+ const { requestPermissions, constraints = { audio: true, video: true } } = options;
3415
3446
  const [state, setState] = React.useState({ devices: [] });
3447
+ const isSupported = useSupported(
3448
+ () => navigator && navigator.mediaDevices && navigator.mediaDevices.enumerateDevices
3449
+ );
3450
+ const permissionGranted = React.useRef(false);
3451
+ const stream = React.useRef(null);
3452
+ const onChange = React.useCallback(() => {
3453
+ navigator.mediaDevices.enumerateDevices().then((devices) => {
3454
+ if (stream.current) {
3455
+ stream.current.getTracks().forEach((t) => t.stop());
3456
+ stream.current = null;
3457
+ }
3458
+ setState({
3459
+ devices: devices.map(({ deviceId, groupId, kind, label }) => ({
3460
+ deviceId,
3461
+ groupId,
3462
+ kind,
3463
+ label
3464
+ }))
3465
+ });
3466
+ }).catch(noop);
3467
+ }, []);
3468
+ const ensurePermissions = React.useCallback(() => __async$4(this, null, function* () {
3469
+ if (!isSupported) {
3470
+ return false;
3471
+ }
3472
+ if (permissionGranted.current) {
3473
+ return true;
3474
+ }
3475
+ const permissionStatus = yield navigator.permissions.query({
3476
+ name: "camera"
3477
+ });
3478
+ if (permissionStatus.state !== "granted") {
3479
+ stream.current = yield navigator.mediaDevices.getUserMedia(constraints);
3480
+ onChange();
3481
+ permissionGranted.current = true;
3482
+ } else {
3483
+ permissionGranted.current = false;
3484
+ }
3485
+ return permissionGranted.current;
3486
+ }), [onChange, isSupported, constraints]);
3416
3487
  React.useEffect(() => {
3417
- let mounted = true;
3418
- const onChange = () => {
3419
- navigator.mediaDevices.enumerateDevices().then((devices) => {
3420
- if (mounted) {
3421
- setState({
3422
- devices: devices.map(({ deviceId, groupId, kind, label }) => ({
3423
- deviceId,
3424
- groupId,
3425
- kind,
3426
- label
3427
- }))
3428
- });
3429
- }
3430
- }).catch(noop);
3431
- };
3488
+ if (!isSupported) {
3489
+ return;
3490
+ }
3491
+ if (requestPermissions) {
3492
+ ensurePermissions();
3493
+ }
3432
3494
  on(navigator.mediaDevices, "devicechange", onChange);
3433
3495
  onChange();
3434
3496
  return () => {
3435
- mounted = false;
3436
3497
  off(navigator.mediaDevices, "devicechange", onChange);
3437
3498
  };
3438
- }, []);
3439
- return state;
3499
+ }, [onChange, isSupported, requestPermissions, ensurePermissions]);
3500
+ return [state, ensurePermissions];
3440
3501
  }
3441
- const useMediaDevicesMock = () => ({ devices: [] });
3502
+ const useMediaDevicesMock = () => [{ devices: [] }, () => {
3503
+ }];
3442
3504
  var index$3 = isNavigator && !!navigator.mediaDevices ? useMediaDevices : useMediaDevicesMock;
3443
3505
 
3444
3506
  function useTextDirection(options = {}) {
@@ -3939,16 +4001,16 @@ function useIntersectionObserver(target, callback, options = {}) {
3939
4001
  }
3940
4002
  }, []);
3941
4003
  useDeepCompareEffect(() => {
3942
- if (!element.current) {
4004
+ if (!element) {
3943
4005
  return;
3944
4006
  }
3945
4007
  observerRef.current = new IntersectionObserver(
3946
4008
  savedCallback.current,
3947
4009
  options
3948
4010
  );
3949
- observerRef.current.observe(element.current);
4011
+ observerRef.current.observe(element);
3950
4012
  return stop;
3951
- }, [options, element.current]);
4013
+ }, [options, element]);
3952
4014
  return stop;
3953
4015
  }
3954
4016
 
@@ -3995,13 +4057,13 @@ function useResizeObserver(target, callback, options = {}) {
3995
4057
  }
3996
4058
  }, []);
3997
4059
  useDeepCompareEffect(() => {
3998
- if (!element.current) {
4060
+ if (!element) {
3999
4061
  return;
4000
4062
  }
4001
4063
  observerRef.current = new ResizeObserver(savedCallback.current);
4002
- observerRef.current.observe(element.current, options);
4064
+ observerRef.current.observe(element, options);
4003
4065
  return stop;
4004
- }, [options, element.current]);
4066
+ }, [options, element]);
4005
4067
  return stop;
4006
4068
  }
4007
4069
 
@@ -4231,16 +4293,16 @@ function useInfiniteScroll(target, onLoadMore, options = {}) {
4231
4293
  useUpdateEffect(() => {
4232
4294
  const opts = latestOptions.current;
4233
4295
  const fn = () => __async$3(this, null, function* () {
4234
- var _a2, _b2, _c, _d;
4296
+ var _a2, _b2;
4235
4297
  const previous = {
4236
- height: (_b2 = (_a2 = element.current) == null ? void 0 : _a2.scrollHeight) != null ? _b2 : 0,
4237
- width: (_d = (_c = element.current) == null ? void 0 : _c.scrollWidth) != null ? _d : 0
4298
+ height: (_a2 = element == null ? void 0 : element.scrollHeight) != null ? _a2 : 0,
4299
+ width: (_b2 = element == null ? void 0 : element.scrollWidth) != null ? _b2 : 0
4238
4300
  };
4239
4301
  yield savedLoadMore.current(state);
4240
- if (opts.preserveScrollPosition && element.current) {
4241
- element.current.scrollTo({
4242
- top: element.current.scrollHeight - previous.height,
4243
- left: element.current.scrollWidth - previous.width
4302
+ if (opts.preserveScrollPosition && element) {
4303
+ element.scrollTo({
4304
+ top: element.scrollHeight - previous.height,
4305
+ left: element.scrollWidth - previous.width
4244
4306
  });
4245
4307
  }
4246
4308
  });
@@ -4282,7 +4344,7 @@ function useMousePressed(target, options = {}) {
4282
4344
  const { touch = true, drag = true, initialValue = false } = options;
4283
4345
  const [pressed, setPressed] = React.useState(initialValue);
4284
4346
  const [sourceType, setSourceType] = React.useState(null);
4285
- const elementRef = useLatestElement(target);
4347
+ const element = useLatestElement(target);
4286
4348
  const onPressed = React.useCallback(
4287
4349
  (srcType) => () => {
4288
4350
  setPressed(true);
@@ -4298,7 +4360,6 @@ function useMousePressed(target, options = {}) {
4298
4360
  useEventListener("mouseleave", onReleased, () => window, { passive: true });
4299
4361
  useEventListener("mouseup", onReleased, () => window, { passive: true });
4300
4362
  React.useEffect(() => {
4301
- const element = elementRef.current;
4302
4363
  if (drag) {
4303
4364
  element == null ? void 0 : element.addEventListener("dragstart", onPressed("mouse"), {
4304
4365
  passive: true
@@ -4333,7 +4394,7 @@ function useMousePressed(target, options = {}) {
4333
4394
  element == null ? void 0 : element.removeEventListener("touchcancel", onReleased);
4334
4395
  }
4335
4396
  };
4336
- }, [drag, onPressed, onReleased, touch, elementRef.current]);
4397
+ }, [drag, onPressed, onReleased, touch, element]);
4337
4398
  return [pressed, sourceType];
4338
4399
  }
4339
4400
 
@@ -4352,32 +4413,32 @@ function useScrollLock(target, initialState = false) {
4352
4413
  const initialOverflowRef = React.useRef("scroll");
4353
4414
  const element = useLatestElement(target);
4354
4415
  React.useEffect(() => {
4355
- if (element.current) {
4356
- initialOverflowRef.current = element.current.style.overflow;
4416
+ if (element) {
4417
+ initialOverflowRef.current = element.style.overflow;
4357
4418
  if (locked) {
4358
- element.current.style.overflow = "hidden";
4419
+ element.style.overflow = "hidden";
4359
4420
  }
4360
4421
  }
4361
- }, [locked, element.current]);
4422
+ }, [locked, element]);
4362
4423
  const lock = useEvent(() => {
4363
- if (!element.current || locked) {
4424
+ if (!element || locked) {
4364
4425
  return;
4365
4426
  }
4366
4427
  if (isIOS) {
4367
- element.current.addEventListener("touchmove", preventDefault, {
4428
+ element.addEventListener("touchmove", preventDefault, {
4368
4429
  passive: false
4369
4430
  });
4370
4431
  }
4371
4432
  setLocked(true);
4372
4433
  });
4373
4434
  const unlock = useEvent(() => {
4374
- if (!element.current || !locked) {
4435
+ if (!element || !locked) {
4375
4436
  return;
4376
4437
  }
4377
4438
  if (isIOS) {
4378
- element.current.removeEventListener("touchmove", preventDefault);
4439
+ element.removeEventListener("touchmove", preventDefault);
4379
4440
  }
4380
- element.current.style.overflow = initialOverflowRef.current;
4441
+ element.style.overflow = initialOverflowRef.current;
4381
4442
  setLocked(false);
4382
4443
  });
4383
4444
  const set = useEvent((flag) => {
@@ -4817,11 +4878,11 @@ function useClickOutSide(target, handler) {
4817
4878
  const savedHandler = useLatest(handler);
4818
4879
  const element = useLatestElement(target);
4819
4880
  const listener = (event) => {
4820
- if (!element.current) {
4881
+ if (!element) {
4821
4882
  return;
4822
4883
  }
4823
4884
  const elements = event.composedPath();
4824
- if (element.current === event.target || elements.includes(element.current)) {
4885
+ if (element === event.target || elements.includes(element)) {
4825
4886
  return;
4826
4887
  }
4827
4888
  savedHandler.current(event);
@@ -5066,7 +5127,7 @@ function useScrollIntoView({
5066
5127
  const scrollIntoView = useEvent(
5067
5128
  ({ alignment = "start" } = {}) => {
5068
5129
  var _a;
5069
- const parent = getTargetElement(scrollElement) || getScrollParent(axis, element.current);
5130
+ const parent = getTargetElement(scrollElement) || getScrollParent(axis, element);
5070
5131
  shouldStop.current = false;
5071
5132
  if (frameID.current) {
5072
5133
  cancel();
@@ -5074,7 +5135,7 @@ function useScrollIntoView({
5074
5135
  const start = (_a = getScrollStart({ parent, axis })) != null ? _a : 0;
5075
5136
  const change = getRelativePosition({
5076
5137
  parent,
5077
- target: element.current,
5138
+ target: element,
5078
5139
  axis,
5079
5140
  alignment,
5080
5141
  offset,
@@ -5128,10 +5189,10 @@ const useSticky = ({
5128
5189
  const [isSticky, setSticky] = React.useState(false);
5129
5190
  const element = useLatestElement(targetElement);
5130
5191
  const { run: scrollHandler } = useThrottleFn(() => {
5131
- if (!element.current) {
5192
+ if (!element) {
5132
5193
  return;
5133
5194
  }
5134
- const rect = element.current.getBoundingClientRect();
5195
+ const rect = element.getBoundingClientRect();
5135
5196
  if (axis === "y") {
5136
5197
  setSticky((rect == null ? void 0 : rect.top) <= nav);
5137
5198
  } else {
@@ -5139,8 +5200,8 @@ const useSticky = ({
5139
5200
  }
5140
5201
  }, 50);
5141
5202
  React.useEffect(() => {
5142
- const scrollParent = getTargetElement(scrollElement) || getScrollParent(axis, element.current);
5143
- if (!element.current || !scrollParent) {
5203
+ const scrollParent = getTargetElement(scrollElement) || getScrollParent(axis, element);
5204
+ if (!element || !scrollParent) {
5144
5205
  return;
5145
5206
  }
5146
5207
  scrollParent.addEventListener("scroll", scrollHandler);
@@ -5222,15 +5283,6 @@ const useCountDown = (time, format = getHMSTime, callback) => {
5222
5283
  return [hour, minute, secoud];
5223
5284
  };
5224
5285
 
5225
- function useSupported(callback, sync = false) {
5226
- const [supported, setSupported] = React.useState(false);
5227
- const effect = sync ? useIsomorphicLayoutEffect : React.useEffect;
5228
- effect(() => {
5229
- setSupported(Boolean(callback()));
5230
- }, []);
5231
- return supported;
5232
- }
5233
-
5234
5286
  function useTextSelection() {
5235
5287
  const [selection, setSelection] = React.useState(null);
5236
5288
  const forceUpdate = useUpdate();
package/dist/index.d.ts CHANGED
@@ -287,15 +287,32 @@ declare function useObjectUrl(object: Blob | MediaSource | undefined): string |
287
287
 
288
288
  declare function useIdle(ms?: number, initialState?: boolean, events?: (keyof WindowEventMap)[]): boolean;
289
289
 
290
- declare function useMediaDevices(): {
290
+ interface UseMediaDeviceOptions {
291
+ /**
292
+ * Request for permissions immediately if it's not granted,
293
+ * otherwise label and deviceIds could be empty
294
+ *
295
+ * @default false
296
+ */
297
+ requestPermissions?: boolean;
298
+ /**
299
+ * Request for types of media permissions
300
+ *
301
+ * @default { audio: true, video: true }
302
+ */
303
+ constraints?: MediaStreamConstraints;
304
+ }
305
+ declare function useMediaDevices(options?: UseMediaDeviceOptions): readonly [{
291
306
  devices: {
292
307
  deviceId: string;
293
308
  groupId: string;
294
309
  kind: MediaDeviceKind;
295
310
  label: string;
296
311
  }[];
297
- };
298
- declare const _default$3: typeof useMediaDevices;
312
+ }, () => Promise<boolean>];
313
+ declare const _default$3: typeof useMediaDevices | (() => ((() => void) | {
314
+ devices: never[];
315
+ })[]);
299
316
 
300
317
  type UseTextDirectionValue = "ltr" | "rtl" | "auto";
301
318
  interface UseTextDirectionOptions {
@@ -852,4 +869,4 @@ declare function useSetState<T extends Record<string, any>>(initialState: T): re
852
869
  type UseMeasureRect = Omit<DOMRectReadOnly, "toJSON">;
853
870
  declare function useMeasure(target: BasicTarget, options?: ResizeObserverOptions): readonly [UseMeasureRect, () => void];
854
871
 
855
- export { ColorScheme, Contrast, CookieOptions, CookieState, CursorState, EyeDropperOpenReturnType, GeneralPermissionDescriptor, IDisposable, IEvent, IEventOnce, IListener, INetworkInformation, IState, IUseNetworkState, KeyModifier, MousePressedOptions, MouseSourceType, OrientationState, RafLoopReturns, ScrollIntoViewAnimation, ScrollIntoViewParams, State, Status, Target, UseDarkOptions, UseDraggableOptions, UseElementBoundingOptions, UseEventEmitterReturn, UseEyeDropperReturn, UseFileDialogOptions, UseFpsOptions, UseFullScreenOptions, UseInfiniteScrollOptions, UseLongPressOptions, UseMeasureRect, UseModifierOptions, UseScriptTagOptions, UseScrollOptions, UseStickyParams, UseTextDirectionOptions, UseTextDirectionValue, UseTimeoutFnOptions, UseVirtualListItem, UseVirtualListOptions, UseVirtualListReturn, WindowSize, getHMSTime, useActiveElement, useAsyncEffect, useClickOutSide as useClickOutside, useClipBorad as useClipboard, useControlled, useCookie, useCountDown, useCounter, useCustomCompareEffect, useCycleList, useDarkMode, useDebounce, useDebounceFn, useDeepCompareEffect, useDocumentVisibility, useDoubleClick, useDraggable, useDropZone, useElementBounding, useElementSize, useElementVisibility, useEvent, useEventEmitter, useEventListener, useEyeDropper, useFavicon, useFileDialog, useFirstMountState, useFocus, _default$2 as useFps, useFullscreen, useGeolocation, useIdle, useInfiniteScroll, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyModifier, useLatest, useLocalStorage, useLongPress, useMeasure, _default$3 as useMediaDevices, useMediaQuery, useMount, useMountedState, useMouse, useMousePressed, useMutationObserver, useNetwork, useObjectUrl, _default$1 as useOnceEffect, _default as useOnceLayoutEffect, useOnline, useOrientation, usePageLeave, usePermission, usePreferredColorScheme, usePreferredContrast, usePreferredDark, usePrevious, useRafFn, useRafState, useReducedMotion, useResizeObserver, useScriptTag, useScroll, useScrollIntoView, useScrollLock, useSessionStorage, useSetState, useSticky, useSupported, useTextDirection, useTextSelection, useThrottle, useThrottleFn, useTimeout, useTimeoutFn, useTitle, useToggle, useUnmount, useUpdate, _default$5 as useUpdateEffect, _default$4 as useUpdateLayoutEffect, useVirtualList, useWindowScroll, useWindowSize, useWindowsFocus };
872
+ export { ColorScheme, Contrast, CookieOptions, CookieState, CursorState, EyeDropperOpenReturnType, GeneralPermissionDescriptor, IDisposable, IEvent, IEventOnce, IListener, INetworkInformation, IState, IUseNetworkState, KeyModifier, MousePressedOptions, MouseSourceType, OrientationState, RafLoopReturns, ScrollIntoViewAnimation, ScrollIntoViewParams, State, Status, Target, UseDarkOptions, UseDraggableOptions, UseElementBoundingOptions, UseEventEmitterReturn, UseEyeDropperReturn, UseFileDialogOptions, UseFpsOptions, UseFullScreenOptions, UseInfiniteScrollOptions, UseLongPressOptions, UseMeasureRect, UseMediaDeviceOptions, UseModifierOptions, UseScriptTagOptions, UseScrollOptions, UseStickyParams, UseTextDirectionOptions, UseTextDirectionValue, UseTimeoutFnOptions, UseVirtualListItem, UseVirtualListOptions, UseVirtualListReturn, WindowSize, getHMSTime, useActiveElement, useAsyncEffect, useClickOutSide as useClickOutside, useClipBorad as useClipboard, useControlled, useCookie, useCountDown, useCounter, useCustomCompareEffect, useCycleList, useDarkMode, useDebounce, useDebounceFn, useDeepCompareEffect, useDocumentVisibility, useDoubleClick, useDraggable, useDropZone, useElementBounding, useElementSize, useElementVisibility, useEvent, useEventEmitter, useEventListener, useEyeDropper, useFavicon, useFileDialog, useFirstMountState, useFocus, _default$2 as useFps, useFullscreen, useGeolocation, useIdle, useInfiniteScroll, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyModifier, useLatest, useLocalStorage, useLongPress, useMeasure, _default$3 as useMediaDevices, useMediaQuery, useMount, useMountedState, useMouse, useMousePressed, useMutationObserver, useNetwork, useObjectUrl, _default$1 as useOnceEffect, _default as useOnceLayoutEffect, useOnline, useOrientation, usePageLeave, usePermission, usePreferredColorScheme, usePreferredContrast, usePreferredDark, usePrevious, useRafFn, useRafState, useReducedMotion, useResizeObserver, useScriptTag, useScroll, useScrollIntoView, useScrollLock, useSessionStorage, useSetState, useSticky, useSupported, useTextDirection, useTextSelection, useThrottle, useThrottleFn, useTimeout, useTimeoutFn, useTitle, useToggle, useUnmount, useUpdate, _default$5 as useUpdateEffect, _default$4 as useUpdateLayoutEffect, useVirtualList, useWindowScroll, useWindowSize, useWindowsFocus };
package/dist/index.mjs CHANGED
@@ -2966,18 +2966,19 @@ function getTargetElement(target, defaultElement) {
2966
2966
  return targetElement;
2967
2967
  }
2968
2968
  function useLatestElement(target, defaultElement) {
2969
- const ref = useRef(getTargetElement(target, defaultElement));
2969
+ const [latestElement, setLatestElement] = useState(
2970
+ getTargetElement(target, defaultElement)
2971
+ );
2970
2972
  useEffect(() => {
2971
- ref.current = getTargetElement(target, defaultElement);
2972
- });
2973
- return ref;
2973
+ setLatestElement(getTargetElement(target, defaultElement));
2974
+ }, [target, defaultElement]);
2975
+ return latestElement;
2974
2976
  }
2975
2977
 
2976
2978
  function useEventListener(eventName, handler, element, options) {
2977
2979
  const savedHandler = useLatest(handler);
2978
- const targetElementRef = useLatestElement(element, defaultWindow);
2980
+ const targetElement = useLatestElement(element, defaultWindow);
2979
2981
  useDeepCompareEffect(() => {
2980
- const targetElement = targetElementRef.current;
2981
2982
  if (!(targetElement && targetElement.addEventListener)) {
2982
2983
  return;
2983
2984
  }
@@ -2989,7 +2990,7 @@ function useEventListener(eventName, handler, element, options) {
2989
2990
  }
2990
2991
  off(targetElement, eventName, eventListener);
2991
2992
  };
2992
- }, [eventName, targetElementRef.current, options, savedHandler]);
2993
+ }, [eventName, targetElement, options, savedHandler]);
2993
2994
  }
2994
2995
 
2995
2996
  function useCounter(initialValue = 0, max = null, min = null) {
@@ -3141,13 +3142,13 @@ function useMutationObserver(callback, target, options = {}) {
3141
3142
  }
3142
3143
  }, []);
3143
3144
  useDeepCompareEffect(() => {
3144
- if (!element.current) {
3145
+ if (!element) {
3145
3146
  return;
3146
3147
  }
3147
3148
  observerRef.current = new MutationObserver(callbackRef.current);
3148
- observerRef.current.observe(element.current, options);
3149
+ observerRef.current.observe(element, options);
3149
3150
  return stop;
3150
- }, [options, element.current]);
3151
+ }, [options, element]);
3151
3152
  return stop;
3152
3153
  }
3153
3154
 
@@ -3403,34 +3404,95 @@ function useIdle(ms = oneMinute, initialState = false, events = defaultEvents$1)
3403
3404
  return state;
3404
3405
  }
3405
3406
 
3406
- function useMediaDevices() {
3407
+ function useSupported(callback, sync = false) {
3408
+ const [supported, setSupported] = useState(false);
3409
+ const effect = sync ? useIsomorphicLayoutEffect : useEffect;
3410
+ effect(() => {
3411
+ setSupported(Boolean(callback()));
3412
+ }, []);
3413
+ return supported;
3414
+ }
3415
+
3416
+ var __async$4 = (__this, __arguments, generator) => {
3417
+ return new Promise((resolve, reject) => {
3418
+ var fulfilled = (value) => {
3419
+ try {
3420
+ step(generator.next(value));
3421
+ } catch (e) {
3422
+ reject(e);
3423
+ }
3424
+ };
3425
+ var rejected = (value) => {
3426
+ try {
3427
+ step(generator.throw(value));
3428
+ } catch (e) {
3429
+ reject(e);
3430
+ }
3431
+ };
3432
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
3433
+ step((generator = generator.apply(__this, __arguments)).next());
3434
+ });
3435
+ };
3436
+ function useMediaDevices(options = {}) {
3437
+ const { requestPermissions, constraints = { audio: true, video: true } } = options;
3407
3438
  const [state, setState] = useState({ devices: [] });
3439
+ const isSupported = useSupported(
3440
+ () => navigator && navigator.mediaDevices && navigator.mediaDevices.enumerateDevices
3441
+ );
3442
+ const permissionGranted = useRef(false);
3443
+ const stream = useRef(null);
3444
+ const onChange = useCallback(() => {
3445
+ navigator.mediaDevices.enumerateDevices().then((devices) => {
3446
+ if (stream.current) {
3447
+ stream.current.getTracks().forEach((t) => t.stop());
3448
+ stream.current = null;
3449
+ }
3450
+ setState({
3451
+ devices: devices.map(({ deviceId, groupId, kind, label }) => ({
3452
+ deviceId,
3453
+ groupId,
3454
+ kind,
3455
+ label
3456
+ }))
3457
+ });
3458
+ }).catch(noop);
3459
+ }, []);
3460
+ const ensurePermissions = useCallback(() => __async$4(this, null, function* () {
3461
+ if (!isSupported) {
3462
+ return false;
3463
+ }
3464
+ if (permissionGranted.current) {
3465
+ return true;
3466
+ }
3467
+ const permissionStatus = yield navigator.permissions.query({
3468
+ name: "camera"
3469
+ });
3470
+ if (permissionStatus.state !== "granted") {
3471
+ stream.current = yield navigator.mediaDevices.getUserMedia(constraints);
3472
+ onChange();
3473
+ permissionGranted.current = true;
3474
+ } else {
3475
+ permissionGranted.current = false;
3476
+ }
3477
+ return permissionGranted.current;
3478
+ }), [onChange, isSupported, constraints]);
3408
3479
  useEffect(() => {
3409
- let mounted = true;
3410
- const onChange = () => {
3411
- navigator.mediaDevices.enumerateDevices().then((devices) => {
3412
- if (mounted) {
3413
- setState({
3414
- devices: devices.map(({ deviceId, groupId, kind, label }) => ({
3415
- deviceId,
3416
- groupId,
3417
- kind,
3418
- label
3419
- }))
3420
- });
3421
- }
3422
- }).catch(noop);
3423
- };
3480
+ if (!isSupported) {
3481
+ return;
3482
+ }
3483
+ if (requestPermissions) {
3484
+ ensurePermissions();
3485
+ }
3424
3486
  on(navigator.mediaDevices, "devicechange", onChange);
3425
3487
  onChange();
3426
3488
  return () => {
3427
- mounted = false;
3428
3489
  off(navigator.mediaDevices, "devicechange", onChange);
3429
3490
  };
3430
- }, []);
3431
- return state;
3491
+ }, [onChange, isSupported, requestPermissions, ensurePermissions]);
3492
+ return [state, ensurePermissions];
3432
3493
  }
3433
- const useMediaDevicesMock = () => ({ devices: [] });
3494
+ const useMediaDevicesMock = () => [{ devices: [] }, () => {
3495
+ }];
3434
3496
  var index$3 = isNavigator && !!navigator.mediaDevices ? useMediaDevices : useMediaDevicesMock;
3435
3497
 
3436
3498
  function useTextDirection(options = {}) {
@@ -3931,16 +3993,16 @@ function useIntersectionObserver(target, callback, options = {}) {
3931
3993
  }
3932
3994
  }, []);
3933
3995
  useDeepCompareEffect(() => {
3934
- if (!element.current) {
3996
+ if (!element) {
3935
3997
  return;
3936
3998
  }
3937
3999
  observerRef.current = new IntersectionObserver(
3938
4000
  savedCallback.current,
3939
4001
  options
3940
4002
  );
3941
- observerRef.current.observe(element.current);
4003
+ observerRef.current.observe(element);
3942
4004
  return stop;
3943
- }, [options, element.current]);
4005
+ }, [options, element]);
3944
4006
  return stop;
3945
4007
  }
3946
4008
 
@@ -3987,13 +4049,13 @@ function useResizeObserver(target, callback, options = {}) {
3987
4049
  }
3988
4050
  }, []);
3989
4051
  useDeepCompareEffect(() => {
3990
- if (!element.current) {
4052
+ if (!element) {
3991
4053
  return;
3992
4054
  }
3993
4055
  observerRef.current = new ResizeObserver(savedCallback.current);
3994
- observerRef.current.observe(element.current, options);
4056
+ observerRef.current.observe(element, options);
3995
4057
  return stop;
3996
- }, [options, element.current]);
4058
+ }, [options, element]);
3997
4059
  return stop;
3998
4060
  }
3999
4061
 
@@ -4223,16 +4285,16 @@ function useInfiniteScroll(target, onLoadMore, options = {}) {
4223
4285
  useUpdateEffect(() => {
4224
4286
  const opts = latestOptions.current;
4225
4287
  const fn = () => __async$3(this, null, function* () {
4226
- var _a2, _b2, _c, _d;
4288
+ var _a2, _b2;
4227
4289
  const previous = {
4228
- height: (_b2 = (_a2 = element.current) == null ? void 0 : _a2.scrollHeight) != null ? _b2 : 0,
4229
- width: (_d = (_c = element.current) == null ? void 0 : _c.scrollWidth) != null ? _d : 0
4290
+ height: (_a2 = element == null ? void 0 : element.scrollHeight) != null ? _a2 : 0,
4291
+ width: (_b2 = element == null ? void 0 : element.scrollWidth) != null ? _b2 : 0
4230
4292
  };
4231
4293
  yield savedLoadMore.current(state);
4232
- if (opts.preserveScrollPosition && element.current) {
4233
- element.current.scrollTo({
4234
- top: element.current.scrollHeight - previous.height,
4235
- left: element.current.scrollWidth - previous.width
4294
+ if (opts.preserveScrollPosition && element) {
4295
+ element.scrollTo({
4296
+ top: element.scrollHeight - previous.height,
4297
+ left: element.scrollWidth - previous.width
4236
4298
  });
4237
4299
  }
4238
4300
  });
@@ -4274,7 +4336,7 @@ function useMousePressed(target, options = {}) {
4274
4336
  const { touch = true, drag = true, initialValue = false } = options;
4275
4337
  const [pressed, setPressed] = useState(initialValue);
4276
4338
  const [sourceType, setSourceType] = useState(null);
4277
- const elementRef = useLatestElement(target);
4339
+ const element = useLatestElement(target);
4278
4340
  const onPressed = useCallback(
4279
4341
  (srcType) => () => {
4280
4342
  setPressed(true);
@@ -4290,7 +4352,6 @@ function useMousePressed(target, options = {}) {
4290
4352
  useEventListener("mouseleave", onReleased, () => window, { passive: true });
4291
4353
  useEventListener("mouseup", onReleased, () => window, { passive: true });
4292
4354
  useEffect(() => {
4293
- const element = elementRef.current;
4294
4355
  if (drag) {
4295
4356
  element == null ? void 0 : element.addEventListener("dragstart", onPressed("mouse"), {
4296
4357
  passive: true
@@ -4325,7 +4386,7 @@ function useMousePressed(target, options = {}) {
4325
4386
  element == null ? void 0 : element.removeEventListener("touchcancel", onReleased);
4326
4387
  }
4327
4388
  };
4328
- }, [drag, onPressed, onReleased, touch, elementRef.current]);
4389
+ }, [drag, onPressed, onReleased, touch, element]);
4329
4390
  return [pressed, sourceType];
4330
4391
  }
4331
4392
 
@@ -4344,32 +4405,32 @@ function useScrollLock(target, initialState = false) {
4344
4405
  const initialOverflowRef = useRef("scroll");
4345
4406
  const element = useLatestElement(target);
4346
4407
  useEffect(() => {
4347
- if (element.current) {
4348
- initialOverflowRef.current = element.current.style.overflow;
4408
+ if (element) {
4409
+ initialOverflowRef.current = element.style.overflow;
4349
4410
  if (locked) {
4350
- element.current.style.overflow = "hidden";
4411
+ element.style.overflow = "hidden";
4351
4412
  }
4352
4413
  }
4353
- }, [locked, element.current]);
4414
+ }, [locked, element]);
4354
4415
  const lock = useEvent(() => {
4355
- if (!element.current || locked) {
4416
+ if (!element || locked) {
4356
4417
  return;
4357
4418
  }
4358
4419
  if (isIOS) {
4359
- element.current.addEventListener("touchmove", preventDefault, {
4420
+ element.addEventListener("touchmove", preventDefault, {
4360
4421
  passive: false
4361
4422
  });
4362
4423
  }
4363
4424
  setLocked(true);
4364
4425
  });
4365
4426
  const unlock = useEvent(() => {
4366
- if (!element.current || !locked) {
4427
+ if (!element || !locked) {
4367
4428
  return;
4368
4429
  }
4369
4430
  if (isIOS) {
4370
- element.current.removeEventListener("touchmove", preventDefault);
4431
+ element.removeEventListener("touchmove", preventDefault);
4371
4432
  }
4372
- element.current.style.overflow = initialOverflowRef.current;
4433
+ element.style.overflow = initialOverflowRef.current;
4373
4434
  setLocked(false);
4374
4435
  });
4375
4436
  const set = useEvent((flag) => {
@@ -4809,11 +4870,11 @@ function useClickOutSide(target, handler) {
4809
4870
  const savedHandler = useLatest(handler);
4810
4871
  const element = useLatestElement(target);
4811
4872
  const listener = (event) => {
4812
- if (!element.current) {
4873
+ if (!element) {
4813
4874
  return;
4814
4875
  }
4815
4876
  const elements = event.composedPath();
4816
- if (element.current === event.target || elements.includes(element.current)) {
4877
+ if (element === event.target || elements.includes(element)) {
4817
4878
  return;
4818
4879
  }
4819
4880
  savedHandler.current(event);
@@ -5058,7 +5119,7 @@ function useScrollIntoView({
5058
5119
  const scrollIntoView = useEvent(
5059
5120
  ({ alignment = "start" } = {}) => {
5060
5121
  var _a;
5061
- const parent = getTargetElement(scrollElement) || getScrollParent(axis, element.current);
5122
+ const parent = getTargetElement(scrollElement) || getScrollParent(axis, element);
5062
5123
  shouldStop.current = false;
5063
5124
  if (frameID.current) {
5064
5125
  cancel();
@@ -5066,7 +5127,7 @@ function useScrollIntoView({
5066
5127
  const start = (_a = getScrollStart({ parent, axis })) != null ? _a : 0;
5067
5128
  const change = getRelativePosition({
5068
5129
  parent,
5069
- target: element.current,
5130
+ target: element,
5070
5131
  axis,
5071
5132
  alignment,
5072
5133
  offset,
@@ -5120,10 +5181,10 @@ const useSticky = ({
5120
5181
  const [isSticky, setSticky] = useState(false);
5121
5182
  const element = useLatestElement(targetElement);
5122
5183
  const { run: scrollHandler } = useThrottleFn(() => {
5123
- if (!element.current) {
5184
+ if (!element) {
5124
5185
  return;
5125
5186
  }
5126
- const rect = element.current.getBoundingClientRect();
5187
+ const rect = element.getBoundingClientRect();
5127
5188
  if (axis === "y") {
5128
5189
  setSticky((rect == null ? void 0 : rect.top) <= nav);
5129
5190
  } else {
@@ -5131,8 +5192,8 @@ const useSticky = ({
5131
5192
  }
5132
5193
  }, 50);
5133
5194
  useEffect(() => {
5134
- const scrollParent = getTargetElement(scrollElement) || getScrollParent(axis, element.current);
5135
- if (!element.current || !scrollParent) {
5195
+ const scrollParent = getTargetElement(scrollElement) || getScrollParent(axis, element);
5196
+ if (!element || !scrollParent) {
5136
5197
  return;
5137
5198
  }
5138
5199
  scrollParent.addEventListener("scroll", scrollHandler);
@@ -5214,15 +5275,6 @@ const useCountDown = (time, format = getHMSTime, callback) => {
5214
5275
  return [hour, minute, secoud];
5215
5276
  };
5216
5277
 
5217
- function useSupported(callback, sync = false) {
5218
- const [supported, setSupported] = useState(false);
5219
- const effect = sync ? useIsomorphicLayoutEffect : useEffect;
5220
- effect(() => {
5221
- setSupported(Boolean(callback()));
5222
- }, []);
5223
- return supported;
5224
- }
5225
-
5226
5278
  function useTextSelection() {
5227
5279
  const [selection, setSelection] = useState(null);
5228
5280
  const forceUpdate = useUpdate();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactuses/core",
3
- "version": "2.2.9",
3
+ "version": "3.0.1",
4
4
  "license": "Unlicense",
5
5
  "homepage": "https://www.reactuse.com/",
6
6
  "repository": {