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

@warp-ds/core

Package Overview
Dependencies
Maintainers
7
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@warp-ds/core - npm Package Compare versions

Comparing version 1.0.2 to 1.1.0

44

dist/attention/utils/helpers.d.ts

@@ -1,21 +0,5 @@

type Directions = "top" | "right" | "bottom" | "left";
export declare const opposites: {
top: string;
bottom: string;
left: string;
right: string;
};
export declare const arrowLabels: {
top: string;
bottom: string;
left: string;
right: string;
};
export declare const directions: string[];
export declare const rotation: {
left: number;
top: number;
right: number;
bottom: number;
};
import { ReferenceElement } from '@floating-ui/dom';
export type Directions = 'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end';
export declare const directions: Directions[];
export declare const opposites: Record<Directions, Directions>;
export type AttentionState = {

@@ -25,17 +9,15 @@ isShowing?: boolean;

actualDirection?: Directions;
directionName: Directions;
directionName?: Directions;
arrowEl?: HTMLElement | null;
attentionEl?: HTMLElement | null;
targetEl?: unknown;
top?: Boolean;
right?: Boolean;
bottom?: Boolean;
left?: Boolean;
tooltip?: Boolean;
popover?: Boolean;
callout?: Boolean;
flip?: Boolean;
fallbackPlacements?: Directions[];
targetEl?: ReferenceElement | null;
noArrow?: Boolean;
distance?: number;
skidding?: number;
waitForDOM?: () => void;
};
export declare function useRecompute(state: AttentionState): Promise<void>;
export {};
export declare const arrowDirectionClassname: (dir: Directions) => Directions;
export declare function useRecompute(state: AttentionState): Promise<void | AttentionState>;
export declare const autoUpdatePosition: (state: AttentionState) => (() => void) | undefined;

@@ -1,28 +0,85 @@

import { computePosition, flip, offset, shift, arrow } from "@floating-ui/dom";
const TOP = "top";
const BOTTOM = "bottom";
const LEFT = "left";
const RIGHT = "right";
import { computePosition, flip, offset, shift, arrow, autoUpdate, autoPlacement, } from '@floating-ui/dom';
const TOP_START = 'top-start';
const TOP = 'top';
const TOP_END = 'top-end';
const RIGHT_START = 'right-start';
const RIGHT = 'right';
const RIGHT_END = 'right-end';
const BOTTOM_START = 'bottom-start';
const BOTTOM = 'bottom';
const BOTTOM_END = 'bottom-end';
const LEFT_START = 'left-start';
const LEFT = 'left';
const LEFT_END = 'left-end';
export const directions = [
TOP_START,
TOP,
TOP_END,
RIGHT_START,
RIGHT,
RIGHT_END,
BOTTOM_START,
BOTTOM,
BOTTOM_END,
LEFT_START,
LEFT,
LEFT_END
];
export const opposites = {
[TOP_START]: BOTTOM_START,
[TOP]: BOTTOM,
[TOP_END]: BOTTOM_END,
[BOTTOM_START]: TOP_START,
[BOTTOM]: TOP,
[BOTTOM_END]: TOP_END,
[LEFT_START]: RIGHT_START,
[LEFT]: RIGHT,
[LEFT_END]: RIGHT_END,
[RIGHT_START]: LEFT_START,
[RIGHT]: LEFT,
[RIGHT_END]: LEFT_END,
};
export const arrowLabels = {
[TOP]: "↑",
[BOTTOM]: "↓",
[LEFT]: "←",
[RIGHT]: "→",
};
export const directions = [TOP, BOTTOM, LEFT, RIGHT];
export const rotation = {
const rotation = {
[LEFT_START]: -45,
[LEFT]: -45,
[LEFT_END]: -45,
[TOP_START]: 45,
[TOP]: 45,
[TOP_END]: 45,
[RIGHT_START]: 135,
[RIGHT]: 135,
[RIGHT_END]: 135,
[BOTTOM_START]: -135,
[BOTTOM]: -135,
[BOTTOM_END]: -135,
};
const middlePosition = "calc(50% - 7px)";
const isDirectionVertical = (name) => [TOP, BOTTOM].includes(name);
function computeCalloutArrow({ actualDirection, directionName, arrowEl, }) {
const middlePosition = 'calc(50% - 7px)';
const isDirectionVertical = (name) => [TOP_START, TOP, TOP_END, BOTTOM_START, BOTTOM, BOTTOM_END].includes(name);
export const arrowDirectionClassname = (dir) => {
let direction;
if (/-/.test(dir)) {
direction = dir
.split('-')
.map((d) => d.charAt(0).toUpperCase() + d.slice(1))
.join('');
}
else {
direction = dir.charAt(0).toUpperCase() + dir.slice(1);
}
return direction;
};
const side = (dir) => dir.split('-')[0];
const staticSide = (dir) => opposites[side(dir)];
const arrowDirection = (dir) => opposites[dir];
const arrowRotation = (dir) => rotation[arrowDirection(dir)];
const applyArrowStyles = (arrowEl, arrowRotation, dir) => {
Object.assign(arrowEl?.style, {
borderTopLeftRadius: '4px',
zIndex: 1,
// border alignment is off by a fraction of a pixel, this fixes it
[`margin${arrowDirectionClassname(staticSide(dir))}`]: '-0.5px',
transform: `rotate(${arrowRotation}deg)`,
});
};
function computeCalloutArrow({ actualDirection, directionName = BOTTOM, arrowEl, }) {
if (!arrowEl)

@@ -32,35 +89,94 @@ return;

const directionIsVertical = isDirectionVertical(directionName);
arrowEl.style.left = directionIsVertical ? middlePosition : "";
arrowEl.style.top = !directionIsVertical ? middlePosition : "";
Object.assign(arrowEl?.style || {}, {
left: directionIsVertical ? middlePosition : '',
top: !directionIsVertical ? middlePosition : '',
});
applyArrowStyles(arrowEl, arrowRotation(actualDirection), actualDirection);
}
export async function useRecompute(state) {
if (!state.isShowing)
if (!state?.isShowing)
return; // we're not currently showing the element, no reason to recompute
await state?.waitForDOM?.(); // wait for DOM to settle before computing
if (state.isCallout)
return computeCalloutArrow(state); // we don't move the callout box, only its arrow
const position = await computePosition(state.targetEl, state.attentionEl, {
placement: state.directionName,
if (state?.waitForDOM) {
await state?.waitForDOM(); // wait for DOM to settle before computing
}
if (state?.isCallout)
return computeCalloutArrow(state);
if (!state?.targetEl || !state?.attentionEl)
return;
const targetEl = state?.targetEl;
const attentionEl = state?.attentionEl;
computePosition(targetEl, attentionEl, {
placement: state?.directionName ?? BOTTOM,
middleware: [
// Should we make this configurable, but have these as sane defaults?
flip(),
offset(8),
offset({ mainAxis: state?.distance ?? 8, crossAxis: state?.skidding ?? 0 }),
state?.flip && flip({
fallbackAxisSideDirection: 'start',
fallbackPlacements: state?.fallbackPlacements,
}),
!state?.flip && autoPlacement(),
shift({ padding: 16 }),
// @ts-ignore
arrow({ element: state.noArrow ? undefined : state.arrowEl }), // FIXME
!state?.noArrow && state?.arrowEl && arrow({ element: state?.arrowEl }),
],
}).then(({ x, y, middlewareData, placement }) => {
state.actualDirection = placement;
Object.assign(attentionEl?.style, {
left: `${x}px`,
top: `${y}px`,
});
const isRtl = window.getComputedStyle(attentionEl).direction === 'rtl'; //checks whether the text direction of the attentionEl is right-to-left. Helps to calculate the position of the arrowEl and ensure proper alignment
const arrowPlacement = arrowDirection(placement).split('-')[1];
if (middlewareData?.arrow && state?.arrowEl) {
const arrowEl = state?.arrowEl;
const { x, y } = middlewareData?.arrow;
let top = '';
let right = '';
let bottom = '';
let left = '';
// calculates the arrow-position depending on if placement has 'start' or 'end':
if (arrowPlacement === 'start') {
const value = typeof x === 'number'
? `calc(33px - ${arrowEl?.offsetWidth / 2}px)`
: '';
top =
typeof y === 'number'
? `calc(33px - ${arrowEl?.offsetWidth / 2}px)`
: '';
right = isRtl ? value : '';
left = isRtl ? '' : value;
}
else if (arrowPlacement === 'end') {
const value = typeof x === 'number'
? `calc(33px - ${arrowEl?.offsetWidth / 2}px)`
: '';
right = isRtl ? '' : value;
left = isRtl ? value : '';
bottom =
typeof y === 'number'
? `calc(33px - ${arrowEl?.offsetWidth / 2}px)`
: '';
}
else {
left = typeof x === 'number' ? `${x}px` : '';
top = typeof y === 'number' ? `${y}px` : '';
}
Object.assign(arrowEl?.style || {}, {
top,
right,
bottom,
left,
});
applyArrowStyles(arrowEl, arrowRotation(placement), placement);
}
});
// @ts-ignore
state.actualDirection = position.placement;
Object.assign(state.attentionEl?.style || {}, {
left: "0",
top: "0",
transform: `translate3d(${Math.round(position.x)}px, ${Math.round(position.y)}px, 0)`,
return state;
}
export const autoUpdatePosition = (state) => {
// computePosition is only run once, so we need to wrap autoUpdate() around useRecompute() in order to recompute the attentionEl's position
// autoUpdate adds event listeners that are triggered on resize and on scroll and will keep calling the useRecompute().
// autoUpdate returns a cleanup() function that removes the event listeners.
if (!state?.targetEl || !state?.attentionEl)
return;
return autoUpdate(state?.targetEl, state?.attentionEl, () => {
useRecompute(state);
});
// @ts-ignore
let { x, y } = position.middlewareData.arrow;
if (state.arrowEl) {
state.arrowEl.style.left = x ? x + "px" : "";
state.arrowEl.style.top = y ? y + "px" : "";
}
}
};

@@ -5,3 +5,3 @@ {

"description": "Shared business logic for JS implementations of Warp Design System",
"version": "1.0.2",
"version": "1.1.0",
"type": "module",

@@ -27,2 +27,5 @@ "exports": {

],
"peerDependencies": {
"@floating-ui/dom": "1.6.3"
},
"scripts": {

@@ -36,5 +39,2 @@ "commit": "cz",

"license": "Apache-2.0",
"dependencies": {
"@floating-ui/dom": "^0.5.0"
},
"devDependencies": {

@@ -41,0 +41,0 @@ "typescript": "^4.7.4",

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