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

@measured/dnd

Package Overview
Dependencies
Maintainers
3
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@measured/dnd - npm Package Compare versions

Comparing version 16.6.0-canary.7ed6934 to 16.6.0-canary.a2766de

src/state/auto-scroller/fluid-scroller/get-iframe-scroll.ts

1

dist/dnd.d.ts

@@ -224,2 +224,3 @@ import { Position } from 'css-box-model';

shouldRespectForcePress?: boolean;
disableSecondaryAnimation?: boolean;
}

@@ -226,0 +227,0 @@

16

package.json
{
"name": "@measured/dnd",
"version": "16.6.0-canary.7ed6934",
"version": "16.6.0-canary.a2766de",
"private": false,
"description": "Beautiful and accessible drag and drop for lists with React",
"author": "Alex Reardon <areardon@atlassian.com>",
"description": "Beautiful and accessible drag and drop for lists with React, with iframe and CSS transform support",
"author": "Measured Corporation Ltd <hello@measured.co>",
"maintainers": [
"Gabriel Santerre <gab@100terres.com>",
"Reece Carolan <reece@hellopangea.com>"
"Measured Corporation Ltd <hello@measured.co>"
],

@@ -25,6 +24,6 @@ "keywords": [

"type": "git",
"url": "https://github.com/hello-pangea/dnd.git"
"url": "https://github.com/measuredco/dnd.git"
},
"bugs": {
"url": "https://github.com/hello-pangea/dnd/issues"
"url": "https://github.com/measuredco/dnd/issues"
},

@@ -80,2 +79,3 @@ "main": "dist/dnd.cjs.js",

"css-box-model": "^1.2.1",
"lru-cache": "^10.2.0",
"memoize-one": "^6.0.0",

@@ -108,4 +108,4 @@ "raf-schd": "^4.0.3",

"@emotion/styled": "11.11.0",
"@jest/environment": "29.7.0",
"@measured/auto-frame-component": "0.1.0-canary.4686711",
"@jest/environment": "29.7.0",
"@release-it/conventional-changelog": "8.0.1",

@@ -112,0 +112,0 @@ "@rollup/plugin-babel": "6.0.4",

@@ -11,3 +11,3 @@ import rafSchd from 'raf-schd';

export interface PublicArgs {
scrollWindow: (change: Position) => void;
scrollWindow: (change: Position, win?: Window) => void;
scrollDroppable: (id: DroppableId, change: Position) => void;

@@ -14,0 +14,0 @@ getAutoScrollerOptions?: () => AutoScrollerOptions;

@@ -14,2 +14,3 @@ import type { Position, Rect } from 'css-box-model';

import { AutoScrollerOptions } from './auto-scroller-options-types';
import getIframeScroll from './get-iframe-scroll';

@@ -20,3 +21,3 @@ interface Args {

shouldUseTimeDampening: boolean;
scrollWindow: (scroll: Position) => void;
scrollWindow: (scroll: Position, win?: Window) => void;
scrollDroppable: (id: DroppableId, scroll: Position) => void;

@@ -56,2 +57,16 @@ getAutoScrollerOptions: () => AutoScrollerOptions;

const iframeScroll = getIframeScroll({
state,
dragStartTime,
shouldUseTimeDampening,
getAutoScrollerOptions,
draggable,
});
if (iframeScroll?.change) {
scrollWindow(iframeScroll.change, iframeScroll.window);
return;
}
const droppable: DroppableDimension | null = getBestScrollableDroppable({

@@ -58,0 +73,0 @@ center,

@@ -14,2 +14,3 @@ import type { BoxModel, Position } from 'css-box-model';

import getSubject from './util/get-subject';
import { Transform } from '../../view/transform';

@@ -34,2 +35,3 @@ export interface Closest {

closest?: Closest | null;
transform: Transform | null;
}

@@ -46,2 +48,3 @@

closest,
transform,
}: Args): DroppableDimension => {

@@ -100,2 +103,3 @@ const frame: Scrollable | null = (() => {

subject,
transform,
};

@@ -102,0 +106,0 @@

@@ -156,2 +156,3 @@ import type { BoxModel, Rect, Position } from 'css-box-model';

subject: DroppableSubject;
transform: Transform | null;
}

@@ -158,0 +159,0 @@ export interface DraggableLocation {

@@ -23,2 +23,3 @@ import type { Position } from 'css-box-model';

Combine,
DroppableDimension,
} from '../../types';

@@ -218,2 +219,3 @@ import type {

snapshot: getSecondarySnapshot(null),
sourceDroppable: null,
},

@@ -239,2 +241,3 @@ };

dimension?: DraggableDimension,
sourceDroppable?: DroppableDimension | null,
): MapProps => ({

@@ -248,2 +251,3 @@ mapped: {

dimension,
sourceDroppable: sourceDroppable || null,
},

@@ -257,5 +261,6 @@ }),

combineTargetFor?: DraggableId | null,
disableSecondaryAnimation?: boolean,
): MapProps | null => {
return combineTargetFor
? getMemoizedProps(origin, combineTargetFor, true)
? getMemoizedProps(origin, combineTargetFor, !disableSecondaryAnimation)
: null;

@@ -270,2 +275,4 @@ };

dimension?: DraggableDimension,
sourceDroppable?: DroppableDimension | null,
disableSecondaryAnimation?: boolean,
): MapProps | null => {

@@ -284,3 +291,3 @@ const visualDisplacement: Displacement | null =

if (!isAfterCriticalInVirtualList) {
return getFallback(combineTargetFor);
return getFallback(combineTargetFor, disableSecondaryAnimation);
}

@@ -302,3 +309,9 @@

const offset: Position = memoizedOffset(change.x, change.y);
return getMemoizedProps(offset, combineTargetFor, true, dimension);
return getMemoizedProps(
offset,
combineTargetFor,
!disableSecondaryAnimation,
dimension,
sourceDroppable,
);
}

@@ -318,4 +331,5 @@

combineTargetFor,
visualDisplacement.shouldAnimate,
disableSecondaryAnimation ? false : visualDisplacement.shouldAnimate,
dimension,
sourceDroppable,
);

@@ -337,2 +351,6 @@ };

const sourceDroppable = state.critical.droppable.id
? state.dimensions.droppables[state.critical.droppable.id]
: null;
return getProps(

@@ -344,2 +362,4 @@ ownProps.draggableId,

dimension,
sourceDroppable,
ownProps.disableSecondaryAnimation,
);

@@ -357,2 +377,6 @@ }

const sourceDroppable = completed.critical.droppable.id
? state.dimensions.droppables[completed.critical.droppable.id]
: null;
return getProps(

@@ -364,2 +388,4 @@ ownProps.draggableId,

dimension,
sourceDroppable,
ownProps.disableSecondaryAnimation,
);

@@ -381,7 +407,24 @@ }

const selector = (state: State, ownProps: OwnProps): MapProps =>
draggingSelector(state, ownProps) ||
secondarySelector(state, ownProps) ||
atRest;
const selector = (state: State, ownProps: OwnProps): MapProps => {
// Modify atRest based on props
const atRestLocal =
atRest.mapped.type === 'DRAGGING'
? atRest
: {
...atRest,
mapped: {
...atRest.mapped,
shouldAnimateDisplacement: ownProps.disableSecondaryAnimation
? false
: atRest.mapped.shouldAnimateDisplacement,
},
};
return (
draggingSelector(state, ownProps) ||
secondarySelector(state, ownProps) ||
atRestLocal
);
};
return selector;

@@ -388,0 +431,0 @@ };

@@ -16,2 +16,3 @@ import type { Position } from 'css-box-model';

DraggableRubric,
DroppableDimension,
} from '../../types';

@@ -144,2 +145,3 @@ import { dropAnimationFinished } from '../../state/action-creators';

dimension?: DraggableDimension;
sourceDroppable: DroppableDimension | null;
}

@@ -171,2 +173,3 @@

shouldRespectForcePress?: boolean;
disableSecondaryAnimation?: boolean;
}

@@ -173,0 +176,0 @@

@@ -14,3 +14,2 @@ import type { BoxModel } from 'css-box-model';

} from './draggable-types';
import { applyTransformPoint } from '../transform';

@@ -64,18 +63,10 @@ export const zIndexOptions: ZIndexOptions = {

const transformedOffset = dimension.transform
? applyTransformPoint(
offset.x,
offset.y,
{
...dimension.transform.matrix,
scaleX: 1 / dimension.transform.matrix.scaleX,
scaleY: 1 / dimension.transform.matrix.scaleY,
},
{ ...dimension.transform.origin },
)
: offset;
const untransformedOffset = {
x: offset.x / (dimension?.transform?.matrix.scaleX || 1),
y: offset.y / (dimension?.transform?.matrix.scaleY || 1),
};
const transform: string | undefined = isDropAnimating
? transforms.drop(transformedOffset, isCombining)
: transforms.moveTo(transformedOffset);
? transforms.drop(untransformedOffset, isCombining)
: transforms.moveTo(untransformedOffset);

@@ -113,10 +104,8 @@ const style: DraggingStyle = {

function getSecondaryStyle(secondary: SecondaryMapProps): NotDraggingStyle {
const { offset, sourceDroppable } = secondary;
return {
transform: transforms.moveTo({
x:
secondary.offset.x /
(secondary.dimension?.transform?.matrix.scaleX || 1),
y:
secondary.offset.y /
(secondary.dimension?.transform?.matrix.scaleY || 1),
x: offset.x / (sourceDroppable?.transform?.matrix.scaleX || 1),
y: offset.y / (sourceDroppable?.transform?.matrix.scaleY || 1),
}),

@@ -123,0 +112,0 @@ // transition style is applied in the head

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

import { IframeHTMLAttributes } from 'react';
import { querySelectorAll } from '../../query-selector-all';

@@ -21,2 +20,22 @@ import type {

let loaded = false;
function bindEvent(win: Window, binding: EventBinding, options: EventOptions) {
let timer: number | undefined;
if (!loaded) {
// Some browsers require us to defer binding events, i.e. Safari
timer = setInterval(() => {
if ((win as Window).document.readyState === 'complete') {
win.addEventListener(binding.eventName, binding.fn, options);
loaded = true;
}
}, 100);
} else {
win.addEventListener(binding.eventName, binding.fn, options);
}
return timer;
}
export default function bindEvents(

@@ -31,3 +50,3 @@ el: HTMLElement | Window,

window.document,
'iframe',
'[data-rfd-iframe]',
) as HTMLIFrameElement[];

@@ -42,5 +61,6 @@

win.addEventListener(binding.eventName, binding.fn, options);
const timer = bindEvent(win as Window, binding, options);
return function unbind() {
clearInterval(timer);
win.removeEventListener(binding.eventName, binding.fn, options);

@@ -47,0 +67,0 @@ };

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

import { LRUCache } from 'lru-cache';
import type { DraggableId, ContextId } from '../../types';

@@ -7,2 +8,7 @@ import { dragHandle as dragHandleAttr } from '../data-attributes';

const dragHandleCache = new LRUCache<string, HTMLElement>({
max: 5000,
ttl: 1000,
});
export default function findDragHandle(

@@ -15,2 +21,8 @@ contextId: ContextId,

const cachedHandle = dragHandleCache.get(selector);
if (cachedHandle) {
return cachedHandle;
}
const possible = querySelectorAllIframe(selector);

@@ -41,3 +53,5 @@

dragHandleCache.set(selector, handle);
return handle;
}

@@ -0,1 +1,9 @@

import { LRUCache } from 'lru-cache';
import { querySelectorAll } from '../../query-selector-all';
const iframeCache = new LRUCache<string, HTMLIFrameElement[]>({
max: 1,
ttl: 1000,
});
/**

@@ -6,8 +14,16 @@ * querySelectorAllIframe

*/
export default function querySelectorAllIframe(selector: string) {
let iframes = iframeCache.get('iframes');
import { querySelectorAll } from '../../query-selector-all';
if (!iframes) {
iframes = querySelectorAll(document, 'iframe') as HTMLIFrameElement[];
export default function querySelectorAllIframe(selector: string) {
const iframes = querySelectorAll(document, 'iframe') as HTMLIFrameElement[];
// Quicker than running the [data-rbd-frame] query
iframes = iframes.filter((iframe) =>
iframe.hasAttribute('data-rfd-iframe'),
);
iframeCache.set('iframes', iframes);
}
const iframePossible = iframes.reduce<HTMLElement[]>(

@@ -14,0 +30,0 @@ (acc, iframe) => [

@@ -101,2 +101,14 @@ import { BoxModel, Rect, Spacing } from 'css-box-model';

const defaultTransform = {
matrix: {
scaleX: 1,
scaleY: 1,
skewX: 0,
skewY: 0,
translateX: 0,
translateY: 0,
},
origin: { x: 0, y: 0 },
};
/**

@@ -117,3 +129,3 @@ * Gets the transform of the element based on transform styles

if (!transformEl) return null;
if (!transformEl) return defaultTransform;

@@ -132,3 +144,3 @@ const styles = window.getComputedStyle(transformEl);

return null;
return defaultTransform;
};

@@ -135,0 +147,0 @@

import { calculateBox, withScroll } from 'css-box-model';
import type { BoxModel, Position } from 'css-box-model';
import type { Position } from 'css-box-model';
import type {

@@ -20,3 +20,7 @@ DraggableDescriptor,

let client = calculateBox(el.getBoundingClientRect(), computedStyles);
const originalClient = calculateBox(
el.getBoundingClientRect(),
computedStyles,
);
let client = { ...originalClient };
let page = withScroll(

@@ -41,3 +45,3 @@ calculateBox(el.getBoundingClientRect(), computedStyles),

const placeholder: Placeholder = {
client,
client: originalClient,
tagName: el.tagName.toLowerCase(),

@@ -44,0 +48,0 @@ display: computedStyles.display,

@@ -13,3 +13,6 @@ import { getBox, withScroll, createBox, expand } from 'css-box-model';

import getScroll from './get-scroll';
import getOffsettedBox from '../iframe/get-offsetted-box';
import getIframeOffset from '../iframe/get-iframe-offset';
import { applyOffsetBox } from '../iframe/apply-offset';
import { Transform, applyTransformBox, getTransform } from '../transform';
import { Offset } from '../iframe/offset-types';

@@ -19,5 +22,15 @@ const getClient = (

closestScrollable?: Element | null,
offset?: Offset | null,
transform?: Transform | null,
): BoxModel => {
const base: BoxModel = getOffsettedBox(targetRef);
let base: BoxModel = getBox(targetRef);
if (transform) {
base = applyTransformBox(base, transform);
}
if (offset) {
base = applyOffsetBox(base, offset);
}
// Droppable has no scroll parent

@@ -85,2 +98,3 @@ if (!closestScrollable) {

shouldClipSubject: boolean;
transform: Transform | null;
}

@@ -99,3 +113,5 @@

const closestScrollable: Element | null = env.closestScrollable;
const client: BoxModel = getClient(ref, closestScrollable);
const offset = getIframeOffset(ref);
const transform = getTransform(ref, { x: 0, y: 0 });
const client: BoxModel = getClient(ref, closestScrollable, offset, transform);
const page: BoxModel = withScroll(client, windowScroll);

@@ -132,2 +148,3 @@

closest,
transform,
});

@@ -134,0 +151,0 @@

import type { Position } from 'css-box-model';
import { getTransform } from '../transform';

@@ -7,5 +8,10 @@ export default (el: Element): Position => {

if (isIframe) {
const targetEl = (el as HTMLIFrameElement).contentWindow!;
const win = (el as HTMLIFrameElement).contentWindow!;
return { x: targetEl.scrollX, y: targetEl.scrollY };
const transform = getTransform(el as HTMLElement);
return {
x: win.scrollX * (transform?.matrix.scaleX || 1),
y: win.scrollY * (transform?.matrix.scaleY || 1),
};
}

@@ -12,0 +18,0 @@

@@ -7,3 +7,3 @@ import { useRef } from 'react';

import { invariant } from '../../invariant';
import checkForNestedScrollContainers from './check-for-nested-scroll-container';
// import checkForNestedScrollContainers from './check-for-nested-scroll-container';
import * as dataAttr from '../data-attributes';

@@ -173,5 +173,5 @@ import { origin } from '../../state/position';

// print a debug warning if using an unsupported nested scroll container setup
if (process.env.NODE_ENV !== 'production') {
checkForNestedScrollContainers(scrollable);
}
// if (process.env.NODE_ENV !== 'production') {
// checkForNestedScrollContainers(scrollable);
// }
}

@@ -178,0 +178,0 @@

import { Position } from 'css-box-model';
import { applyTransformPoint, getMatrix, getOrigin } from '../../../transform';
import { applyTransformPoint, getTransform } from '../../../transform';

@@ -16,7 +16,4 @@ export default function offsetPoint(

const iframeStyles = window.getComputedStyle(iframe);
const transform = getTransform(iframe);
const transform = getMatrix(iframeStyles.transform);
const origin = getOrigin(iframeStyles.transformOrigin) || { x: 0, y: 0 };
offsetX = rect.left;

@@ -29,4 +26,4 @@ offsetY = rect.top;

y,
transform,
origin,
transform.matrix,
transform.origin,
);

@@ -33,0 +30,0 @@

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

import { useRef, MutableRefObject } from 'react';
import memoizeOne from 'memoize-one';

@@ -11,6 +10,7 @@ import { useMemo, useCallback } from 'use-memo-one';

import useLayoutEffect from '../use-isomorphic-layout-effect';
import { querySelectorAll } from '../../query-selector-all';
import querySelectorAllIframe from '../iframe/query-selector-all-iframe';
const getHead = (): HTMLHeadElement => {
const head: HTMLHeadElement | null = document.querySelector('head');
invariant(head, 'Cannot find the head to append a style to');
const getHead = (doc: Document): HTMLHeadElement | null => {
const head: HTMLHeadElement | null = doc.querySelector('head');
return head;

@@ -28,6 +28,7 @@ };

const alwaysDataAttr = `${prefix}-always`;
const dynamicDataAttr = `${prefix}-dynamic`;
export default function useStyleMarshal(contextId: ContextId, nonce?: string) {
const styles: Styles = useMemo(() => getStyles(contextId), [contextId]);
const alwaysRef = useRef<HTMLStyleElement | null>(null);
const dynamicRef = useRef<HTMLStyleElement | null>(null);

@@ -38,51 +39,83 @@ // eslint-disable-next-line react-hooks/exhaustive-deps

memoizeOne((proposed: string) => {
const el: HTMLStyleElement | null = dynamicRef.current;
invariant(el, 'Cannot set dynamic style element if it is not set');
el.textContent = proposed;
const selector = `[${dynamicDataAttr}="${contextId}"]`;
querySelectorAllIframe(selector).forEach((el) => {
invariant(el, 'Cannot set dynamic style element if it is not set');
el.textContent = proposed;
});
}),
[],
[contextId],
);
const setAlwaysStyle = useCallback((proposed: string) => {
const el: HTMLStyleElement | null = alwaysRef.current;
invariant(el, 'Cannot set dynamic style element if it is not set');
el.textContent = proposed;
}, []);
const setAlwaysStyle = useCallback(
(proposed: string) => {
const selector = `[${alwaysDataAttr}="${contextId}"]`;
querySelectorAllIframe(selector).forEach((el) => {
invariant(el, 'Cannot set dynamic style element if it is not set');
el.textContent = proposed;
});
},
[contextId],
);
// using layout effect as programatic dragging might start straight away (such as for cypress)
useLayoutEffect(() => {
invariant(
!alwaysRef.current && !dynamicRef.current,
'style elements already mounted',
);
const alwaysSelector = `[${alwaysDataAttr}="${contextId}"]`;
const dynamicSelector = `[${dynamicDataAttr}="${contextId}"]`;
const always: HTMLStyleElement = createStyleEl(nonce);
const dynamic: HTMLStyleElement = createStyleEl(nonce);
const heads = [
getHead(document),
...(
querySelectorAll(document, `[${prefix}-iframe]`) as HTMLIFrameElement[]
).map((iframe) => getHead(iframe.contentWindow!.document)),
];
// store their refs
alwaysRef.current = always;
dynamicRef.current = dynamic;
// Create initial style elements
heads.forEach((head) => {
if (!head) return;
// for easy identification
always.setAttribute(`${prefix}-always`, contextId);
dynamic.setAttribute(`${prefix}-dynamic`, contextId);
const alwaysElements = querySelectorAll(
head.ownerDocument,
alwaysSelector,
);
const dynamicElements = querySelectorAll(
head.ownerDocument,
dynamicSelector,
);
// add style tags to head
getHead().appendChild(always);
getHead().appendChild(dynamic);
if (
alwaysElements.length >= heads.length ||
dynamicElements.length >= heads.length
) {
return;
}
// set initial style
setAlwaysStyle(styles.always);
setDynamicStyle(styles.resting);
const always: HTMLStyleElement = createStyleEl(nonce);
const dynamic: HTMLStyleElement = createStyleEl(nonce);
// for easy identification
always.setAttribute(alwaysDataAttr, contextId);
dynamic.setAttribute(dynamicDataAttr, contextId);
head.appendChild(always);
head.appendChild(dynamic);
// set initial style
setAlwaysStyle(styles.always);
setDynamicStyle(styles.resting);
});
return () => {
const remove = (ref: MutableRefObject<HTMLStyleElement | null>) => {
const current: HTMLStyleElement | null = ref.current;
invariant(current, 'Cannot unmount ref as it is not set');
getHead().removeChild(current);
ref.current = null;
const remove = (selector: string) => {
const elements = querySelectorAllIframe(selector);
elements.forEach((el) => {
invariant(el, 'Cannot unmount element as it is not set');
el.ownerDocument.head.removeChild(el);
});
};
remove(alwaysRef);
remove(dynamicRef);
remove(alwaysSelector);
remove(dynamicSelector);
};

@@ -113,6 +146,2 @@ }, [

const resting = useCallback(() => {
// Can be called defensively
if (!dynamicRef.current) {
return;
}
setDynamicStyle(styles.resting);

@@ -119,0 +148,0 @@ }, [setDynamicStyle, styles.resting]);

import type { Position } from 'css-box-model';
// Not guarenteed to scroll by the entire amount
export default (change: Position): void => {
window.scrollBy(change.x, change.y);
// Not guaranteed to scroll by the entire amount
export default (change: Position, win: Window = window): void => {
win.scrollBy(change.x, change.y);
};

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

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