Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More ā†’
Socket
Sign inDemoInstall
Socket

react-floater

Package Overview
Dependencies
Maintainers
1
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-floater - npm Package Compare versions

Comparing version 0.8.2 to 0.9.0

dist/index.d.mts

119

package.json
{
"name": "react-floater",
"version": "0.8.2",
"version": "0.9.0",
"description": "Floaters everywhere!",

@@ -25,48 +25,53 @@ "author": "Gil Barbara <gilbarbara@gmail.com>",

"homepage": "https://github.com/gilbarbara/react-floater#readme",
"main": "lib/index.js",
"module": "esm/index.js",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js"
}
},
"files": [
"esm",
"lib",
"dist",
"src"
],
"types": "lib",
"types": "dist/index.d.ts",
"sideEffects": false,
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
"react": "16.8 - 18",
"react-dom": "16.8 - 18"
},
"dependencies": {
"@popperjs/core": "^2.11.5",
"deepmerge-ts": "^4.2.1",
"exenv": "^1.2.2",
"is-lite": "^0.8.2",
"tree-changes-hook": "^0.9.1"
"@popperjs/core": "^2.11.8",
"deepmerge-ts": "^5.1.0",
"is-lite": "^0.9.3",
"tree-changes-hook": "^0.10.0"
},
"devDependencies": {
"@emotion/react": "^11.9.3",
"@emotion/styled": "^11.9.3",
"@gilbarbara/eslint-config": "^0.2.4",
"@gilbarbara/prettier-config": "^0.1.0",
"@gilbarbara/tsconfig": "^0.1.1",
"@gilbarbara/types": "^0.1.1",
"@size-limit/preset-small-lib": "^7.0.8",
"@testing-library/dom": "^8.13.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@gilbarbara/eslint-config": "^0.5.4",
"@gilbarbara/prettier-config": "^1.0.0",
"@gilbarbara/tsconfig": "^0.2.3",
"@gilbarbara/types": "^0.2.2",
"@size-limit/preset-small-lib": "^9.0.0",
"@swc/core": "^1.3.92",
"@testing-library/dom": "^9.3.3",
"@testing-library/jest-dom": "^6.1.3",
"@testing-library/react": "^14.0.0",
"@types/exenv": "^1.2.0",
"@types/jest": "^28.1.2",
"@types/node": "^18.0.0",
"@types/react": "^18.0.14",
"@types/react-dom": "^18.0.5",
"del-cli": "^4.0.1",
"@types/jest": "^29.5.5",
"@types/node": "^20.8.3",
"@types/react": "^18.2.25",
"@types/react-dom": "^18.2.11",
"del-cli": "^5.1.0",
"disable-scroll": "^0.6.0",
"husky": "^8.0.1",
"fix-tsup-cjs": "^1.2.0",
"husky": "^8.0.3",
"is-ci-cli": "^2.2.0",
"jest": "^28.1.1",
"jest-environment-jsdom": "^28.1.1",
"jest-extended": "^2.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-extended": "^4.0.1",
"jest-serializer-html": "^7.1.0",
"jest-watch-typeahead": "^1.1.0",
"jest-watch-typeahead": "^2.2.2",
"react": "^18.2.0",

@@ -76,23 +81,21 @@ "react-dom": "^18.2.0",

"repo-tools": "^0.2.2",
"size-limit": "^7.0.8",
"ts-jest": "^28.0.5",
"ts-node": "^10.8.1",
"type-fest": "^2.13.1",
"typescript": "^4.7.4",
"webpack": "^5.73.0"
"size-limit": "^9.0.0",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"tsup": "^7.2.0",
"type-fest": "^4.4.0",
"typescript": "^5.2.2",
"webpack": "^5.88.2"
},
"scripts": {
"build": "npm run clean && npm run build:cjs && npm run build:esm",
"build:cjs": "tsc",
"build:esm": "tsc -m es6 --outDir esm",
"watch:cjs": "npm run build:cjs -- -w",
"watch:esm": "npm run build:esm -- -w",
"clean": "del lib/* && del esm/*",
"lint": "eslint --ext .ts,.tsx src test",
"build": "npm run clean && tsup && fix-tsup-cjs",
"watch": "tsup --watch",
"clean": "del dist/*",
"lint": "eslint src test",
"test": "is-ci \"test:coverage\" \"test:watch\"",
"test:coverage": "jest --bail --coverage",
"test:watch": "jest --watchAll --verbose",
"typecheck": "tsc --noEmit",
"typecheck": "tsc -p test/tsconfig.json --noEmit",
"format": "prettier \"**/*.{js,jsx,json,yml,yaml,css,less,scss,ts,tsx,md,graphql,mdx}\" --write",
"validate": "npm run lint && npm run test:coverage && npm run build && npm run size",
"validate": "npm run lint && npm run typecheck && npm run test:coverage && npm run build && npm run size",
"size": "size-limit",

@@ -104,2 +107,14 @@ "storybook:dev": "start-storybook -p 6006",

},
"tsup": {
"dts": true,
"entry": [
"src/index.tsx"
],
"format": [
"cjs",
"esm"
],
"sourcemap": true,
"splitting": false
},
"eslintConfig": {

@@ -116,4 +131,4 @@ "extends": [

{
"name": "lib",
"path": "./lib/index.js",
"name": "commonjs",
"path": "./dist/index.js",
"limit": "20 kB"

@@ -123,3 +138,3 @@ },

"name": "esm",
"path": "./esm/index.js",
"path": "./dist/index.mjs",
"limit": "20 kB"

@@ -126,0 +141,0 @@ }

# React Floater
[![NPM version](https://badge.fury.io/js/react-floater.svg)](https://www.npmjs.com/package/react-floater) [![CI](https://github.com/gilbarbara/react-floater/actions/workflows/main.yml/badge.svg)](https://github.com/gilbarbara/react-floater/actions/workflows/main.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/a3457f536c0915c0935b/maintainability)](https://codeclimate.com/github/gilbarbara/react-floater/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/a3457f536c0915c0935b/test_coverage)](https://codeclimate.com/github/gilbarbara/react-floater/test_coverage)
[![NPM version](https://badge.fury.io/js/react-floater.svg)](https://www.npmjs.com/package/react-floater) [![CI](https://github.com/gilbarbara/react-floater/actions/workflows/main.yml/badge.svg)](https://github.com/gilbarbara/react-floater/actions/workflows/main.yml) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=gilbarbara_react-floater&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=gilbarbara_react-floater) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=gilbarbara_react-floater&metric=coverage)](https://sonarcloud.io/summary/new_code?id=gilbarbara_react-floater)

@@ -17,4 +17,4 @@ Advanced tooltips for React!

```bash
npm install --save react-floater
```shell
npm install react-floater
```

@@ -24,3 +24,3 @@

```jsx
```tsx
import Floater from 'react-floater';

@@ -37,123 +37,157 @@

You can use your own components to render the Floater with the prop `component`.
Check `WithStyledComponents.js` in the [demo](https://codesandbox.io/s/github/gilbarbara/react-floater/tree/main/demo) for an example.
You can use a custom component to render the Floater with the `component` prop.
Check `WithStyledComponents.ts` in the [demo](https://codesandbox.io/s/github/gilbarbara/react-floater/tree/main/demo) for an example.
If you use your own components as `children` it will receive an `innerRef` prop that you must set in your HTMLElement:
```typescript jsx
const Button = ({ innerRef, ...rest }) => <button ref={innerRef} {...rest} />;
<Floater content="This is the Floater content">
<Button>click me</Button>
</Floater>;
```
This works with styled-components (and other css-in-js libraries):
```typescript jsx
const Wrapper = styled.div`
margin: 0 auto;
max-width: 500px;
line-height: 1.5;
`;
<Floater content="This is the Floater content">
<Wrapper>click me</Wrapper>
</Floater>;
```
## Props
**autoOpen?: boolean = `false`**
**autoOpen** `boolean` ā–¶ļøŽ false
Open the Floater automatically.
**callback?: (action: 'open' | 'close', props: Props)**
It will be called when the Floater change state.
**callback** `(action: 'open' | 'close', props: Props) => void`
It will be called when the Floater changes state.
**children: React.ReactNode**
**children** `ReactNode`
An element to trigger the Floater.
**component** {element|function}
A React component or function to as a custom UI for the Floater.
The prop `closeFloater` will be available in your component.
**component** `ComponentType | ReactElement`
A React element or function to use as a custom UI for the Floater.
The prop `closeFn` will be available in your component.
**content** {node}
**content** `ReactNode`
The Floater content. It can be anything that can be rendered.
_This is the only required props, unless you pass a_ `component`.
_This is required unless you pass a_ `component`.
**debug** {bool} ā–¶ļøŽ `false`
**debug** `boolean` ā–¶ļøŽ false
Log some basic actions.
_You can also set a global variable_ `ReactFloaterDebug = true;`
**disableFlip** {bool} ā–¶ļøŽ `false`
**disableFlip** `boolean` ā–¶ļøŽ false
Disable changes in the Floater position on scroll/resize.
**disableHoverToClick** {bool} ā–¶ļøŽ `false`
Don't convert _hover_ event to _click_ on mobile.
**disableHoverToClick** `boolean` ā–¶ļøŽ false
Don't convert the _hover_ event to _click_ on mobile.
**event** {string} ā–¶ļøŽ `click`
The event that will trigger the Floater. It can be `hover | click`.
_These won't work in controlled mode._
**event** `'hover' | 'click'` ā–¶ļøŽ click
The event that will trigger the Floater.
**eventDelay** {number} ā–¶ļøŽ `0.4`
The amount of time (in seconds) that the floater should wait after a `mouseLeave` event before hiding.
Only valid for event type `hover`.
> This won't work in a controlled mode.
**footer** {node}
**eventDelay** `number` ā–¶ļøŽ 0.4
The amount of time (in seconds) the floater should wait after a `mouseLeave` event before hiding.
> Only valid for event type `hover`.
**footer** `ReactNode`
It can be anything that can be rendered.
**getPopper** {function} Get the popper.js instance. It receives with 2 parameters:
**getPopper** `(popper: PopperInstance, origin: 'floater' | 'wrapper') => void`
Get the popper.js instance.
- **popper** {object} the popper object
- **origin** {object} `floater` or `wrapper`
**hideArrow** {bool} ā–¶ļøŽ `false`
**hideArrow** `boolean` ā–¶ļøŽ false
Don't show the arrow. Useful for centered or modal layout.
**offset** {number} ā–¶ļøŽ `15`
**offset** `number` ā–¶ļøŽ 15
The distance between the Floater and its target in pixels.
**open** {bool}
**open** `boolean`
The switch between normal and controlled modes.
_Setting this prop will disabled the normal behavior._
> Setting this prop will disable normal behavior.
**options** {object}
**modifiers** `PopperModifiers`
Customize popper.js modifiers.
_Don't use it unless you know what you're doing_
**placement** {string} ā–¶ļøŽ `bottom`
<details>
<summary>Type Definition</summary>
```typescript
interface PopperModifiers {
applyStyles?: Partial<ApplyStylesModifier>;
arrow?: Partial<ArrowModifier>;
computeStyles?: Partial<ComputeStylesModifier>;
eventListeners?: Partial<EventListenersModifier>;
flip?: Partial<FlipModifier>;
hide?: Partial<HideModifier>;
offset?: Partial<OffsetModifier>;
popperOffsets?: Partial<PopperOffsetsModifier>;
preventOverflow?: Partial<PreventOverflowModifier>;
}
```
</details>
> Don't use it unless you know what you're doing
**placement** `Placement` ā–¶ļøŽ `bottom`
The placement of the Floater. It will update the position if there's no space available.
It can be:
<details>
<summary>Type Definition</summary>
- top (top-start, top-end)
- bottom (bottom-start, bottom-end)
- left (left-start, left-end)
- right (right-start, right-end)
- auto
- center
```typescript
type Placement =
| "auto" | "auto-start" | "auto-end"
| "top" | "top-start" | "top-end"
| "bottom" | "bottom-start" | "bottom-end"
| "right"| "right-start" | "right-end"
| "left" | "left-start" | "left-end"
| "center"
```
**portalElement** {string|null|HTMLElement}
</details>
**portalElement** `string|HTMLElement`
A css selector or element to render the tooltips
**showCloseButton** {bool} ā–¶ļøŽ `false`
**showCloseButton** `boolean` ā–¶ļøŽ false
It will show a ā؉ button to close the Floater.
This will be `true` when you change `wrapperOptions` position.
This will be `true` when you change the `wrapperOptions` position.
**styles** {object} ā–¶ļøŽ `defaultStyles`
Customize the default UI.
**styles** `Styles`
Customize the UI.
**target** {object|string}
The target used to calculate the Floater position. If it's not set, it will use the `children` as the target.
<details>
<summary>Type Definition</summary>
**title** {node}
```typescript
interface Styles {
arrow: CSSProperties & {
length: number;
spread: number;
};
close: CSSProperties;
container: CSSProperties;
content: CSSProperties;
floater: CSSProperties;
floaterCentered: CSSProperties;
floaterClosing: CSSProperties;
floaterOpening: CSSProperties;
floaterWithAnimation: CSSProperties;
floaterWithComponent: CSSProperties;
footer: CSSProperties;
options: {
zIndex: number;
};
title: CSSProperties;
wrapper: CSSProperties;
wrapperPosition: CSSProperties;
}
```
</details>
**target** `string | HTMLElement`
The target element to calculate the Floater position. It will use the children as the target if it's not set.
**title** `ReactNode`
It can be anything that can be rendered.
**wrapperOptions** {WrapperOptions}
**wrapperOptions** `WrapperOptions`
Position the wrapper relative to the target.
_You need to set a `target` for this to work._
<details>
<summary>Type Definition</summary>
```typescript
interface WrapperOptions {
offset: number; // The distance between the wrapper and the target. It can be negative.
offset: number; // The distance between the wrapper and the target. It can be a negative value.
placement: string; // the same options as above, except center

@@ -164,6 +198,8 @@ position: bool; // Set to true to position the wrapper

</details>
## Styling
You can customize everything with the `styles` prop.
Only set the properties you want to change and the default styles will be merged.
Only set the properties you want to change, and the default styles will be merged.

@@ -177,3 +213,3 @@ Check the [styles.ts](src/modules/styles.ts) for the syntax.

```typescript jsx
```tsx
<Floater content="This is the Floater content">

@@ -185,5 +221,5 @@ <span>click me</span>

**Proxy**
The wrapper will trigger the events but the Floater will use the **target** prop to position itself.
The wrapper will trigger the events, but the Floater will use the **target** prop to position itself.
```typescript jsx
```tsx
<div className="App">

@@ -199,5 +235,5 @@ <img src="some-path" />

**Beacon**
The same as the **proxy mode** but the wrapper will be positioned relative to the `target`.
It is the same as the **proxy mode,** but the wrapper will be positioned relative to the `target`.
```typescript jsx
```tsx
<div className="App">

@@ -225,6 +261,6 @@ <img

**Controlled**
When you set a boolean to the `open` prop it will enter the controlled mode and it will not respond to events.
In this mode you don't even need to have `children`
Setting a boolean to the open prop will enter the controlled mode and not respond to events.
In this mode, you don't even need to have `children`
```typescript jsx
```tsx
<div className="App">

@@ -231,0 +267,0 @@ <img src="some-path" />

@@ -0,12 +1,16 @@

import * as React from 'react';
import { Modifier, Placement } from '@popperjs/core';
import { deepmerge } from 'deepmerge-ts';
import * as ExecutionEnvironment from 'exenv';
import is from 'is-lite';
import { SetRequired } from 'type-fest';
import { LogOptions, PopperModifiers, Props } from '../types';
export const { canUseDOM } = ExecutionEnvironment;
export const portalId = 'react-floater-portal';
export function enhanceProps(props: Props): Props {
export function canUseDOM(): boolean {
return !!(typeof window !== 'undefined' && window.document && window.document.createElement);
}
export function enhanceProps(props: Props) {
return {

@@ -29,3 +33,3 @@ autoOpen: false,

...props,
};
} satisfies SetRequired<Props, 'wrapperOptions'>;
}

@@ -63,3 +67,3 @@

return deepmerge(defaultOptions, modifiers || {}) as PopperModifiers;
return deepmerge(defaultOptions, modifiers ?? {});
}

@@ -89,2 +93,6 @@

export function isValidElement(object: unknown): object is React.ReactElement {
return React.isValidElement(object);
}
/**

@@ -124,3 +132,3 @@ * Log method calls if debug is enabled

): Partial<Modifier<any, any>> {
return deepmerge(modifier, customModifier || {});
return deepmerge(modifier, customModifier ?? {});
}

@@ -127,0 +135,0 @@

@@ -1,3 +0,2 @@

import { DependencyList, EffectCallback, useCallback, useEffect, useRef, useState } from 'react';
import { AnyObject } from '@gilbarbara/types';
import { DependencyList, EffectCallback, useEffect, useRef } from 'react';

@@ -13,20 +12,2 @@ function useEffectOnce(effect: EffectCallback) {

export function useSetState<T extends AnyObject>(
initialState: T = {} as T,
): [T, (patch: Partial<T> | ((previousState: T) => Partial<T>)) => void] {
const [state, set] = useState<T>(initialState);
const setState = useCallback(
(patch: Partial<T> | ((previousState: T) => Partial<T>)) => {
set(previousState => ({
...previousState,
...(patch instanceof Function ? patch(previousState) : patch),
}));
},
[set],
);
return [state, setState];
}
export function useSingleton(callback: () => void): void {

@@ -33,0 +14,0 @@ const hasBeenCalled = useRef(false);

@@ -11,3 +11,3 @@ import { deepmerge } from 'deepmerge-ts';

export default function getStyles(styles?: PartialDeep<Styles>): Styles {
const { options = {}, ...rest } = styles || {};
const { options = {}, ...rest } = styles ?? {};

@@ -14,0 +14,0 @@ return deepmerge(

@@ -1,2 +0,8 @@

import * as React from 'react';
import {
CSSProperties,
FunctionComponent,
MouseEventHandler,
ReactElement,
ReactNode,
} from 'react';
import { PartialDeep, RequireExactlyOne, ValueOf } from 'type-fest';

@@ -9,8 +15,11 @@

export type Action = 'open' | 'close';
export type HandlerFunction<T = HTMLElement> = (event: React.SyntheticEvent<T>) => void;
export type PlacementOptions = PopperPlacement | 'center';
export type PlainObject<T = any> = Record<string, T>;
export type CloseFunction<T = HTMLElement> = MouseEventHandler<T>;
export type Placement = PopperPlacement | 'center';
export type SelectorOrElement = string | null | HTMLElement;
export type Statuses = ValueOf<typeof STATUS>;
export interface CustomComponentProps {
closeFn: CloseFunction;
}
export interface LogOptions {

@@ -22,5 +31,3 @@ data: any;

export interface RenderProps {
closeFn: HandlerFunction;
}
export type FloaterComponent<T = CustomComponentProps> = FunctionComponent<T> | ReactElement<T>;

@@ -36,3 +43,3 @@ export interface BaseProps {

/* The element to have the Floater. */
children?: React.ReactNode;
children?: ReactNode;
/**

@@ -42,5 +49,5 @@ * A React element or function to be used as the custom UI for the Floater.

*/
component: React.FunctionComponent<RenderProps> | React.ReactElement;
component: FloaterComponent;
/* Anything that can be rendered. */
content: React.ReactNode;
content: ReactNode;
/**

@@ -74,3 +81,3 @@ * Log some actions.

/* Anything that can be rendered. */
footer?: React.ReactNode;
footer?: ReactNode;
/* The popper.js instance */

@@ -99,3 +106,3 @@ getPopper?: (popper: PopperInstance, origin: 'floater' | 'wrapper') => void;

*/
placement?: PlacementOptions;
placement?: Placement;
/* A custom element to render the tooltip */

@@ -108,3 +115,3 @@ portalElement?: SelectorOrElement;

showCloseButton?: boolean;
style?: React.CSSProperties;
style?: CSSProperties;
/* Customize the UI. */

@@ -115,3 +122,3 @@ styles?: PartialDeep<Styles>;

/* Anything that can be rendered. */
title?: React.ReactNode;
title?: ReactNode;
/* Position the wrapper relative to the target. */

@@ -128,3 +135,3 @@ wrapperOptions?: {

export interface State {
currentPlacement: PlacementOptions;
currentPlacement: Placement;
positionWrapper: boolean;

@@ -135,28 +142,23 @@ status: Statuses;

export interface CustomComponent {
children?: React.ReactNode;
closeFn: HandlerFunction;
}
export interface Styles {
arrow: React.CSSProperties & {
arrow: CSSProperties & {
length: number;
spread: number;
};
close: React.CSSProperties;
container: React.CSSProperties;
content: React.CSSProperties;
floater: React.CSSProperties;
floaterCentered: React.CSSProperties;
floaterClosing: React.CSSProperties;
floaterOpening: React.CSSProperties;
floaterWithAnimation: React.CSSProperties;
floaterWithComponent: React.CSSProperties;
footer: React.CSSProperties;
close: CSSProperties;
container: CSSProperties;
content: CSSProperties;
floater: CSSProperties;
floaterCentered: CSSProperties;
floaterClosing: CSSProperties;
floaterOpening: CSSProperties;
floaterWithAnimation: CSSProperties;
floaterWithComponent: CSSProperties;
footer: CSSProperties;
options: {
zIndex: number;
};
title: React.CSSProperties;
wrapper: React.CSSProperties;
wrapperPosition: React.CSSProperties;
title: CSSProperties;
wrapper: CSSProperties;
wrapperPosition: CSSProperties;
}

@@ -163,0 +165,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with āš”ļø by Socket Inc