etudes 0.36.0 → 0.37.0

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.
package/lib/Panorama.d.ts CHANGED
@@ -22,15 +22,18 @@ export declare type Props = HTMLAttributes<HTMLDivElement> & {
22
22
  */
23
23
  zeroAnchor?: number;
24
24
  /**
25
- * Handler invoked when the changes. This can either be invoked from the `angle` prop being
26
- * changed or from the image being dragged.
25
+ * Handler invoked when the positionchanges. This can either be invoked from the `angle` prop
26
+ * being changed or from the image being dragged.
27
27
  *
28
28
  * @param position - The current position.
29
29
  * @param isDragging - Specifies if the position change is due to dragging.
30
30
  */
31
31
  onPositionChange?: (position: number, isDragging: boolean) => void;
32
32
  /**
33
- * Handler invoked when the angle changes.
33
+ * Handler invoked when the angle changes. This can either be invoked from the `angle` prop being
34
+ * changed or from the image being dragged. When `angle` is being double-binded, ensure that the
35
+ * value is only being set by this handler when `isDragging` is `true` to avoid potential update
36
+ * overflow.
34
37
  *
35
38
  * @param angle - The current angle.
36
39
  * @param isDragging - Specifies if the angle change is due to dragging.
package/lib/Panorama.js CHANGED
@@ -141,10 +141,12 @@ function Panorama(_a) {
141
141
  var newAngle = getAngleFromDisplacement(displacement, imageSize, size, zeroAnchor);
142
142
  if (angle !== newAngle) {
143
143
  setAngle(newAngle);
144
- onAngleChange === null || onAngleChange === void 0 ? void 0 : onAngleChange(angle, isDragging);
145
- onPositionChange === null || onPositionChange === void 0 ? void 0 : onPositionChange(angle / 360, isDragging);
146
144
  }
147
145
  }, [displacement, imageSize, size, zeroAnchor]);
146
+ (0, react_1.useEffect)(function () {
147
+ onAngleChange === null || onAngleChange === void 0 ? void 0 : onAngleChange(angle, isDragging);
148
+ onPositionChange === null || onPositionChange === void 0 ? void 0 : onPositionChange(angle / 360, isDragging);
149
+ }, [angle]);
148
150
  return (react_1.default.createElement(StyledRoot, __assign({ ref: rootRef }, props),
149
151
  react_1.default.createElement(StyledImageContainer, { style: {
150
152
  backgroundImage: "url(".concat(src, ")"),
@@ -1 +1 @@
1
- {"version":3,"file":"Panorama.js","sourceRoot":"/","sources":["Panorama.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { HTMLAttributes, useEffect, useRef, useState } from 'react'\nimport { Size } from 'spase'\nimport styled from 'styled-components'\nimport useDragEffect from './hooks/useDragEffect'\nimport useLoadImageEffect from './hooks/useLoadImageEffect'\nimport useResizeEffect from './hooks/useResizeEffect'\n\nconst debug = process.env.NODE_ENV === 'development' ? require('debug')('etudes:panorama') : () => {}\n\nexport type Props = HTMLAttributes<HTMLDivElement> & {\n /**\n * The current angle in degrees, 0.0 - 360.0, inclusive. When angle is 0 or 360, the left bound of\n * the image is at the center of the component.\n */\n angle?: number\n\n /**\n * The panning speed. This is a multiplier to the number of pixels dragged, i.e. when set to 1,\n * the image will shift the same amount of pixels that were dragged.\n */\n speed?: number\n\n /**\n * The source URL of the image.\n */\n src: string\n\n /**\n * A decimal percentage of the component width indicating where 0° should be, i.e. if `zeroAnchor`\n * is `0`, the `angle` would be 0° when the left edge of the image is at the left edge of the\n * component.\n */\n zeroAnchor?: number\n\n /**\n * Handler invoked when the changes. This can either be invoked from the `angle` prop being\n * changed or from the image being dragged.\n *\n * @param position - The current position.\n * @param isDragging - Specifies if the position change is due to dragging.\n */\n onPositionChange?: (position: number, isDragging: boolean) => void\n\n /**\n * Handler invoked when the angle changes.\n *\n * @param angle - The current angle.\n * @param isDragging - Specifies if the angle change is due to dragging.\n */\n onAngleChange?: (angle: number, isDragging: boolean) => void\n\n /**\n * Handler invoked when dragging starts.\n */\n onDragStart?: () => void\n\n /**\n * Handler invoked when dragging ends.\n */\n onDragEnd?: () => void\n\n /**\n * Handler invoked when the image begins loading.\n */\n onImageLoadStart?: () => void\n\n /**\n * Handler invoked when the image is done loading.\n *\n * @param imageElement - The loaded image element.\n */\n onImageLoadComplete?: (imageElement: HTMLImageElement) => void\n\n /**\n * Handler invoked when there is an error loading the image.\n */\n onImageLoadError?: () => void\n\n /**\n * Handler invoked when the image size changes. This is the actual size of the loaded image. When\n * no images are loaded yet, the size is `undefined`.\n *\n * @param size - The actual size of the loaded iamge. If no images are loaded yet, the size is\n * `undefined`.\n */\n onImageSizeChange?: (size?: Size) => void\n\n /**\n * Handler invoked when the size of this component changes.\n *\n * @param size - The size of this component.\n */\n onResize?: (size: Size) => void\n}\n\nfunction getFilledImageSize(originalSize: Size, sizeToFill: Size): Size {\n const { width: originalWidth, height: originalHeight } = originalSize\n const { height: filledHeignt } = sizeToFill\n\n if (originalHeight <= 0) return new Size()\n\n const aspectRatio = filledHeignt / originalHeight\n const filledWidth = aspectRatio * originalWidth\n\n return new Size([filledWidth, filledHeignt])\n}\n\nfunction getDisplacementFromAngle(angle: number, originalImageSize: Size, componentSize: Size, zeroAnchor: number): number {\n const { width: imageWidth } = getFilledImageSize(originalImageSize, componentSize)\n const { width: componentWidth } = componentSize\n const offset = componentWidth*zeroAnchor\n return (angle / 360) * imageWidth - offset\n}\n\nfunction getAngleFromDisplacement(displacement: number, originalImageSize: Size, componentSize: Size, zeroAnchor: number): number {\n const { width: imageWidth } = getFilledImageSize(originalImageSize, componentSize)\n const { width: componentWidth } = componentSize\n const offset = componentWidth*zeroAnchor\n\n let angle = ((displacement + offset) % imageWidth) / imageWidth*360\n while (angle < 0) angle += 360\n return angle\n}\n\n/**\n * A component containing a pannable 360° panorama image. The angle supports two-way binding.\n *\n * @requires react\n * @requires styled-component\n * @requires spase\n * @requires interactjs\n */\nexport default function Panorama({\n angle: externalAngle = 0,\n speed = 1,\n src,\n zeroAnchor = 0,\n onAngleChange,\n onPositionChange,\n onDragStart,\n onDragEnd,\n onImageLoadStart,\n onImageLoadComplete,\n onImageLoadError,\n onImageSizeChange,\n onResize,\n ...props\n}: Props) {\n function transform(currentDisplacement: number, dx: number, dy: number): number {\n const newDisplacement = currentDisplacement - (dx * speed)\n return newDisplacement\n }\n\n const rootRef = useRef<HTMLDivElement>(null)\n\n const [size] = useResizeEffect(rootRef, { onResize })\n const [angle, setAngle] = useState(externalAngle)\n\n const { isLoading: [isLoading], imageSize: [imageSize] } = useLoadImageEffect(src, {\n onImageLoadComplete,\n onImageLoadError,\n onImageSizeChange,\n })\n\n const { isDragging: [isDragging], value: [displacement, setDisplacement] } = useDragEffect(rootRef, {\n initialValue: 0,\n transform,\n onDragStart,\n onDragEnd,\n })\n\n useEffect(() => {\n if (isDragging || isLoading || !imageSize) return\n\n const newDisplacement = getDisplacementFromAngle(externalAngle, imageSize, size, zeroAnchor)\n\n if (newDisplacement !== displacement) {\n // debug('Updating drag effect value from angle prop...', 'OK', `old=${displacement} new=${newDisplacement}`)\n setDisplacement(newDisplacement)\n }\n\n if (externalAngle !== angle) {\n setAngle(externalAngle)\n }\n }, [externalAngle, isLoading, imageSize, size, zeroAnchor])\n\n useEffect(() => {\n if (!isDragging || !imageSize) return\n\n const newAngle = getAngleFromDisplacement(displacement, imageSize, size, zeroAnchor)\n\n if (angle !== newAngle) {\n setAngle(newAngle)\n onAngleChange?.(angle, isDragging)\n onPositionChange?.(angle / 360, isDragging)\n }\n }, [displacement, imageSize, size, zeroAnchor])\n\n return (\n <StyledRoot ref={rootRef} {...props}>\n <StyledImageContainer\n style={{\n backgroundImage: `url(${src})`,\n backgroundPositionX: `${-displacement}px`,\n }}\n />\n </StyledRoot>\n )\n}\n\nconst StyledImageContainer = styled.div`\n background-repeat: repeat;\n background-size: auto 100%;\n height: 100%;\n left: 0;\n margin: 0;\n padding: 0;\n position: absolute;\n top: 0;\n width: 100%;\n`\n\nconst StyledRoot = styled.div`\n align-items: center;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n flex: 0 0 auto;\n justify-content: center;\n padding: 0;\n position: relative;\n touch-action: none;\n\n > div {\n height: 100%;\n left: 0;\n margin: 0;\n padding: 0;\n position: absolute;\n top: 0;\n width: 100%;\n }\n`\n"]}
1
+ {"version":3,"file":"Panorama.js","sourceRoot":"/","sources":["Panorama.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { HTMLAttributes, useEffect, useRef, useState } from 'react'\nimport { Size } from 'spase'\nimport styled from 'styled-components'\nimport useDragEffect from './hooks/useDragEffect'\nimport useLoadImageEffect from './hooks/useLoadImageEffect'\nimport useResizeEffect from './hooks/useResizeEffect'\n\nconst debug = process.env.NODE_ENV === 'development' ? require('debug')('etudes:panorama') : () => {}\n\nexport type Props = HTMLAttributes<HTMLDivElement> & {\n /**\n * The current angle in degrees, 0.0 - 360.0, inclusive. When angle is 0 or 360, the left bound of\n * the image is at the center of the component.\n */\n angle?: number\n\n /**\n * The panning speed. This is a multiplier to the number of pixels dragged, i.e. when set to 1,\n * the image will shift the same amount of pixels that were dragged.\n */\n speed?: number\n\n /**\n * The source URL of the image.\n */\n src: string\n\n /**\n * A decimal percentage of the component width indicating where 0° should be, i.e. if `zeroAnchor`\n * is `0`, the `angle` would be 0° when the left edge of the image is at the left edge of the\n * component.\n */\n zeroAnchor?: number\n\n /**\n * Handler invoked when the positionchanges. This can either be invoked from the `angle` prop\n * being changed or from the image being dragged.\n *\n * @param position - The current position.\n * @param isDragging - Specifies if the position change is due to dragging.\n */\n onPositionChange?: (position: number, isDragging: boolean) => void\n\n /**\n * Handler invoked when the angle changes. This can either be invoked from the `angle` prop being\n * changed or from the image being dragged. When `angle` is being double-binded, ensure that the\n * value is only being set by this handler when `isDragging` is `true` to avoid potential update\n * overflow.\n *\n * @param angle - The current angle.\n * @param isDragging - Specifies if the angle change is due to dragging.\n */\n onAngleChange?: (angle: number, isDragging: boolean) => void\n\n /**\n * Handler invoked when dragging starts.\n */\n onDragStart?: () => void\n\n /**\n * Handler invoked when dragging ends.\n */\n onDragEnd?: () => void\n\n /**\n * Handler invoked when the image begins loading.\n */\n onImageLoadStart?: () => void\n\n /**\n * Handler invoked when the image is done loading.\n *\n * @param imageElement - The loaded image element.\n */\n onImageLoadComplete?: (imageElement: HTMLImageElement) => void\n\n /**\n * Handler invoked when there is an error loading the image.\n */\n onImageLoadError?: () => void\n\n /**\n * Handler invoked when the image size changes. This is the actual size of the loaded image. When\n * no images are loaded yet, the size is `undefined`.\n *\n * @param size - The actual size of the loaded iamge. If no images are loaded yet, the size is\n * `undefined`.\n */\n onImageSizeChange?: (size?: Size) => void\n\n /**\n * Handler invoked when the size of this component changes.\n *\n * @param size - The size of this component.\n */\n onResize?: (size: Size) => void\n}\n\nfunction getFilledImageSize(originalSize: Size, sizeToFill: Size): Size {\n const { width: originalWidth, height: originalHeight } = originalSize\n const { height: filledHeignt } = sizeToFill\n\n if (originalHeight <= 0) return new Size()\n\n const aspectRatio = filledHeignt / originalHeight\n const filledWidth = aspectRatio * originalWidth\n\n return new Size([filledWidth, filledHeignt])\n}\n\nfunction getDisplacementFromAngle(angle: number, originalImageSize: Size, componentSize: Size, zeroAnchor: number): number {\n const { width: imageWidth } = getFilledImageSize(originalImageSize, componentSize)\n const { width: componentWidth } = componentSize\n const offset = componentWidth*zeroAnchor\n return (angle / 360) * imageWidth - offset\n}\n\nfunction getAngleFromDisplacement(displacement: number, originalImageSize: Size, componentSize: Size, zeroAnchor: number): number {\n const { width: imageWidth } = getFilledImageSize(originalImageSize, componentSize)\n const { width: componentWidth } = componentSize\n const offset = componentWidth*zeroAnchor\n\n let angle = ((displacement + offset) % imageWidth) / imageWidth*360\n while (angle < 0) angle += 360\n return angle\n}\n\n/**\n * A component containing a pannable 360° panorama image. The angle supports two-way binding.\n *\n * @requires react\n * @requires styled-component\n * @requires spase\n * @requires interactjs\n */\nexport default function Panorama({\n angle: externalAngle = 0,\n speed = 1,\n src,\n zeroAnchor = 0,\n onAngleChange,\n onPositionChange,\n onDragStart,\n onDragEnd,\n onImageLoadStart,\n onImageLoadComplete,\n onImageLoadError,\n onImageSizeChange,\n onResize,\n ...props\n}: Props) {\n function transform(currentDisplacement: number, dx: number, dy: number): number {\n const newDisplacement = currentDisplacement - (dx * speed)\n return newDisplacement\n }\n\n const rootRef = useRef<HTMLDivElement>(null)\n\n const [size] = useResizeEffect(rootRef, { onResize })\n const [angle, setAngle] = useState(externalAngle)\n\n const { isLoading: [isLoading], imageSize: [imageSize] } = useLoadImageEffect(src, {\n onImageLoadComplete,\n onImageLoadError,\n onImageSizeChange,\n })\n\n const { isDragging: [isDragging], value: [displacement, setDisplacement] } = useDragEffect(rootRef, {\n initialValue: 0,\n transform,\n onDragStart,\n onDragEnd,\n })\n\n useEffect(() => {\n if (isDragging || isLoading || !imageSize) return\n\n const newDisplacement = getDisplacementFromAngle(externalAngle, imageSize, size, zeroAnchor)\n\n if (newDisplacement !== displacement) {\n // debug('Updating drag effect value from angle prop...', 'OK', `old=${displacement} new=${newDisplacement}`)\n setDisplacement(newDisplacement)\n }\n\n if (externalAngle !== angle) {\n setAngle(externalAngle)\n }\n }, [externalAngle, isLoading, imageSize, size, zeroAnchor])\n\n useEffect(() => {\n if (!isDragging || !imageSize) return\n\n const newAngle = getAngleFromDisplacement(displacement, imageSize, size, zeroAnchor)\n\n if (angle !== newAngle) {\n setAngle(newAngle)\n }\n }, [displacement, imageSize, size, zeroAnchor])\n\n useEffect(() => {\n onAngleChange?.(angle, isDragging)\n onPositionChange?.(angle / 360, isDragging)\n }, [angle])\n\n return (\n <StyledRoot ref={rootRef} {...props}>\n <StyledImageContainer\n style={{\n backgroundImage: `url(${src})`,\n backgroundPositionX: `${-displacement}px`,\n }}\n />\n </StyledRoot>\n )\n}\n\nconst StyledImageContainer = styled.div`\n background-repeat: repeat;\n background-size: auto 100%;\n height: 100%;\n left: 0;\n margin: 0;\n padding: 0;\n position: absolute;\n top: 0;\n width: 100%;\n`\n\nconst StyledRoot = styled.div`\n align-items: center;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n flex: 0 0 auto;\n justify-content: center;\n padding: 0;\n position: relative;\n touch-action: none;\n\n > div {\n height: 100%;\n left: 0;\n margin: 0;\n padding: 0;\n position: absolute;\n top: 0;\n width: 100%;\n }\n`\n"]}
package/lib/Slider.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.js","sourceRoot":"/","sources":["Slider.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,0DAAmC;AACnC,6CAAgE;AAChE,+BAA4B;AAC5B,qEAAwD;AACxD,wEAAiD;AAGjD,IAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,cAAO,CAAC,CAAA;AA4FnG;;;;;;;;;;;;GAYG;AACH,SAAwB,MAAM,CAAC,EAiBvB;IAhBN,IAAA,kBAAkB,EAAlB,UAAU,mBAAG,KAAK,KAAA,EAClB,+BAA+B,EAA/B,uBAAuB,mBAAG,KAAK,KAAA,EAC/B,oBAAgB,EAAhB,YAAY,mBAAG,CAAC,KAAA,EAChB,kBAAe,EAAf,UAAU,mBAAG,EAAE,KAAA,EACf,iBAAc,EAAd,SAAS,mBAAG,EAAE,KAAA,EACd,mBAAwB,EAAxB,WAAW,mBAAG,UAAU,KAAA,EACxB,gBAA8B,EAApB,gBAAgB,mBAAG,CAAC,KAAA,EAC9B,aAAa,mBAAA,EACb,SAAS,eAAA,EACT,WAAW,iBAAA,EACX,gBAAgB,sBAAA,EAChB,gBAAgB,sBAAA,EAChB,cAAc,oBAAA,EACd,OAAO,aAAA,EACP,QAAQ,cAAA,EACL,KAAK,cAhBqB,6OAiB9B,CADS;IAER,SAAS,SAAS,CAAC,eAAuB,EAAE,EAAU,EAAE,EAAU;;QAChE,IAAM,IAAI,GAAG,MAAA,YAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,mCAAI,IAAI,YAAI,EAAE,CAAA;QACrD,IAAM,eAAe,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,eAAe,CAAA;QAC1E,IAAM,mBAAmB,GAAG,eAAe,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;QAC7D,IAAM,mBAAmB,GAAG,eAAe,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE,CAAA;QAC9D,IAAM,kBAAkB,GAAG,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;QAClL,IAAM,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,kBAAkB,CAAA;QAC5E,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,IAAM,OAAO,GAAG,IAAA,cAAM,EAAiB,IAAI,CAAC,CAAA;IAC5C,IAAM,OAAO,GAAG,IAAA,cAAM,EAAoB,IAAI,CAAC,CAAA;IAEzC,IAAA,KAA+D,IAAA,uBAAa,EAAC,OAAO,EAAE;QAC1F,YAAY,EAAE,gBAAgB;QAC9B,SAAS,WAAA;QACT,WAAW,aAAA;QACX,SAAS,WAAA;KACV,CAAC,EALM,KAAA,wBAAwB,EAAX,UAAU,QAAA,EAAG,KAAA,mBAA8B,EAAtB,QAAQ,QAAA,EAAE,WAAW,QAK7D,CAAA;IAEF,8BAA8B;IAE9B,IAAM,eAAe,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAA;IAE5D,IAAA,iBAAS,EAAC;QACR,IAAI,UAAU,IAAI,gBAAgB,KAAK,QAAQ;YAAE,OAAM;QAEvD,KAAK,CAAC,kDAAkD,EAAE,IAAI,EAAE,eAAQ,gBAAgB,sBAAY,QAAQ,CAAE,CAAC,CAAA;QAE/G,WAAW,CAAC,gBAAgB,CAAC,CAAA;IAC/B,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAA;IAEtB,IAAA,iBAAS,EAAC;QACR,IAAI,UAAU,IAAI,uBAAuB;YAAE,OAAM;QACjD,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAG,QAAQ,EAAE,UAAU,CAAC,CAAA;IAC1C,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,IAAA,iBAAS,EAAC;QACR,IAAI,UAAU,IAAI,CAAC,uBAAuB;YAAE,OAAM;QAElD,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAG,QAAQ,EAAE,IAAI,CAAC,CAAA;IACpC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAA;IAEhB,OAAO,CACL,8BAAC,UAAU,aAAC,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,IAAM,KAAK;QAC3D,8BAAC,WAAW,IAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,gBAAgB,EAC1D,KAAK,EAAE,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC;gBAClC,GAAG,EAAE,CAAC;gBACN,MAAM,EAAE,eAAQ,eAAe,GAAC,GAAG,iBAAO,UAAU,GAAC,EAAE,kBAAQ,YAAY,QAAK;aACjF,CAAC,CAAC,CAAC;gBACF,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,eAAQ,eAAe,GAAC,GAAG,iBAAO,SAAS,GAAC,EAAE,kBAAQ,YAAY,QAAK;aAC/E,GACD;QACF,8BAAC,mBAAmB,IAAC,GAAG,EAAE,OAAO,EAAE,KAAK,aACtC,SAAS,EAAE,4BAA4B,IACpC,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC;gBAC/B,IAAI,EAAE,KAAK;gBACX,GAAG,EAAE,UAAG,eAAe,GAAC,GAAG,MAAG;gBAC9B,UAAU,EAAE,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,MAAM;aACjE,CAAC,CAAC,CAAC;gBACF,IAAI,EAAE,UAAG,eAAe,GAAC,GAAG,MAAG;gBAC/B,GAAG,EAAE,KAAK;gBACV,UAAU,EAAE,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,MAAM;aAClE,CAAC;YAEF,8BAAC,UAAU,IACT,SAAS,EAAE,IAAA,oBAAU,EAAC;oBACpB,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC;oBAC1D,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC;oBAC5D,UAAU,EAAE,UAAU,KAAK,IAAI;iBAChC,CAAC,EACF,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE;oBACL,MAAM,EAAE,UAAG,UAAU,OAAI;oBACzB,KAAK,EAAE,UAAG,SAAS,OAAI;iBACxB,IAEA,aAAa,IAAI,CAChB,8BAAC,WAAW,IAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,IAAG,aAAa,CAAC,QAAQ,CAAC,CAAe,CAC5F,CACU,CACO;QACtB,8BAAC,WAAW,IAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,cAAc,EACxD,KAAK,EAAE,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC;gBAClC,MAAM,EAAE,CAAC;gBACT,MAAM,EAAE,eAAQ,CAAC,CAAC,GAAG,eAAe,CAAC,GAAC,GAAG,iBAAO,UAAU,GAAC,EAAE,kBAAQ,YAAY,QAAK;aACvF,CAAC,CAAC,CAAC;gBACF,KAAK,EAAE,CAAC;gBACR,KAAK,EAAE,eAAQ,CAAC,CAAC,GAAG,eAAe,CAAC,GAAC,GAAG,iBAAO,SAAS,GAAC,EAAE,kBAAQ,YAAY,QAAK;aACrF,GACD,CACS,CACd,CAAA;AACH,CAAC;AAhHD,yBAgHC;AAED,IAAM,WAAW,GAAG,2BAAM,CAAC,GAAG,uIAAoD,oDAI9E,EAUD,QAEC,EAAkB,IACrB,KAbG,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,KAAC,uBAAG,8IAAA,0EAKhD,KAAC,CAAC,KAAC,uBAAG,+IAAA,2EAKN,IAAA,EAVU,CAUV,EAEC,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,GAAG,EAAT,CAAS,CACrB,CAAA;AAED,IAAM,WAAW,GAAG,2BAAM,CAAC,KAAK,sKAAkD,iCAEnE,EAA8B,0DAIzC,EAAkB,IACrB,KALc,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,UAAU,GAAG,EAAE,EAArB,CAAqB,EAIzC,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,GAAG,EAAT,CAAS,CACrB,CAAA;AAED,IAAM,mBAAmB,GAAG,2BAAM,CAAC,MAAM,6GAAA,0CAGxC,IAAA,CAAA;AAED,IAAM,UAAU,GAAG,2BAAM,CAAC,GAAG,gYAAA,uTAYzB,EAAkB,IACrB,KADG,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,GAAG,EAAT,CAAS,CACrB,CAAA;AAED,IAAM,UAAU,GAAG,2BAAM,CAAC,GAAG,6KAE3B,4DAGU,EAA2D,qCAE5D,EAA2D,KACrE,KAHW,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAlD,CAAkD,EAE5D,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAlD,CAAkD,CACrE,CAAA","sourcesContent":["import classNames from 'classnames'\nimport React, { HTMLAttributes, useEffect, useRef } from 'react'\nimport { Rect } from 'spase'\nimport styled, { css, CSSProp } from 'styled-components'\nimport useDragEffect from './hooks/useDragEffect'\nimport { Orientation } from './types'\n\nconst debug = process.env.NODE_ENV === 'development' ? require('debug')('etudes:slider') : () => {}\n\nexport type Props = HTMLAttributes<HTMLDivElement> & {\n /**\n * By default the position is a value from 0 - 1, 0 being the start of the slider and 1 being the\n * end. Switching on this flag inverts this behavior, where 0 becomes the end of the slider and 1\n * being the start.\n */\n isInverted?: boolean\n\n /**\n * Indicates if position change events are dispatched only when dragging ends. When disabled,\n * aforementioned events are fired repeatedly while dragging.\n */\n onlyDispatchesOnDragEnd?: boolean\n\n /**\n * A function that returns the label to be displayed at a given slider position.\n *\n * @param position - The current slider position.\n *\n * @returns The label.\n */\n labelProvider?: (position: number) => string\n\n /**\n * Padding between the track and the knob in pixels.\n */\n trackPadding?: number\n\n /**\n * Height of the knob in pixels.\n */\n knobHeight?: number\n\n /**\n * Width of the knob in pixels.\n */\n knobWidth?: number\n\n /**\n * Orientation of the slider.\n */\n orientation?: Orientation\n\n /**\n * The current position.\n */\n position?: number\n\n /**\n * Handler invoked when position changes. This can either be invoked from the `position` prop\n * being changed or from the slider being dragged. Note that if the event is emitted at the end of\n * dragging due to `onlyDispatchesOnDragEnd` set to `true`, the `isDragging` parameter here is\n * still `true`.\n *\n * @param position - The current slider position.\n * @param isDragging - Specifies if the position change is due to dragging.\n */\n onPositionChange?: (position: number, isDragging: boolean) => void\n\n /**\n * Handler invoked when dragging ends.\n */\n onDragEnd?: () => void\n\n /**\n * Handler invoked when dragging begins.\n */\n onDragStart?: () => void\n\n /**\n * Custom CSS provided to the track before the knob.\n */\n startingTrackCSS?: CSSProp<any>\n\n /**\n * Custom CSS provided to the track after the knob.\n */\n endingTrackCSS?: CSSProp<any>\n\n /**\n * Custom CSS provided to the knob.\n */\n knobCSS?: CSSProp<any>\n\n /**\n * Custom CSS provided to the label inside the knob.\n */\n labelCSS?: CSSProp<any>\n}\n\n/**\n * A slider component supporting both horizontal and vertical orientations whose sliding position (a\n * decimal between 0.0 and 1.0, inclusive) can be two-way binded. The component consists of four\n * customizable elements: a draggable knob, a label on the knob, a scroll track before the knob and\n * a scroll track after the knob. While the width and height of the slider is inferred from its CSS\n * rules, the width and height of the knob are set via props (`knobWidth` and `knobHeight`,\n * respectively). The size of the knob does not impact the size of the slider.\n *\n * @requires react\n * @requires styled-components\n * @requires spase\n * @requires interactjs\n */\nexport default function Slider({\n isInverted = false,\n onlyDispatchesOnDragEnd = false,\n trackPadding = 0,\n knobHeight = 30,\n knobWidth = 30,\n orientation = 'vertical',\n position: externalPosition = 0,\n labelProvider,\n onDragEnd,\n onDragStart,\n onPositionChange,\n startingTrackCSS,\n endingTrackCSS,\n knobCSS,\n labelCSS,\n ...props\n}: Props) {\n function transform(currentPosition: number, dx: number, dy: number): number {\n const rect = Rect.from(rootRef.current) ?? new Rect()\n const naturalPosition = isInverted ? 1 - currentPosition : currentPosition\n const naturalNewPositionX = naturalPosition * rect.width + dx\n const naturalNewPositionY = naturalPosition * rect.height + dy\n const naturalNewPosition = (orientation === 'vertical') ? Math.max(0, Math.min(1, naturalNewPositionY / rect.height)) : Math.max(0, Math.min(1, naturalNewPositionX / rect.width))\n const newPosition = isInverted ? 1 - naturalNewPosition : naturalNewPosition\n return newPosition\n }\n\n const rootRef = useRef<HTMLDivElement>(null)\n const knobRef = useRef<HTMLButtonElement>(null)\n\n const { isDragging: [isDragging], value: [position, setPosition] } = useDragEffect(knobRef, {\n initialValue: externalPosition,\n transform,\n onDragStart,\n onDragEnd,\n })\n\n // debug('Rendering...', 'OK')\n\n const naturalPosition = isInverted ? 1 - position : position\n\n useEffect(() => {\n if (isDragging || externalPosition === position) return\n\n debug('Updating drag effect value from position prop...', 'OK', `prop=${externalPosition}, effect=${position}`)\n\n setPosition(externalPosition)\n }, [externalPosition])\n\n useEffect(() => {\n if (isDragging && onlyDispatchesOnDragEnd) return\n onPositionChange?.(position, isDragging)\n }, [position])\n\n useEffect(() => {\n if (isDragging || !onlyDispatchesOnDragEnd) return\n\n onPositionChange?.(position, true)\n }, [isDragging])\n\n return (\n <StyledRoot ref={rootRef} orientation={orientation} {...props}>\n <StyledTrack orientation={orientation} css={startingTrackCSS}\n style={orientation === 'vertical' ? {\n top: 0,\n height: `calc(${naturalPosition*100}% - ${knobHeight*.5}px - ${trackPadding}px)`,\n } : {\n left: 0,\n width: `calc(${naturalPosition*100}% - ${knobWidth*.5}px - ${trackPadding}px)`,\n }}\n />\n <StyledKnobContainer ref={knobRef} style={{\n transform: 'translate3d(-50%, -50%, 0)',\n ...(orientation === 'vertical' ? {\n left: '50%',\n top: `${naturalPosition*100}%`,\n transition: isDragging === false ? 'top 100ms ease-out' : 'none',\n } : {\n left: `${naturalPosition*100}%`,\n top: '50%',\n transition: isDragging === false ? 'left 100ms ease-out' : 'none',\n }),\n }}>\n <StyledKnob\n className={classNames({\n 'at-end': isInverted ? (position === 0) : (position === 1),\n 'at-start': isInverted ? (position === 1) : (position === 0),\n 'dragging': isDragging === true,\n })}\n css={knobCSS}\n style={{\n height: `${knobHeight}px`,\n width: `${knobWidth}px`,\n }}\n >\n {labelProvider && (\n <StyledLabel knobHeight={knobHeight} css={labelCSS}>{labelProvider(position)}</StyledLabel>\n )}\n </StyledKnob>\n </StyledKnobContainer>\n <StyledTrack orientation={orientation} css={endingTrackCSS}\n style={orientation === 'vertical' ? {\n bottom: 0,\n height: `calc(${(1 - naturalPosition)*100}% - ${knobHeight*.5}px - ${trackPadding}px)`,\n } : {\n right: 0,\n width: `calc(${(1 - naturalPosition)*100}% - ${knobWidth*.5}px - ${trackPadding}px)`,\n }}\n />\n </StyledRoot>\n )\n}\n\nconst StyledTrack = styled.div<{ orientation: NonNullable<Props['orientation']> }>`\n background: #fff;\n position: absolute;\n\n ${props => props.orientation === 'vertical' ? css`\n left: 0;\n margin: 0 auto;\n right: 0;\n width: 100%;\n ` : css`\n bottom: 0;\n height: 100%;\n margin: auto 0;\n top: 0;\n `}\n\n ${props => props.css}\n`\n\nconst StyledLabel = styled.label<{ knobHeight: NonNullable<Props['knobHeight']> }>`\n color: #000;\n font-size: ${props => props.knobHeight * .5}px;\n pointer-events: none;\n user-select: none;\n\n ${props => props.css}\n`\n\nconst StyledKnobContainer = styled.button`\n position: absolute;\n z-index: 1;\n`\n\nconst StyledKnob = styled.div`\n align-items: center;\n background: #fff;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n justify-content: center;\n touch-action: none;\n transition-duration: 100ms;\n transition-property: background, color, opacity, transform;\n transition-timing-function: ease-out;\n\n ${props => props.css}\n`\n\nconst StyledRoot = styled.div<{\n orientation: Orientation\n}>`\n box-sizing: border-box;\n display: block;\n height: ${props => props.orientation === 'vertical' ? '300px' : '4px'};\n position: relative;\n width: ${props => props.orientation === 'vertical' ? '4px' : '300px'};\n`\n"]}
1
+ {"version":3,"file":"Slider.js","sourceRoot":"/","sources":["Slider.tsx"],"names":[],"mappings":"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","sourcesContent":["import classNames from 'classnames'\nimport React, { HTMLAttributes, useEffect, useRef } from 'react'\nimport { Rect } from 'spase'\nimport styled, { css, CSSProp } from 'styled-components'\nimport useDragEffect from './hooks/useDragEffect'\nimport { Orientation } from './types'\n\nconst debug = process.env.NODE_ENV === 'development' ? require('debug')('etudes:slider') : () => {}\n\nexport type Props = HTMLAttributes<HTMLDivElement> & {\n /**\n * By default the position is a value from 0 - 1, 0 being the start of the slider and 1 being the\n * end. Switching on this flag inverts this behavior, where 0 becomes the end of the slider and 1\n * being the start.\n */\n isInverted?: boolean\n\n /**\n * Indicates if position change events are dispatched only when dragging ends. When disabled,\n * aforementioned events are fired repeatedly while dragging.\n */\n onlyDispatchesOnDragEnd?: boolean\n\n /**\n * A function that returns the label to be displayed at a given slider position.\n *\n * @param position - The current slider position.\n *\n * @returns The label.\n */\n labelProvider?: (position: number) => string\n\n /**\n * Padding between the track and the knob in pixels.\n */\n trackPadding?: number\n\n /**\n * Height of the knob in pixels.\n */\n knobHeight?: number\n\n /**\n * Width of the knob in pixels.\n */\n knobWidth?: number\n\n /**\n * Orientation of the slider.\n */\n orientation?: Orientation\n\n /**\n * The current position.\n */\n position?: number\n\n /**\n * Handler invoked when position changes. This can either be invoked from the `position` prop\n * being changed or from the slider being dragged. Note that if the event is emitted at the end of\n * dragging due to `onlyDispatchesOnDragEnd` set to `true`, the `isDragging` parameter here is\n * still `true`.\n *\n * @param position - The current slider position.\n * @param isDragging - Specifies if the position change is due to dragging.\n */\n onPositionChange?: (position: number, isDragging: boolean) => void\n\n /**\n * Handler invoked when dragging ends.\n */\n onDragEnd?: () => void\n\n /**\n * Handler invoked when dragging begins.\n */\n onDragStart?: () => void\n\n /**\n * Custom CSS provided to the track before the knob.\n */\n startingTrackCSS?: CSSProp<any>\n\n /**\n * Custom CSS provided to the track after the knob.\n */\n endingTrackCSS?: CSSProp<any>\n\n /**\n * Custom CSS provided to the knob.\n */\n knobCSS?: CSSProp<any>\n\n /**\n * Custom CSS provided to the label inside the knob.\n */\n labelCSS?: CSSProp<any>\n}\n\n/**\n * A slider component supporting both horizontal and vertical orientations whose sliding position (a\n * decimal between 0.0 and 1.0, inclusive) can be two-way binded. The component consists of four\n * customizable elements: a draggable knob, a label on the knob, a scroll track before the knob and\n * a scroll track after the knob. While the width and height of the slider is inferred from its CSS\n * rules, the width and height of the knob are set via props (`knobWidth` and `knobHeight`,\n * respectively). The size of the knob does not impact the size of the slider.\n *\n * @requires react\n * @requires styled-components\n * @requires spase\n * @requires interactjs\n */\nexport default function Slider({\n isInverted = false,\n onlyDispatchesOnDragEnd = false,\n trackPadding = 0,\n knobHeight = 30,\n knobWidth = 30,\n orientation = 'vertical',\n position: externalPosition = 0,\n labelProvider,\n onDragEnd,\n onDragStart,\n onPositionChange,\n startingTrackCSS,\n endingTrackCSS,\n knobCSS,\n labelCSS,\n ...props\n}: Props) {\n function transform(currentPosition: number, dx: number, dy: number): number {\n const rect = Rect.from(rootRef.current) ?? new Rect()\n const naturalPosition = isInverted ? 1 - currentPosition : currentPosition\n const naturalNewPositionX = naturalPosition * rect.width + dx\n const naturalNewPositionY = naturalPosition * rect.height + dy\n const naturalNewPosition = (orientation === 'vertical') ? Math.max(0, Math.min(1, naturalNewPositionY / rect.height)) : Math.max(0, Math.min(1, naturalNewPositionX / rect.width))\n const newPosition = isInverted ? 1 - naturalNewPosition : naturalNewPosition\n return newPosition\n }\n\n const rootRef = useRef<HTMLDivElement>(null)\n const knobRef = useRef<HTMLButtonElement>(null)\n\n const { isDragging: [isDragging], value: [position, setPosition] } = useDragEffect(knobRef, {\n initialValue: externalPosition,\n transform,\n onDragStart,\n onDragEnd,\n })\n\n // debug('Rendering...', 'OK')\n\n const naturalPosition = isInverted ? 1 - position : position\n\n useEffect(() => {\n if (isDragging || externalPosition === position) return\n\n debug('Updating drag effect value from position prop...', 'OK', `prop=${externalPosition}, effect=${position}`)\n\n setPosition(externalPosition)\n }, [externalPosition])\n\n useEffect(() => {\n if (isDragging && onlyDispatchesOnDragEnd) return\n onPositionChange?.(position, isDragging)\n }, [position])\n\n useEffect(() => {\n if (isDragging || !onlyDispatchesOnDragEnd) return\n onPositionChange?.(position, true)\n }, [isDragging])\n\n return (\n <StyledRoot ref={rootRef} orientation={orientation} {...props}>\n <StyledTrack orientation={orientation} css={startingTrackCSS}\n style={orientation === 'vertical' ? {\n top: 0,\n height: `calc(${naturalPosition*100}% - ${knobHeight*.5}px - ${trackPadding}px)`,\n } : {\n left: 0,\n width: `calc(${naturalPosition*100}% - ${knobWidth*.5}px - ${trackPadding}px)`,\n }}\n />\n <StyledKnobContainer ref={knobRef} style={{\n transform: 'translate3d(-50%, -50%, 0)',\n ...(orientation === 'vertical' ? {\n left: '50%',\n top: `${naturalPosition*100}%`,\n transition: isDragging === false ? 'top 100ms ease-out' : 'none',\n } : {\n left: `${naturalPosition*100}%`,\n top: '50%',\n transition: isDragging === false ? 'left 100ms ease-out' : 'none',\n }),\n }}>\n <StyledKnob\n className={classNames({\n 'at-end': isInverted ? (position === 0) : (position === 1),\n 'at-start': isInverted ? (position === 1) : (position === 0),\n 'dragging': isDragging === true,\n })}\n css={knobCSS}\n style={{\n height: `${knobHeight}px`,\n width: `${knobWidth}px`,\n }}\n >\n {labelProvider && (\n <StyledLabel knobHeight={knobHeight} css={labelCSS}>{labelProvider(position)}</StyledLabel>\n )}\n </StyledKnob>\n </StyledKnobContainer>\n <StyledTrack orientation={orientation} css={endingTrackCSS}\n style={orientation === 'vertical' ? {\n bottom: 0,\n height: `calc(${(1 - naturalPosition)*100}% - ${knobHeight*.5}px - ${trackPadding}px)`,\n } : {\n right: 0,\n width: `calc(${(1 - naturalPosition)*100}% - ${knobWidth*.5}px - ${trackPadding}px)`,\n }}\n />\n </StyledRoot>\n )\n}\n\nconst StyledTrack = styled.div<{ orientation: NonNullable<Props['orientation']> }>`\n background: #fff;\n position: absolute;\n\n ${props => props.orientation === 'vertical' ? css`\n left: 0;\n margin: 0 auto;\n right: 0;\n width: 100%;\n ` : css`\n bottom: 0;\n height: 100%;\n margin: auto 0;\n top: 0;\n `}\n\n ${props => props.css}\n`\n\nconst StyledLabel = styled.label<{ knobHeight: NonNullable<Props['knobHeight']> }>`\n color: #000;\n font-size: ${props => props.knobHeight * .5}px;\n pointer-events: none;\n user-select: none;\n\n ${props => props.css}\n`\n\nconst StyledKnobContainer = styled.button`\n position: absolute;\n z-index: 1;\n`\n\nconst StyledKnob = styled.div`\n align-items: center;\n background: #fff;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n justify-content: center;\n touch-action: none;\n transition-duration: 100ms;\n transition-property: background, color, opacity, transform;\n transition-timing-function: ease-out;\n\n ${props => props.css}\n`\n\nconst StyledRoot = styled.div<{\n orientation: Orientation\n}>`\n box-sizing: border-box;\n display: block;\n height: ${props => props.orientation === 'vertical' ? '300px' : '4px'};\n position: relative;\n width: ${props => props.orientation === 'vertical' ? '4px' : '300px'};\n`\n"]}
@@ -93,7 +93,6 @@ function useDragEffect(targetRef, _a, deps) {
93
93
  // Do not consume states in these listeners as they will remain their initial values within
94
94
  // the scope of the listeners.
95
95
  (0, interactjs_1.default)(targetRef.current).draggable(__assign(__assign({ inertia: true }, options), { onstart: function () {
96
- console.log('started');
97
96
  setIsDragging(true);
98
97
  onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart();
99
98
  }, onmove: function (_a) {
@@ -106,7 +105,6 @@ function useDragEffect(targetRef, _a, deps) {
106
105
  }
107
106
  onDragMove === null || onDragMove === void 0 ? void 0 : onDragMove(dx, dy);
108
107
  }, onend: function () {
109
- console.log('stopped');
110
108
  setIsDragging(false);
111
109
  onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd();
112
110
  } }));
@@ -1 +1 @@
1
- {"version":3,"file":"useDragEffect.js","sourceRoot":"/","sources":["hooks/useDragEffect.ts"],"names":[],"mappings":"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","sourcesContent":["import interact from 'interactjs'\nimport _ from 'lodash'\nimport { DependencyList, Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'\n\nconst debug = process.env.NODE_ENV === 'development' ? require('debug')('etudes:hooks') : () => {}\n\ntype ReturnedStates<T> = {\n isDragging: [boolean, Dispatch<SetStateAction<boolean>>]\n value: [T, Dispatch<SetStateAction<T>>]\n}\n\ntype Options<T> = Omit<Interact.DraggableOptions, 'onstart' | 'onmove' | 'onend'> & {\n /**\n * The initial associated value of this hook.\n */\n initialValue: T\n\n /**\n * Handler invoked when dragging starts.\n */\n onDragStart?: () => void\n\n /**\n * Handler invoked when dragging.\n *\n * @param dx - The displacement on the x-axis (in pixels) since the last emitted drag move event.\n * @param dy - The displacement on the y-axis (in pixels) since the last emitted drag move event.\n */\n onDragMove?: (dx: number, dy: number) => void\n\n /**\n * Handler invoked when dragging ends.\n */\n onDragEnd?: () => void\n\n /**\n * A function that transforms the drag move delta values to the associated value of this hook.\n *\n * @param currentValue - The current associated value.\n * @param dx - The displacement on the x-axis (in pixels) since the last emitted drag move event.\n * @param dy - The displacement on the y-axis (in pixels) since the last emitted drag move event.\n *\n * @returns The transformed value.\n */\n transform?: (currentValue: T, dx: number, dy: number) => T\n}\n\n/**\n * Hook for adding effectful dragging interaction to an element.\n *\n * @param targetRef - The reference to the target element to add drag interaction to.\n * @param options - Additional options which include options for `module:interactjs.draggable`.\n * @param deps - Dependencies that trigger this effect.\n *\n * @returns The states created for this effect.\n *\n * @requires react\n * @requires spase\n * @requires interactjs\n */\nexport default function useDragEffect<T = [number, number]>(targetRef: RefObject<HTMLElement>, { onDragStart, onDragMove, onDragEnd, initialValue, transform, ...options }: Options<T>, deps?: DependencyList): ReturnedStates<T> {\n const valueRef = useRef<T>(initialValue)\n const [isDragging, setIsDragging] = useState<boolean>(false)\n const [value, setValue] = useState(valueRef.current)\n\n /**\n * Sets the current associated value reference. This reference object is equal to the `value`\n * state but differs slightly in how they are set. Because states are asynchronous by nature, this\n * reference object is used to cache time-sensitive value changes while drag event happens.\n *\n * @param value - The value to set the associated value to.\n *\n * @returns `true` if the value was set, `false` otherwise.\n */\n function setValueRef(value: T): boolean {\n if (_.isEqual(valueRef.current, value)) return false\n valueRef.current = value\n return true\n }\n\n useEffect(() => {\n // debug(`Using drag effect for element ${targetRef.current}...`, 'OK', `value=${valueRef.current}`)\n\n if (targetRef.current && !interact.isSet(targetRef.current)) {\n // Do not consume states in these listeners as they will remain their initial values within\n // the scope of the listeners.\n interact(targetRef.current).draggable({\n inertia: true,\n ...options,\n onstart: () => {\n console.log('started')\n setIsDragging(true)\n onDragStart?.()\n },\n onmove: ({ dx, dy }) => {\n const newValue = transform?.(valueRef.current, dx, dy) ?? [dx, dy] as unknown as T\n\n if (setValueRef(newValue)) {\n // debug('Updating value from dragging...', 'OK', newValue)\n setValue(newValue)\n }\n\n onDragMove?.(dx, dy)\n },\n onend: () => {\n console.log('stopped')\n setIsDragging(false)\n onDragEnd?.()\n },\n })\n }\n\n return () => {\n // debug(`Removing drag effect for element ${targetRef.current}...`, 'OK', `value=${valueRef.current}`)\n\n if (targetRef.current && interact.isSet(targetRef.current)) {\n interact(targetRef.current).unset()\n }\n }\n }, [...deps ? deps : []])\n\n useEffect(() => {\n if (setValueRef(value)) {\n // debug('Updating value from externally...', 'OK', value)\n }\n }, [value])\n\n return {\n isDragging: [isDragging, setIsDragging],\n value: [value, setValue],\n }\n}\n"]}
1
+ {"version":3,"file":"useDragEffect.js","sourceRoot":"/","sources":["hooks/useDragEffect.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,0DAAiC;AACjC,kDAAsB;AACtB,+BAAwG;AAExG,IAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAO,CAAC,CAAA;AA2ClG;;;;;;;;;;;;GAYG;AACH,SAAwB,aAAa,CAAuB,SAAiC,EAAE,EAAuF,EAAE,IAAqB;IAA5G,IAAA,WAAW,iBAAA,EAAE,UAAU,gBAAA,EAAE,SAAS,eAAA,EAAE,YAAY,kBAAA,EAAE,SAAS,eAAA,EAAK,OAAO,cAAzE,uEAA2E,CAAF;IACtK,IAAM,QAAQ,GAAG,IAAA,cAAM,EAAI,YAAY,CAAC,CAAA;IAClC,IAAA,KAAA,OAA8B,IAAA,gBAAQ,EAAU,KAAK,CAAC,IAAA,EAArD,UAAU,QAAA,EAAE,aAAa,QAA4B,CAAA;IACtD,IAAA,KAAA,OAAoB,IAAA,gBAAQ,EAAC,QAAQ,CAAC,OAAO,CAAC,IAAA,EAA7C,KAAK,QAAA,EAAE,QAAQ,QAA8B,CAAA;IAEpD;;;;;;;;OAQG;IACH,SAAS,WAAW,CAAC,KAAQ;QAC3B,IAAI,gBAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;YAAE,OAAO,KAAK,CAAA;QACpD,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAA;QACxB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAA,iBAAS,EAAC;QACR,oGAAoG;QAEpG,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,oBAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;YAC3D,2FAA2F;YAC3F,8BAA8B;YAC9B,IAAA,oBAAQ,EAAC,SAAS,CAAC,OAAO,CAAC,CAAC,SAAS,qBACnC,OAAO,EAAE,IAAI,IACV,OAAO,KACV,OAAO,EAAE;oBACP,aAAa,CAAC,IAAI,CAAC,CAAA;oBACnB,WAAW,aAAX,WAAW,uBAAX,WAAW,EAAI,CAAA;gBACjB,CAAC,EACD,MAAM,EAAE,UAAC,EAAU;;wBAAR,EAAE,QAAA,EAAE,EAAE,QAAA;oBACf,IAAM,QAAQ,GAAG,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,mCAAI,CAAC,EAAE,EAAE,EAAE,CAAiB,CAAA;oBAElF,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE;wBACzB,2DAA2D;wBAC3D,QAAQ,CAAC,QAAQ,CAAC,CAAA;qBACnB;oBAED,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,EAAE,EAAE,EAAE,CAAC,CAAA;gBACtB,CAAC,EACD,KAAK,EAAE;oBACL,aAAa,CAAC,KAAK,CAAC,CAAA;oBACpB,SAAS,aAAT,SAAS,uBAAT,SAAS,EAAI,CAAA;gBACf,CAAC,IACD,CAAA;SACH;QAED,OAAO;YACL,uGAAuG;YAEvG,IAAI,SAAS,CAAC,OAAO,IAAI,oBAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;gBAC1D,IAAA,oBAAQ,EAAC,SAAS,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAA;aACpC;QACH,CAAC,CAAA;IACH,CAAC,2BAAM,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,UAAE,CAAA;IAEzB,IAAA,iBAAS,EAAC;QACR,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE;YACtB,0DAA0D;SAC3D;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,OAAO;QACL,UAAU,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC;QACvC,KAAK,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;KACzB,CAAA;AACH,CAAC;AArED,gCAqEC","sourcesContent":["import interact from 'interactjs'\nimport _ from 'lodash'\nimport { DependencyList, Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'\n\nconst debug = process.env.NODE_ENV === 'development' ? require('debug')('etudes:hooks') : () => {}\n\ntype ReturnedStates<T> = {\n isDragging: [boolean, Dispatch<SetStateAction<boolean>>]\n value: [T, Dispatch<SetStateAction<T>>]\n}\n\ntype Options<T> = Omit<Interact.DraggableOptions, 'onstart' | 'onmove' | 'onend'> & {\n /**\n * The initial associated value of this hook.\n */\n initialValue: T\n\n /**\n * Handler invoked when dragging starts.\n */\n onDragStart?: () => void\n\n /**\n * Handler invoked when dragging.\n *\n * @param dx - The displacement on the x-axis (in pixels) since the last emitted drag move event.\n * @param dy - The displacement on the y-axis (in pixels) since the last emitted drag move event.\n */\n onDragMove?: (dx: number, dy: number) => void\n\n /**\n * Handler invoked when dragging ends.\n */\n onDragEnd?: () => void\n\n /**\n * A function that transforms the drag move delta values to the associated value of this hook.\n *\n * @param currentValue - The current associated value.\n * @param dx - The displacement on the x-axis (in pixels) since the last emitted drag move event.\n * @param dy - The displacement on the y-axis (in pixels) since the last emitted drag move event.\n *\n * @returns The transformed value.\n */\n transform?: (currentValue: T, dx: number, dy: number) => T\n}\n\n/**\n * Hook for adding effectful dragging interaction to an element.\n *\n * @param targetRef - The reference to the target element to add drag interaction to.\n * @param options - Additional options which include options for `module:interactjs.draggable`.\n * @param deps - Dependencies that trigger this effect.\n *\n * @returns The states created for this effect.\n *\n * @requires react\n * @requires spase\n * @requires interactjs\n */\nexport default function useDragEffect<T = [number, number]>(targetRef: RefObject<HTMLElement>, { onDragStart, onDragMove, onDragEnd, initialValue, transform, ...options }: Options<T>, deps?: DependencyList): ReturnedStates<T> {\n const valueRef = useRef<T>(initialValue)\n const [isDragging, setIsDragging] = useState<boolean>(false)\n const [value, setValue] = useState(valueRef.current)\n\n /**\n * Sets the current associated value reference. This reference object is equal to the `value`\n * state but differs slightly in how they are set. Because states are asynchronous by nature, this\n * reference object is used to cache time-sensitive value changes while drag event happens.\n *\n * @param value - The value to set the associated value to.\n *\n * @returns `true` if the value was set, `false` otherwise.\n */\n function setValueRef(value: T): boolean {\n if (_.isEqual(valueRef.current, value)) return false\n valueRef.current = value\n return true\n }\n\n useEffect(() => {\n // debug(`Using drag effect for element ${targetRef.current}...`, 'OK', `value=${valueRef.current}`)\n\n if (targetRef.current && !interact.isSet(targetRef.current)) {\n // Do not consume states in these listeners as they will remain their initial values within\n // the scope of the listeners.\n interact(targetRef.current).draggable({\n inertia: true,\n ...options,\n onstart: () => {\n setIsDragging(true)\n onDragStart?.()\n },\n onmove: ({ dx, dy }) => {\n const newValue = transform?.(valueRef.current, dx, dy) ?? [dx, dy] as unknown as T\n\n if (setValueRef(newValue)) {\n // debug('Updating value from dragging...', 'OK', newValue)\n setValue(newValue)\n }\n\n onDragMove?.(dx, dy)\n },\n onend: () => {\n setIsDragging(false)\n onDragEnd?.()\n },\n })\n }\n\n return () => {\n // debug(`Removing drag effect for element ${targetRef.current}...`, 'OK', `value=${valueRef.current}`)\n\n if (targetRef.current && interact.isSet(targetRef.current)) {\n interact(targetRef.current).unset()\n }\n }\n }, [...deps ? deps : []])\n\n useEffect(() => {\n if (setValueRef(value)) {\n // debug('Updating value from externally...', 'OK', value)\n }\n }, [value])\n\n return {\n isDragging: [isDragging, setIsDragging],\n value: [value, setValue],\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "etudes",
3
- "version": "0.36.0",
3
+ "version": "0.37.0",
4
4
  "description": "A study of styled React components",
5
5
  "main": "lib",
6
6
  "scripts": {