Files
root f6fac6c4bc Fix bin/publish: copy docs.dist from project root
Fix bin/publish: use correct .env path for rspade_system
Fix bin/publish script: prevent grep exit code 1 from terminating script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 02:08:33 +00:00

456 lines
13 KiB
JavaScript
Executable File

import * as React from 'react';
import { useEffect } from 'react';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
const observerMap = new Map();
const RootIds = new WeakMap();
let rootId = 0;
let unsupportedValue = undefined;
/**
* What should be the default behavior if the IntersectionObserver is unsupported?
* Ideally the polyfill has been loaded, you can have the following happen:
* - `undefined`: Throw an error
* - `true` or `false`: Set the `inView` value to this regardless of intersection state
* **/
function defaultFallbackInView(inView) {
unsupportedValue = inView;
}
/**
* Generate a unique ID for the root element
* @param root
*/
function getRootId(root) {
if (!root) return '0';
if (RootIds.has(root)) return RootIds.get(root);
rootId += 1;
RootIds.set(root, rootId.toString());
return RootIds.get(root);
}
/**
* Convert the options to a string Id, based on the values.
* Ensures we can reuse the same observer when observing elements with the same options.
* @param options
*/
function optionsToId(options) {
return Object.keys(options).sort().filter(key => options[key] !== undefined).map(key => {
return `${key}_${key === 'root' ? getRootId(options.root) : options[key]}`;
}).toString();
}
function createObserver(options) {
// Create a unique ID for this observer instance, based on the root, root margin and threshold.
let id = optionsToId(options);
let instance = observerMap.get(id);
if (!instance) {
// Create a map of elements this observer is going to observe. Each element has a list of callbacks that should be triggered, once it comes into view.
const elements = new Map();
let thresholds;
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
var _elements$get;
// While it would be nice if you could just look at isIntersecting to determine if the component is inside the viewport, browsers can't agree on how to use it.
// -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0
const inView = entry.isIntersecting && thresholds.some(threshold => entry.intersectionRatio >= threshold); // @ts-ignore support IntersectionObserver v2
if (options.trackVisibility && typeof entry.isVisible === 'undefined') {
// The browser doesn't support Intersection Observer v2, falling back to v1 behavior.
// @ts-ignore
entry.isVisible = inView;
}
(_elements$get = elements.get(entry.target)) == null ? void 0 : _elements$get.forEach(callback => {
callback(inView, entry);
});
});
}, options); // Ensure we have a valid thresholds array. If not, use the threshold from the options
thresholds = observer.thresholds || (Array.isArray(options.threshold) ? options.threshold : [options.threshold || 0]);
instance = {
id,
observer,
elements
};
observerMap.set(id, instance);
}
return instance;
}
/**
* @param element - DOM Element to observe
* @param callback - Callback function to trigger when intersection status changes
* @param options - Intersection Observer options
* @param fallbackInView - Fallback inView value.
* @return Function - Cleanup function that should be triggered to unregister the observer
*/
function observe(element, callback, options = {}, fallbackInView = unsupportedValue) {
if (typeof window.IntersectionObserver === 'undefined' && fallbackInView !== undefined) {
const bounds = element.getBoundingClientRect();
callback(fallbackInView, {
isIntersecting: fallbackInView,
target: element,
intersectionRatio: typeof options.threshold === 'number' ? options.threshold : 0,
time: 0,
boundingClientRect: bounds,
intersectionRect: bounds,
rootBounds: bounds
});
return () => {// Nothing to cleanup
};
} // An observer with the same options can be reused, so lets use this fact
const {
id,
observer,
elements
} = createObserver(options); // Register the callback listener for this element
let callbacks = elements.get(element) || [];
if (!elements.has(element)) {
elements.set(element, callbacks);
}
callbacks.push(callback);
observer.observe(element);
return function unobserve() {
// Remove the callback from the callback list
callbacks.splice(callbacks.indexOf(callback), 1);
if (callbacks.length === 0) {
// No more callback exists for element, so destroy it
elements.delete(element);
observer.unobserve(element);
}
if (elements.size === 0) {
// No more elements are being observer by this instance, so destroy it
observer.disconnect();
observerMap.delete(id);
}
};
}
const _excluded = ["children", "as", "tag", "triggerOnce", "threshold", "root", "rootMargin", "onChange", "skip", "trackVisibility", "delay", "initialInView", "fallbackInView"];
function isPlainChildren(props) {
return typeof props.children !== 'function';
}
/**
## Render props
To use the `<InView>` component, you pass it a function. It will be called
whenever the state changes, with the new value of `inView`. In addition to the
`inView` prop, children also receive a `ref` that should be set on the
containing DOM element. This is the element that the IntersectionObserver will
monitor.
If you need it, you can also access the
[`IntersectionObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry)
on `entry`, giving you access to all the details about the current intersection
state.
```jsx
import { InView } from 'react-intersection-observer';
const Component = () => (
<InView>
{({ inView, ref, entry }) => (
<div ref={ref}>
<h2>{`Header inside viewport ${inView}.`}</h2>
</div>
)}
</InView>
);
export default Component;
```
## Plain children
You can pass any element to the `<InView />`, and it will handle creating the
wrapping DOM element. Add a handler to the `onChange` method, and control the
state in your own component. Any extra props you add to `<InView>` will be
passed to the HTML element, allowing you set the `className`, `style`, etc.
```jsx
import { InView } from 'react-intersection-observer';
const Component = () => (
<InView as="div" onChange={(inView, entry) => console.log('Inview:', inView)}>
<h2>Plain children are always rendered. Use onChange to monitor state.</h2>
</InView>
);
export default Component;
```
*/
class InView extends React.Component {
constructor(props) {
super(props);
this.node = null;
this._unobserveCb = null;
this.handleNode = node => {
if (this.node) {
// Clear the old observer, before we start observing a new element
this.unobserve();
if (!node && !this.props.triggerOnce && !this.props.skip) {
// Reset the state if we get a new node, and we aren't ignoring updates
this.setState({
inView: !!this.props.initialInView,
entry: undefined
});
}
}
this.node = node ? node : null;
this.observeNode();
};
this.handleChange = (inView, entry) => {
if (inView && this.props.triggerOnce) {
// If `triggerOnce` is true, we should stop observing the element.
this.unobserve();
}
if (!isPlainChildren(this.props)) {
// Store the current State, so we can pass it to the children in the next render update
// There's no reason to update the state for plain children, since it's not used in the rendering.
this.setState({
inView,
entry
});
}
if (this.props.onChange) {
// If the user is actively listening for onChange, always trigger it
this.props.onChange(inView, entry);
}
};
this.state = {
inView: !!props.initialInView,
entry: undefined
};
}
componentDidUpdate(prevProps) {
// If a IntersectionObserver option changed, reinit the observer
if (prevProps.rootMargin !== this.props.rootMargin || prevProps.root !== this.props.root || prevProps.threshold !== this.props.threshold || prevProps.skip !== this.props.skip || prevProps.trackVisibility !== this.props.trackVisibility || prevProps.delay !== this.props.delay) {
this.unobserve();
this.observeNode();
}
}
componentWillUnmount() {
this.unobserve();
this.node = null;
}
observeNode() {
if (!this.node || this.props.skip) return;
const {
threshold,
root,
rootMargin,
trackVisibility,
delay,
fallbackInView
} = this.props;
this._unobserveCb = observe(this.node, this.handleChange, {
threshold,
root,
rootMargin,
// @ts-ignore
trackVisibility,
// @ts-ignore
delay
}, fallbackInView);
}
unobserve() {
if (this._unobserveCb) {
this._unobserveCb();
this._unobserveCb = null;
}
}
render() {
if (!isPlainChildren(this.props)) {
const {
inView,
entry
} = this.state;
return this.props.children({
inView,
entry,
ref: this.handleNode
});
}
const _this$props = this.props,
{
children,
as,
tag
} = _this$props,
props = _objectWithoutPropertiesLoose(_this$props, _excluded);
return /*#__PURE__*/React.createElement(as || tag || 'div', _extends({
ref: this.handleNode
}, props), children);
}
}
InView.displayName = 'InView';
InView.defaultProps = {
threshold: 0,
triggerOnce: false,
initialInView: false
};
/**
* React Hooks make it easy to monitor the `inView` state of your components. Call
* the `useInView` hook with the (optional) [options](#options) you need. It will
* return an array containing a `ref`, the `inView` status and the current
* [`entry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry).
* Assign the `ref` to the DOM element you want to monitor, and the hook will
* report the status.
*
* @example
* ```jsx
* import React from 'react';
* import { useInView } from 'react-intersection-observer';
*
* const Component = () => {
* const { ref, inView, entry } = useInView({
* threshold: 0,
* });
*
* return (
* <div ref={ref}>
* <h2>{`Header inside viewport ${inView}.`}</h2>
* </div>
* );
* };
* ```
*/
function useInView({
threshold,
delay,
trackVisibility,
rootMargin,
root,
triggerOnce,
skip,
initialInView,
fallbackInView
} = {}) {
const unobserve = React.useRef();
const [state, setState] = React.useState({
inView: !!initialInView
});
const setRef = React.useCallback(node => {
if (unobserve.current !== undefined) {
unobserve.current();
unobserve.current = undefined;
} // Skip creating the observer
if (skip) return;
if (node) {
unobserve.current = observe(node, (inView, entry) => {
setState({
inView,
entry
});
if (entry.isIntersecting && triggerOnce && unobserve.current) {
// If it should only trigger once, unobserve the element after it's inView
unobserve.current();
unobserve.current = undefined;
}
}, {
root,
rootMargin,
threshold,
// @ts-ignore
trackVisibility,
// @ts-ignore
delay
}, fallbackInView);
}
}, // We break the rule here, because we aren't including the actual `threshold` variable
// eslint-disable-next-line react-hooks/exhaustive-deps
[// If the threshold is an array, convert it to a string so it won't change between renders.
// eslint-disable-next-line react-hooks/exhaustive-deps
Array.isArray(threshold) ? threshold.toString() : threshold, root, rootMargin, triggerOnce, skip, trackVisibility, fallbackInView, delay]);
/* eslint-disable-next-line */
useEffect(() => {
if (!unobserve.current && state.entry && !triggerOnce && !skip) {
// If we don't have a ref, then reset the state (unless the hook is set to only `triggerOnce` or `skip`)
// This ensures we correctly reflect the current state - If you aren't observing anything, then nothing is inView
setState({
inView: !!initialInView
});
}
});
const result = [setRef, state.inView, state.entry]; // Support object destructuring, by adding the specific values.
result.ref = result[0];
result.inView = result[1];
result.entry = result[2];
return result;
}
export { InView, InView as default, defaultFallbackInView, observe, useInView };
//# sourceMappingURL=react-intersection-observer.esm.js.map