@koine/react 1.0.87 → 1.0.89

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.
Files changed (51) hide show
  1. package/Autocomplete/AutocompleteMui.d.ts +1 -1
  2. package/Calendar/CalendarDaygridNav.d.ts +1 -1
  3. package/Calendar/CalendarDaygridTable.d.ts +1 -1
  4. package/Carousel/CarouselCss.d.ts +1 -6
  5. package/Details/Details.d.ts +1 -283
  6. package/Dialog/DialogMui.d.ts +1 -298
  7. package/Dialog/css/bare.d.ts +1 -298
  8. package/Dialog/m/bare.d.ts +1 -298
  9. package/Dialog/sc/bare.d.ts +1 -298
  10. package/Dialog/sc/framer.d.ts +1 -298
  11. package/Dialog/sc/framerMaterial.d.ts +1 -298
  12. package/Dialog/sc/material.d.ts +1 -298
  13. package/Dialog/tw/bare.d.ts +7 -304
  14. package/Dialog/tw/elegant.d.ts +7 -304
  15. package/Dialog/tw/framer.d.ts +3 -300
  16. package/Dialog/tw/framerMaterial.d.ts +5 -302
  17. package/Dialog/tw/material.d.ts +7 -304
  18. package/Form/Form.d.ts +2 -28
  19. package/Form/sc/bare.d.ts +2 -27
  20. package/Forms/Checkbox/Checkbox.d.ts +1 -1
  21. package/Forms/Field/FieldControl.d.ts +1 -1
  22. package/Forms/Input/Input.d.ts +1 -1
  23. package/Forms/Password/Password.d.ts +1 -1
  24. package/Forms/Radio/Radio.d.ts +1 -1
  25. package/Forms/Switch/Switch.d.ts +1 -1
  26. package/MenuItem/useMenuItem.d.ts +1 -1
  27. package/Tabs/TabsMui.d.ts +1 -279
  28. package/Tabs/tw/bare.d.ts +1 -279
  29. package/Tabs/tw/material.d.ts +7 -285
  30. package/helpers/createUseMediaQueryWidth.d.ts +6 -0
  31. package/helpers/createUseMediaQueryWidth.js +169 -0
  32. package/helpers/index.d.ts +1 -0
  33. package/helpers/index.js +1 -0
  34. package/helpers/mergeRefs.d.ts +3 -0
  35. package/helpers/mergeRefs.js +13 -0
  36. package/hooks/index.d.ts +3 -1
  37. package/hooks/index.js +3 -1
  38. package/hooks/useFixedOffset.d.ts +8 -0
  39. package/hooks/useFixedOffset.js +50 -0
  40. package/hooks/useMeasure.d.ts +27 -0
  41. package/hooks/useMeasure.js +163 -0
  42. package/hooks/useSmoothScroll.d.ts +2 -0
  43. package/hooks/useSmoothScroll.js +26 -0
  44. package/node/{hooks/useMediaQueryWidthCreator.js → helpers/createUseMediaQueryWidth.js} +4 -4
  45. package/node/helpers/index.js +1 -0
  46. package/node/helpers/mergeRefs.js +17 -0
  47. package/node/hooks/index.js +3 -1
  48. package/node/hooks/useFixedOffset.js +54 -0
  49. package/node/hooks/useMeasure.js +167 -0
  50. package/node/hooks/useSmoothScroll.js +30 -0
  51. package/package.json +11 -10
@@ -0,0 +1,6 @@
1
+ import { type GetMediaQueryWidthResolversBreakpoints } from "@koine/utils";
2
+ declare type _MediaQuerWidthDefExplicit<TBreakpoint extends string> = `min-${TBreakpoint}` | `max-${TBreakpoint}` | `up-${TBreakpoint}` | `down-${TBreakpoint}` | `between-${TBreakpoint}_${TBreakpoint}` | `only-${TBreakpoint}`;
3
+ export declare type MediaQuerWidthDef<TBreakpoint extends string> = `${TBreakpoint}` | _MediaQuerWidthDefExplicit<TBreakpoint>;
4
+ export declare type MediaQueryWidth<TBreakpoint extends string> = `@${MediaQuerWidthDef<TBreakpoint>}`;
5
+ export declare function createUseMediaQueryWidth<TBreakpointsConfig extends GetMediaQueryWidthResolversBreakpoints>(customBreakpoints: TBreakpointsConfig): <TBreakpoints extends Extract<keyof TBreakpointsConfig, string>>(media: `@${TBreakpoints}` | `@min-${TBreakpoints}` | `@max-${TBreakpoints}` | `@up-${TBreakpoints}` | `@down-${TBreakpoints}` | `@between-${TBreakpoints}_${TBreakpoints}` | `@only-${TBreakpoints}`) => boolean;
6
+ export default createUseMediaQueryWidth;
@@ -0,0 +1,169 @@
1
+ import { useState, useEffect, useMemo } from "react";
2
+ import { isBrowser, isUndefined, getMediaQueryWidthResolvers, } from "@koine/utils";
3
+ export function createUseMediaQueryWidth(customBreakpoints) {
4
+ var queryResolvers = getMediaQueryWidthResolvers(customBreakpoints);
5
+ return function useMediaQueryWidth(media) {
6
+ var definition = media.substring(1);
7
+ var _a = definition.split("-"), rule = _a[0], ruleBreakpoint = _a[1];
8
+ if (isUndefined(ruleBreakpoint)) {
9
+ ruleBreakpoint = rule;
10
+ }
11
+ if (isUndefined(rule)) {
12
+ rule = "min";
13
+ }
14
+ // with the hook creator approach these breakpoint types cannot be deduced
15
+ // const [br1, br2] = ruleBreakpoint.split("-") as Split<
16
+ // typeof ruleBreakpoint,
17
+ // "-"
18
+ // >;
19
+ var _b = ruleBreakpoint.split("_"), br1 = _b[0], br2 = _b[1];
20
+ var query = queryResolvers[rule](br1, br2);
21
+ var mq = useMemo(function () { return (isBrowser ? window.matchMedia(query) : { matches: false }); }, [query]);
22
+ var _c = useState(mq.matches), matches = _c[0], setMatches = _c[1];
23
+ useEffect(function () {
24
+ var mq = window.matchMedia(query);
25
+ var handleChange = function (event) {
26
+ setMatches(event.matches);
27
+ };
28
+ setMatches(mq.matches);
29
+ // Safari < 14 can't use addEventListener on a MediaQueryList
30
+ // https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList#Browser_compatibility
31
+ if (!mq.addEventListener) {
32
+ // Update the state whenever the media query match state changes
33
+ mq.addListener(handleChange);
34
+ // Clean up on unmount and if the query changes
35
+ return function () {
36
+ mq.removeListener(handleChange);
37
+ };
38
+ }
39
+ mq.addEventListener("change", handleChange);
40
+ return function () {
41
+ mq.removeEventListener("change", handleChange);
42
+ };
43
+ }, [query]);
44
+ return matches;
45
+ };
46
+ }
47
+ export default createUseMediaQueryWidth;
48
+ //// without creator it would be:
49
+ //// ---------------------------------------------------------------------------
50
+ // import { useState, useEffect, useMemo } from "react";
51
+ // import { isBrowser, type Split } from "@koine/utils";
52
+ // import { breakpoints as themeBreakpoints } from "@/config/theme/breakpoints";
53
+ // type Breakpoint = "xs" | "sm" | "md" | "lg" | "xl";
54
+ // type Breakpoints = Record<Breakpoint, number>;
55
+ // type MediaQuery =
56
+ // | `max:${Breakpoint}`
57
+ // | `min:${Breakpoint}`
58
+ // | `down:${Breakpoint}`
59
+ // | `up:${Breakpoint}`
60
+ // | `between:${Breakpoint}-${Breakpoint}`
61
+ // | `only:${Breakpoint}`;
62
+ // const breakpoints: Breakpoints = {
63
+ // xs: 0,
64
+ // ...themeBreakpoints,
65
+ // };
66
+ // const sortedBreakpointsNames = (
67
+ // Object.keys(breakpoints).map((key) => {
68
+ // const br = key as keyof typeof breakpoints;
69
+ // return [br, breakpoints[br]];
70
+ // }) as [Breakpoint, number][]
71
+ // )
72
+ // .sort((a, b) => a[1] - b[1])
73
+ // .map((item) => item[0]);
74
+ // const getNextBreakpoint = (breakpoint: Breakpoint) => {
75
+ // const index = sortedBreakpointsNames.indexOf(breakpoint);
76
+ // return sortedBreakpointsNames[index + 1];
77
+ // };
78
+ // /**
79
+ // * It behaves the same as `(min-width: ${value}px)`
80
+ // * where value is the given breakpoint value.
81
+ // * For ease of use this can be used both as a function `min("md")` and as an
82
+ // * object literal `min.md`.
83
+ // */
84
+ // const min = (br: Breakpoint) => `(min-width: ${breakpoints[br]}px)`;
85
+ // /**
86
+ // * It behaves the same as `(max-width: ${value}px)`
87
+ // * where value is the given breakpoint value.
88
+ // * For ease of use this can be used both as a function `max("md")` and as an
89
+ // * object literal `max.md`.
90
+ // */
91
+ // const max = (br: Breakpoint) => `(max-width: ${breakpoints[br] - 0.02}px)`;
92
+ // /**
93
+ // * It behaves the same as `min`
94
+ // * @inheritdoc {max}
95
+ // */
96
+ // const up = min;
97
+ // /**
98
+ // * It behaves similarly to `max` but you will use the "next" breakpoint,
99
+ // * specifying CSS that will apply from the given breakpoint and down.
100
+ // */
101
+ // const down = (br: Breakpoint) => {
102
+ // const brNext = getNextBreakpoint(br);
103
+ // // TODO: if br does not exists otherwise throw Error
104
+ // return brNext && `(max-width: ${breakpoints[brNext] - 0.02}px)`;
105
+ // };
106
+ // /**
107
+ // * Media query between the two given breakpoints
108
+ // */
109
+ // const between = (br1: Breakpoint, br2?: Breakpoint) => {
110
+ // return br2
111
+ // ? `(min-width: ${breakpoints[br1]}px) and (max-width: ${
112
+ // breakpoints[br2] - 0.02
113
+ // }px)`
114
+ // : min(br1);
115
+ // };
116
+ // /**
117
+ // * Media query to apply from the given breakpoint until the next, just for its
118
+ // * full range
119
+ // */
120
+ // const only = (br: Breakpoint) => {
121
+ // const brNext = getNextBreakpoint(br);
122
+ // return brNext ? between(br, brNext) : min(br);
123
+ // };
124
+ // const queryResolvers = {
125
+ // max,
126
+ // min,
127
+ // down,
128
+ // up,
129
+ // between,
130
+ // only,
131
+ // };
132
+ // export function useMqWidth(media: MediaQuery) {
133
+ // const [rule = "min", ruleBreakpoint] = media.split(":") as Split<
134
+ // MediaQuery,
135
+ // ":"
136
+ // >;
137
+ // const [br1, br2] = ruleBreakpoint.split("-") as Split<
138
+ // typeof ruleBreakpoint,
139
+ // "-"
140
+ // >;
141
+ // const query = queryResolvers[rule](br1, br2);
142
+ // const mq = useMemo(
143
+ // () => (isBrowser ? window.matchMedia(query) : { matches: false }),
144
+ // [query]
145
+ // );
146
+ // const [matches, setMatches] = useState(mq.matches);
147
+ // useEffect(() => {
148
+ // const mq = window.matchMedia(query);
149
+ // const handleChange = (event: MediaQueryListEvent) => {
150
+ // setMatches(event.matches);
151
+ // };
152
+ // setMatches(mq.matches);
153
+ // // Safari < 14 can't use addEventListener on a MediaQueryList
154
+ // // https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList#Browser_compatibility
155
+ // if (!mq.addEventListener) {
156
+ // // Update the state whenever the media query match state changes
157
+ // mq.addListener(handleChange);
158
+ // // Clean up on unmount and if the query changes
159
+ // return () => {
160
+ // mq.removeListener(handleChange);
161
+ // };
162
+ // }
163
+ // mq.addEventListener("change", handleChange);
164
+ // return () => {
165
+ // mq.removeEventListener("change", handleChange);
166
+ // };
167
+ // }, [query]);
168
+ // return matches;
169
+ // }
@@ -1,2 +1,3 @@
1
1
  export * from "./classed";
2
+ export * from "./createUseMediaQueryWidth";
2
3
  export * from "./extend-component";
package/helpers/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./classed";
2
+ export * from "./createUseMediaQueryWidth";
2
3
  export * from "./extend-component";
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ export declare function mergeRefs<T = Element>(refs: Array<React.MutableRefObject<T> | React.LegacyRef<T>>): React.RefCallback<T>;
3
+ export default mergeRefs;
@@ -0,0 +1,13 @@
1
+ export function mergeRefs(refs) {
2
+ return function (value) {
3
+ refs.forEach(function (ref) {
4
+ if (typeof ref === "function") {
5
+ ref(value);
6
+ }
7
+ else if (ref != null) {
8
+ ref.current = value;
9
+ }
10
+ });
11
+ };
12
+ }
13
+ export default mergeRefs;
package/hooks/index.d.ts CHANGED
@@ -2,14 +2,16 @@ export * from "./useAsyncFn";
2
2
  export * from "./useDateLocale";
3
3
  export * from "./useEffectOnce";
4
4
  export * from "./useFirstMountState";
5
+ export * from "./useFixedOffset";
5
6
  export * from "./useFocus";
6
7
  export * from "./useId";
7
8
  export * from "./useIsomorphicLayoutEffect";
8
- export * from "./useMediaQueryWidthCreator";
9
+ export * from "./useMeasure";
9
10
  export * from "./useMount";
10
11
  export * from "./useMountedState";
11
12
  export * from "./usePrevious";
12
13
  export * from "./useScrollPosition";
14
+ export * from "./useSmoothScroll";
13
15
  export * from "./useTraceUpdate";
14
16
  export * from "./useUpdateEffect";
15
17
  export * from "./useWindowSize";
package/hooks/index.js CHANGED
@@ -2,15 +2,17 @@ export * from "./useAsyncFn";
2
2
  export * from "./useDateLocale";
3
3
  export * from "./useEffectOnce";
4
4
  export * from "./useFirstMountState";
5
+ export * from "./useFixedOffset";
5
6
  export * from "./useFocus";
6
7
  export * from "./useId";
7
8
  export * from "./useIsomorphicLayoutEffect";
8
- export * from "./useMediaQueryWidthCreator";
9
+ export * from "./useMeasure";
9
10
  export * from "./useMount";
10
11
  export * from "./useMountedState";
11
12
  export * from "./usePrevious";
12
13
  export * from "./useScrollPosition";
13
14
  // export * from "./useScrollTo";
15
+ export * from "./useSmoothScroll";
14
16
  export * from "./useTraceUpdate";
15
17
  export * from "./useUpdateEffect";
16
18
  export * from "./useWindowSize";
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ /**
3
+ * Maybe use [ResizeObserver polyfill](https://github.com/juggle/resize-observer)
4
+ *
5
+ * @see https://web.dev/resize-observer/
6
+ */
7
+ export declare function useFixedOffset(): import("react").MutableRefObject<number>;
8
+ export default useFixedOffset;
@@ -0,0 +1,50 @@
1
+ import { useLayoutEffect, useRef } from "react";
2
+ import { injectCss, calculateFixedOffset, listenResize, $each, } from "@koine/dom";
3
+ import { debounce } from "@koine/utils";
4
+ var observer;
5
+ var inject = function (value) {
6
+ injectCss("useFixedOffset", "html{scroll-padding-top: ".concat(value, "px}"));
7
+ };
8
+ /**
9
+ * Maybe use [ResizeObserver polyfill](https://github.com/juggle/resize-observer)
10
+ *
11
+ * @see https://web.dev/resize-observer/
12
+ */
13
+ export function useFixedOffset() {
14
+ var fixedOffset = useRef(0);
15
+ useLayoutEffect(function () {
16
+ var update = function () {
17
+ var newFixedOffset = calculateFixedOffset();
18
+ fixedOffset.current = newFixedOffset;
19
+ // inject this CSS make the hashed deeplinks position the scroll at the
20
+ // right offset
21
+ inject(newFixedOffset);
22
+ };
23
+ update();
24
+ if (!observer && ResizeObserver) {
25
+ // const elements = $$("[data-fixed]");
26
+ observer = new ResizeObserver(function (entries) {
27
+ var newFixedOffset = 0;
28
+ entries.forEach(function (entry) {
29
+ newFixedOffset += entry.contentRect.height;
30
+ });
31
+ fixedOffset.current = newFixedOffset;
32
+ var updateOnResize = debounce(function () { return inject(newFixedOffset); }, 400);
33
+ updateOnResize();
34
+ });
35
+ $each("[data-fixed]", function ($el) {
36
+ if (observer)
37
+ observer.observe($el);
38
+ });
39
+ return function () {
40
+ observer === null || observer === void 0 ? void 0 : observer.disconnect();
41
+ };
42
+ }
43
+ else {
44
+ var listener = listenResize(update);
45
+ return listener;
46
+ }
47
+ }, []);
48
+ return fixedOffset;
49
+ }
50
+ export default useFixedOffset;
@@ -0,0 +1,27 @@
1
+ interface RectReadOnly {
2
+ readonly x: number;
3
+ readonly y: number;
4
+ readonly width: number;
5
+ readonly height: number;
6
+ readonly top: number;
7
+ readonly right: number;
8
+ readonly bottom: number;
9
+ readonly left: number;
10
+ [key: string]: number;
11
+ }
12
+ declare type HTMLOrSVGElement = HTMLElement | SVGElement;
13
+ export declare type UseMeasureOptions = {
14
+ scroll?: boolean;
15
+ };
16
+ export declare type UseMeasureReturn = [
17
+ (element: HTMLOrSVGElement | null) => void,
18
+ RectReadOnly,
19
+ () => void
20
+ ];
21
+ /**
22
+ * Use measure hook
23
+ *
24
+ * @borrows [pmndrs/react-use-measure](https://github.com/pmndrs/react-use-measure)
25
+ */
26
+ export declare function useMeasure(options?: UseMeasureOptions): UseMeasureReturn;
27
+ export default useMeasure;
@@ -0,0 +1,163 @@
1
+ import { __spreadArray } from "tslib";
2
+ import { useEffect, useState, useRef, useMemo } from "react";
3
+ import { debounce } from "@koine/utils";
4
+ import { listenResize, listenScroll, on, off } from "@koine/dom";
5
+ var observer;
6
+ // Adds native resize listener to window
7
+ function useOnWindowResize(onWindowResize) {
8
+ useEffect(function () {
9
+ var listener = listenResize(onWindowResize);
10
+ return listener;
11
+ }, [onWindowResize]);
12
+ }
13
+ function useOnWindowScroll(onScroll, enabled) {
14
+ useEffect(function () {
15
+ if (enabled) {
16
+ var listener = listenScroll(onScroll);
17
+ return listener;
18
+ }
19
+ return function () { return 0; };
20
+ }, [onScroll, enabled]);
21
+ }
22
+ // Returns a list of scroll offsets
23
+ function findScrollContainers(element) {
24
+ var result = [];
25
+ if (!element || element === document.body)
26
+ return result;
27
+ var _a = window.getComputedStyle(element), overflow = _a.overflow, overflowX = _a.overflowX, overflowY = _a.overflowY;
28
+ if ([overflow, overflowX, overflowY].some(function (prop) { return prop === "auto" || prop === "scroll"; }))
29
+ result.push(element);
30
+ return __spreadArray(__spreadArray([], result, true), findScrollContainers(element.parentElement), true);
31
+ }
32
+ var keys = [
33
+ "x",
34
+ "y",
35
+ "top",
36
+ "bottom",
37
+ "left",
38
+ "right",
39
+ "width",
40
+ "height",
41
+ ];
42
+ var areBoundsEqual = function (a, b) {
43
+ return keys.every(function (key) { return a[key] === b[key]; });
44
+ };
45
+ /**
46
+ * Use measure hook
47
+ *
48
+ * @borrows [pmndrs/react-use-measure](https://github.com/pmndrs/react-use-measure)
49
+ */
50
+ export function useMeasure(options) {
51
+ var _a = (options || {}).scroll /* offsetSize = false */, scroll = _a === void 0 ? false : _a /* offsetSize = false */;
52
+ var _b = useState({
53
+ left: 0,
54
+ top: 0,
55
+ width: 0,
56
+ height: 0,
57
+ bottom: 0,
58
+ right: 0,
59
+ x: 0,
60
+ y: 0,
61
+ }), bounds = _b[0], setBounds = _b[1];
62
+ // keep all state in a ref
63
+ var state = useRef([
64
+ // element
65
+ null,
66
+ // scrollContainers
67
+ null,
68
+ // resizeObserver
69
+ null,
70
+ // lastBounds
71
+ bounds,
72
+ ]);
73
+ // make sure to update state only as long as the component is truly mounted
74
+ var mounted = useRef(false);
75
+ useEffect(function () {
76
+ mounted.current = true;
77
+ return function () { return void (mounted.current = false); };
78
+ }, []);
79
+ // memoize handlers, so event-listeners know when they should update
80
+ var _c = useMemo(function () {
81
+ var callback = function () {
82
+ var _args = [];
83
+ for (var _i = 0; _i < arguments.length; _i++) {
84
+ _args[_i] = arguments[_i];
85
+ }
86
+ var _a = state.current, element = _a[0], lastBounds = _a[3];
87
+ if (!element)
88
+ return;
89
+ var size = element.getBoundingClientRect();
90
+ // if (element instanceof HTMLElement && offsetSize) {
91
+ // size.height = element.offsetHeight;
92
+ // size.width = element.offsetWidth;
93
+ // }
94
+ Object.freeze(size);
95
+ if (mounted.current && !areBoundsEqual(lastBounds, size)) {
96
+ state.current[3] = size;
97
+ setBounds(size);
98
+ }
99
+ };
100
+ var debouncedCallback = debounce(callback);
101
+ return [callback, debouncedCallback, debouncedCallback];
102
+ }, [setBounds /* , offsetSize */]), forceRefresh = _c[0] /* resizeChange */, scrollChange = _c[2];
103
+ // cleanup current scroll-listeners / observers
104
+ function removeListeners() {
105
+ var _a = state.current, scrollContainers = _a[1], resizeObserver = _a[2];
106
+ if (scrollContainers) {
107
+ scrollContainers.forEach(function (element) {
108
+ return off(element, "scroll", scrollChange);
109
+ });
110
+ state.current[1] = null;
111
+ }
112
+ if (resizeObserver) {
113
+ resizeObserver.disconnect();
114
+ state.current[2] = null;
115
+ }
116
+ }
117
+ // add scroll-listeners / observers
118
+ function addListeners() {
119
+ var _a = state.current, element = _a[0], scrollContainers = _a[1];
120
+ if (!element)
121
+ return;
122
+ if (!observer && ResizeObserver) {
123
+ observer = new ResizeObserver(scrollChange);
124
+ state.current[2] = observer;
125
+ observer.observe(element);
126
+ if (scroll && scrollContainers) {
127
+ scrollContainers.forEach(function (scrollContainer) {
128
+ return on(scrollContainer, "scroll", scrollChange, {
129
+ capture: true,
130
+ passive: true,
131
+ });
132
+ });
133
+ }
134
+ }
135
+ }
136
+ // the ref we expose to the user
137
+ var ref = function (node) {
138
+ if (!node || node === state.current[0])
139
+ return;
140
+ removeListeners();
141
+ state.current[0] = node;
142
+ state.current[1] = findScrollContainers(node);
143
+ addListeners();
144
+ };
145
+ // add general event listeners
146
+ useOnWindowScroll(forceRefresh, Boolean(scroll));
147
+ useOnWindowResize(forceRefresh);
148
+ // respond to changes that are relevant for the listeners
149
+ useEffect(function () {
150
+ removeListeners();
151
+ addListeners();
152
+ // eslint-disable-next-line react-hooks/exhaustive-deps
153
+ }, [scroll /* , scrollChange, resizeChange */]);
154
+ useEffect(function () {
155
+ // operate on mount, @kuus on the original version there is no call on mount?
156
+ forceRefresh();
157
+ // remove all listeners when the components unmounts
158
+ return removeListeners;
159
+ // eslint-disable-next-line react-hooks/exhaustive-deps
160
+ }, []);
161
+ return [ref, bounds, forceRefresh];
162
+ }
163
+ export default useMeasure;
@@ -0,0 +1,2 @@
1
+ export declare function useSmoothScroll(): (to?: number | string, offset?: number, callback?: () => void) => void;
2
+ export default useSmoothScroll;
@@ -0,0 +1,26 @@
1
+ import { useCallback } from "react";
2
+ import { isNumber } from "@koine/utils";
3
+ import { scrollTo } from "@koine/dom";
4
+ import { useFixedOffset } from "./useFixedOffset";
5
+ export function useSmoothScroll() {
6
+ var fixedOffset = useFixedOffset();
7
+ var scroll = useCallback(function (to, offset, callback) {
8
+ if (offset === void 0) { offset = 0; }
9
+ var top = undefined;
10
+ if (isNumber(to)) {
11
+ top = to;
12
+ }
13
+ else if (to) {
14
+ var el = document.getElementById(to);
15
+ if (el) {
16
+ top = el.getBoundingClientRect().top;
17
+ }
18
+ }
19
+ if (isNumber(top)) {
20
+ top = top + window.scrollY - (fixedOffset.current + offset);
21
+ scrollTo(top, callback);
22
+ }
23
+ }, [fixedOffset]);
24
+ return scroll;
25
+ }
26
+ export default useSmoothScroll;
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useMediaQueryWidthCreator = void 0;
3
+ exports.createUseMediaQueryWidth = void 0;
4
4
  var react_1 = require("react");
5
5
  var utils_1 = require("@koine/utils");
6
- function useMediaQueryWidthCreator(customBreakpoints) {
6
+ function createUseMediaQueryWidth(customBreakpoints) {
7
7
  var queryResolvers = (0, utils_1.getMediaQueryWidthResolvers)(customBreakpoints);
8
8
  return function useMediaQueryWidth(media) {
9
9
  var definition = media.substring(1);
@@ -47,8 +47,8 @@ function useMediaQueryWidthCreator(customBreakpoints) {
47
47
  return matches;
48
48
  };
49
49
  }
50
- exports.useMediaQueryWidthCreator = useMediaQueryWidthCreator;
51
- exports.default = useMediaQueryWidthCreator;
50
+ exports.createUseMediaQueryWidth = createUseMediaQueryWidth;
51
+ exports.default = createUseMediaQueryWidth;
52
52
  //// without creator it would be:
53
53
  //// ---------------------------------------------------------------------------
54
54
  // import { useState, useEffect, useMemo } from "react";
@@ -2,4 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  var tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./classed"), exports);
5
+ tslib_1.__exportStar(require("./createUseMediaQueryWidth"), exports);
5
6
  tslib_1.__exportStar(require("./extend-component"), exports);
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeRefs = void 0;
4
+ function mergeRefs(refs) {
5
+ return function (value) {
6
+ refs.forEach(function (ref) {
7
+ if (typeof ref === "function") {
8
+ ref(value);
9
+ }
10
+ else if (ref != null) {
11
+ ref.current = value;
12
+ }
13
+ });
14
+ };
15
+ }
16
+ exports.mergeRefs = mergeRefs;
17
+ exports.default = mergeRefs;
@@ -5,15 +5,17 @@ tslib_1.__exportStar(require("./useAsyncFn"), exports);
5
5
  tslib_1.__exportStar(require("./useDateLocale"), exports);
6
6
  tslib_1.__exportStar(require("./useEffectOnce"), exports);
7
7
  tslib_1.__exportStar(require("./useFirstMountState"), exports);
8
+ tslib_1.__exportStar(require("./useFixedOffset"), exports);
8
9
  tslib_1.__exportStar(require("./useFocus"), exports);
9
10
  tslib_1.__exportStar(require("./useId"), exports);
10
11
  tslib_1.__exportStar(require("./useIsomorphicLayoutEffect"), exports);
11
- tslib_1.__exportStar(require("./useMediaQueryWidthCreator"), exports);
12
+ tslib_1.__exportStar(require("./useMeasure"), exports);
12
13
  tslib_1.__exportStar(require("./useMount"), exports);
13
14
  tslib_1.__exportStar(require("./useMountedState"), exports);
14
15
  tslib_1.__exportStar(require("./usePrevious"), exports);
15
16
  tslib_1.__exportStar(require("./useScrollPosition"), exports);
16
17
  // export * from "./useScrollTo";
18
+ tslib_1.__exportStar(require("./useSmoothScroll"), exports);
17
19
  tslib_1.__exportStar(require("./useTraceUpdate"), exports);
18
20
  tslib_1.__exportStar(require("./useUpdateEffect"), exports);
19
21
  tslib_1.__exportStar(require("./useWindowSize"), exports);
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFixedOffset = void 0;
4
+ var react_1 = require("react");
5
+ var dom_1 = require("@koine/dom");
6
+ var utils_1 = require("@koine/utils");
7
+ var observer;
8
+ var inject = function (value) {
9
+ (0, dom_1.injectCss)("useFixedOffset", "html{scroll-padding-top: ".concat(value, "px}"));
10
+ };
11
+ /**
12
+ * Maybe use [ResizeObserver polyfill](https://github.com/juggle/resize-observer)
13
+ *
14
+ * @see https://web.dev/resize-observer/
15
+ */
16
+ function useFixedOffset() {
17
+ var fixedOffset = (0, react_1.useRef)(0);
18
+ (0, react_1.useLayoutEffect)(function () {
19
+ var update = function () {
20
+ var newFixedOffset = (0, dom_1.calculateFixedOffset)();
21
+ fixedOffset.current = newFixedOffset;
22
+ // inject this CSS make the hashed deeplinks position the scroll at the
23
+ // right offset
24
+ inject(newFixedOffset);
25
+ };
26
+ update();
27
+ if (!observer && ResizeObserver) {
28
+ // const elements = $$("[data-fixed]");
29
+ observer = new ResizeObserver(function (entries) {
30
+ var newFixedOffset = 0;
31
+ entries.forEach(function (entry) {
32
+ newFixedOffset += entry.contentRect.height;
33
+ });
34
+ fixedOffset.current = newFixedOffset;
35
+ var updateOnResize = (0, utils_1.debounce)(function () { return inject(newFixedOffset); }, 400);
36
+ updateOnResize();
37
+ });
38
+ (0, dom_1.$each)("[data-fixed]", function ($el) {
39
+ if (observer)
40
+ observer.observe($el);
41
+ });
42
+ return function () {
43
+ observer === null || observer === void 0 ? void 0 : observer.disconnect();
44
+ };
45
+ }
46
+ else {
47
+ var listener = (0, dom_1.listenResize)(update);
48
+ return listener;
49
+ }
50
+ }, []);
51
+ return fixedOffset;
52
+ }
53
+ exports.useFixedOffset = useFixedOffset;
54
+ exports.default = useFixedOffset;