etudes 1.2.0 → 2.0.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.
Files changed (120) hide show
  1. package/README.md +1 -1
  2. package/lib/Accordion.d.ts +80 -71
  3. package/lib/Accordion.js +173 -183
  4. package/lib/Accordion.js.map +1 -1
  5. package/lib/BurgerButton.d.ts +20 -7
  6. package/lib/BurgerButton.js +113 -20
  7. package/lib/BurgerButton.js.map +1 -1
  8. package/lib/Conditional.d.ts +2 -3
  9. package/lib/Conditional.js +0 -1
  10. package/lib/Conditional.js.map +1 -1
  11. package/lib/DebugConsole.d.ts +14 -23
  12. package/lib/DebugConsole.js +86 -87
  13. package/lib/DebugConsole.js.map +1 -1
  14. package/lib/Dial.d.ts +53 -16
  15. package/lib/Dial.js +121 -35
  16. package/lib/Dial.js.map +1 -1
  17. package/lib/Dropdown.d.ts +68 -83
  18. package/lib/Dropdown.js +226 -161
  19. package/lib/Dropdown.js.map +1 -1
  20. package/lib/Each.d.ts +2 -2
  21. package/lib/Each.js.map +1 -1
  22. package/lib/ExtractChild.d.ts +5 -4
  23. package/lib/ExtractChild.js +13 -11
  24. package/lib/ExtractChild.js.map +1 -1
  25. package/lib/ExtractChildren.d.ts +2 -2
  26. package/lib/ExtractChildren.js +7 -5
  27. package/lib/ExtractChildren.js.map +1 -1
  28. package/lib/FlatSVG.d.ts +30 -25
  29. package/lib/FlatSVG.js +28 -37
  30. package/lib/FlatSVG.js.map +1 -1
  31. package/lib/List.d.ts +97 -54
  32. package/lib/List.js +124 -63
  33. package/lib/List.js.map +1 -1
  34. package/lib/MasonryGrid.d.ts +27 -15
  35. package/lib/MasonryGrid.js +163 -148
  36. package/lib/MasonryGrid.js.map +1 -1
  37. package/lib/Panorama.d.ts +100 -21
  38. package/lib/Panorama.js +45 -44
  39. package/lib/Panorama.js.map +1 -1
  40. package/lib/PanoramaSlider.d.ts +65 -23
  41. package/lib/PanoramaSlider.js +150 -45
  42. package/lib/PanoramaSlider.js.map +1 -1
  43. package/lib/RangeSlider.d.ts +29 -89
  44. package/lib/RangeSlider.js +272 -286
  45. package/lib/RangeSlider.js.map +1 -1
  46. package/lib/Repeat.d.ts +4 -3
  47. package/lib/Repeat.js +3 -2
  48. package/lib/Repeat.js.map +1 -1
  49. package/lib/RotatingGallery.d.ts +38 -36
  50. package/lib/RotatingGallery.js +47 -17
  51. package/lib/RotatingGallery.js.map +1 -1
  52. package/lib/SelectableButton.d.ts +13 -4
  53. package/lib/SelectableButton.js +3 -14
  54. package/lib/SelectableButton.js.map +1 -1
  55. package/lib/Slider.d.ts +103 -41
  56. package/lib/Slider.js +182 -82
  57. package/lib/Slider.js.map +1 -1
  58. package/lib/StepwiseSlider.d.ts +146 -59
  59. package/lib/StepwiseSlider.js +248 -142
  60. package/lib/StepwiseSlider.js.map +1 -1
  61. package/lib/SwipeContainer.d.ts +13 -5
  62. package/lib/SwipeContainer.js +5 -15
  63. package/lib/SwipeContainer.js.map +1 -1
  64. package/lib/TextField.d.ts +1 -1
  65. package/lib/TextField.js +5 -15
  66. package/lib/TextField.js.map +1 -1
  67. package/lib/Video.d.ts +30 -51
  68. package/lib/Video.js +77 -119
  69. package/lib/Video.js.map +1 -1
  70. package/lib/WithTooltip.d.ts +16 -18
  71. package/lib/WithTooltip.js +167 -101
  72. package/lib/WithTooltip.js.map +1 -1
  73. package/lib/hooks/useDocumentTitle.d.ts +2 -1
  74. package/lib/hooks/useDocumentTitle.js +2 -1
  75. package/lib/hooks/useDocumentTitle.js.map +1 -1
  76. package/lib/hooks/useDragEffect.d.ts +25 -16
  77. package/lib/hooks/useDragEffect.js +30 -20
  78. package/lib/hooks/useDragEffect.js.map +1 -1
  79. package/lib/hooks/useElementRect.d.ts +2 -1
  80. package/lib/hooks/useElementRect.js +5 -4
  81. package/lib/hooks/useElementRect.js.map +1 -1
  82. package/lib/hooks/useInterval.d.ts +2 -2
  83. package/lib/hooks/useInterval.js +1 -1
  84. package/lib/hooks/useInterval.js.map +1 -1
  85. package/lib/hooks/useLoadImageEffect.d.ts +6 -6
  86. package/lib/hooks/useLoadImageEffect.js.map +1 -1
  87. package/lib/hooks/usePrevious.d.ts +6 -0
  88. package/lib/hooks/usePrevious.js +17 -0
  89. package/lib/hooks/usePrevious.js.map +1 -0
  90. package/lib/hooks/useResizeEffect.d.ts +2 -2
  91. package/lib/hooks/useResizeEffect.js +5 -8
  92. package/lib/hooks/useResizeEffect.js.map +1 -1
  93. package/lib/hooks/useSearchParamState.d.ts +10 -7
  94. package/lib/hooks/useSearchParamState.js +14 -10
  95. package/lib/hooks/useSearchParamState.js.map +1 -1
  96. package/lib/utils/asClassNameDict.d.ts +3 -0
  97. package/lib/utils/asClassNameDict.js +7 -0
  98. package/lib/utils/asClassNameDict.js.map +1 -0
  99. package/lib/utils/asComponentDict.d.ts +5 -0
  100. package/lib/utils/asComponentDict.js +23 -0
  101. package/lib/utils/asComponentDict.js.map +1 -0
  102. package/lib/utils/asStyleDict.d.ts +4 -0
  103. package/lib/utils/asStyleDict.js +7 -0
  104. package/lib/utils/asStyleDict.js.map +1 -0
  105. package/lib/utils/cloneStyledElement.d.ts +18 -0
  106. package/lib/utils/cloneStyledElement.js +63 -0
  107. package/lib/utils/cloneStyledElement.js.map +1 -0
  108. package/lib/utils/styles.d.ts +2 -0
  109. package/lib/utils/styles.js +22 -0
  110. package/lib/utils/styles.js.map +1 -0
  111. package/lib/utils/useDebug.d.ts +2 -0
  112. package/lib/utils/useDebug.js +46 -0
  113. package/lib/utils/useDebug.js.map +1 -0
  114. package/package.json +25 -33
  115. package/lib/AbstractSelectableCollection.d.ts +0 -94
  116. package/lib/AbstractSelectableCollection.js +0 -151
  117. package/lib/AbstractSelectableCollection.js.map +0 -1
  118. package/lib/types/index.d.ts +0 -7
  119. package/lib/types/index.js +0 -3
  120. package/lib/types/index.js.map +0 -1
package/lib/Panorama.d.ts CHANGED
@@ -1,14 +1,15 @@
1
- import { HTMLAttributes } from 'react';
1
+ import React, { HTMLAttributes } from 'react';
2
2
  import { Size } from 'spase';
3
- export declare type Props = HTMLAttributes<HTMLDivElement> & {
3
+ export declare type PanoramaProps = Omit<HTMLAttributes<HTMLDivElement>, 'onResize'> & {
4
4
  /**
5
- * The current angle in degrees, 0.0 - 360.0, inclusive. When angle is 0 or 360, the left bound of
6
- * the image is at the center of the component.
5
+ * The current angle in degrees, 0.0 - 360.0, inclusive. When angle is 0 or
6
+ * 360, the left bound of the image is at the center of the component.
7
7
  */
8
8
  angle?: number;
9
9
  /**
10
- * The panning speed. This is a multiplier to the number of pixels dragged, i.e. when set to 1,
11
- * the image will shift the same amount of pixels that were dragged.
10
+ * The panning speed. This is a multiplier to the number of pixels dragged,
11
+ * i.e. when set to 1, the image will shift the same amount of pixels that
12
+ * were dragged.
12
13
  */
13
14
  speed?: number;
14
15
  /**
@@ -16,24 +17,24 @@ export declare type Props = HTMLAttributes<HTMLDivElement> & {
16
17
  */
17
18
  src?: string;
18
19
  /**
19
- * A decimal percentage of the component width indicating where 0° should be, i.e. if `zeroAnchor`
20
- * is `0`, the `angle` would be 0° when the left edge of the image is at the left edge of the
21
- * component.
20
+ * A decimal percentage of the component width indicating where 0° should be,
21
+ * i.e. if `zeroAnchor` is `0`, the `angle` would be 0° when the left edge of
22
+ * the image is at the left edge of the component.
22
23
  */
23
24
  zeroAnchor?: number;
24
25
  /**
25
- * Handler invoked when the positionchanges. This can either be invoked from the `angle` prop
26
- * being changed or from the image being dragged.
26
+ * Handler invoked when the positionchanges. This can either be invoked from
27
+ * the `angle` prop being changed or from the image being dragged.
27
28
  *
28
29
  * @param position - The current position.
29
30
  * @param isDragging - Specifies if the position change is due to dragging.
30
31
  */
31
32
  onPositionChange?: (position: number, isDragging: boolean) => void;
32
33
  /**
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
+ * Handler invoked when the angle changes. This can either be invoked from the
35
+ * `angle` prop being changed or from the image being dragged. When `angle` is
36
+ * being double-binded, ensure that the value is only being set by this
37
+ * handler when `isDragging` is `true` to avoid potential update overflow.
37
38
  *
38
39
  * @param angle - The current angle.
39
40
  * @param isDragging - Specifies if the angle change is due to dragging.
@@ -62,11 +63,11 @@ export declare type Props = HTMLAttributes<HTMLDivElement> & {
62
63
  */
63
64
  onImageLoadError?: () => void;
64
65
  /**
65
- * Handler invoked when the image size changes. This is the actual size of the loaded image. When
66
- * no images are loaded yet, the size is `undefined`.
66
+ * Handler invoked when the image size changes. This is the actual size of the
67
+ * loaded image. When no images are loaded yet, the size is `undefined`.
67
68
  *
68
- * @param size - The actual size of the loaded iamge. If no images are loaded yet, the size is
69
- * `undefined`.
69
+ * @param size - The actual size of the loaded iamge. If no images are loaded
70
+ * yet, the size is `undefined`.
70
71
  */
71
72
  onImageSizeChange?: (size?: Size) => void;
72
73
  /**
@@ -77,6 +78,84 @@ export declare type Props = HTMLAttributes<HTMLDivElement> & {
77
78
  onResize?: (size: Size) => void;
78
79
  };
79
80
  /**
80
- * A component containing a pannable 360° panorama image. The angle supports two-way binding.
81
+ * A component containing a pannable 360° panorama image. The angle supports
82
+ * two-way binding.
81
83
  */
82
- export default function Panorama({ angle: externalAngle, speed, src, zeroAnchor, onAngleChange, onPositionChange, onDragStart, onDragEnd, onImageLoadStart, onImageLoadComplete, onImageLoadError, onImageSizeChange, onResize, ...props }: Props): JSX.Element;
84
+ declare const _default: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLDivElement>, "onResize"> & {
85
+ /**
86
+ * The current angle in degrees, 0.0 - 360.0, inclusive. When angle is 0 or
87
+ * 360, the left bound of the image is at the center of the component.
88
+ */
89
+ angle?: number | undefined;
90
+ /**
91
+ * The panning speed. This is a multiplier to the number of pixels dragged,
92
+ * i.e. when set to 1, the image will shift the same amount of pixels that
93
+ * were dragged.
94
+ */
95
+ speed?: number | undefined;
96
+ /**
97
+ * The source URL of the image.
98
+ */
99
+ src?: string | undefined;
100
+ /**
101
+ * A decimal percentage of the component width indicating where 0° should be,
102
+ * i.e. if `zeroAnchor` is `0`, the `angle` would be 0° when the left edge of
103
+ * the image is at the left edge of the component.
104
+ */
105
+ zeroAnchor?: number | undefined;
106
+ /**
107
+ * Handler invoked when the positionchanges. This can either be invoked from
108
+ * the `angle` prop being changed or from the image being dragged.
109
+ *
110
+ * @param position - The current position.
111
+ * @param isDragging - Specifies if the position change is due to dragging.
112
+ */
113
+ onPositionChange?: ((position: number, isDragging: boolean) => void) | undefined;
114
+ /**
115
+ * Handler invoked when the angle changes. This can either be invoked from the
116
+ * `angle` prop being changed or from the image being dragged. When `angle` is
117
+ * being double-binded, ensure that the value is only being set by this
118
+ * handler when `isDragging` is `true` to avoid potential update overflow.
119
+ *
120
+ * @param angle - The current angle.
121
+ * @param isDragging - Specifies if the angle change is due to dragging.
122
+ */
123
+ onAngleChange?: ((angle: number, isDragging: boolean) => void) | undefined;
124
+ /**
125
+ * Handler invoked when dragging starts.
126
+ */
127
+ onDragStart?: (() => void) | undefined;
128
+ /**
129
+ * Handler invoked when dragging ends.
130
+ */
131
+ onDragEnd?: (() => void) | undefined;
132
+ /**
133
+ * Handler invoked when the image begins loading.
134
+ */
135
+ onImageLoadStart?: (() => void) | undefined;
136
+ /**
137
+ * Handler invoked when the image is done loading.
138
+ *
139
+ * @param imageElement - The loaded image element.
140
+ */
141
+ onImageLoadComplete?: ((imageElement: HTMLImageElement) => void) | undefined;
142
+ /**
143
+ * Handler invoked when there is an error loading the image.
144
+ */
145
+ onImageLoadError?: (() => void) | undefined;
146
+ /**
147
+ * Handler invoked when the image size changes. This is the actual size of the
148
+ * loaded image. When no images are loaded yet, the size is `undefined`.
149
+ *
150
+ * @param size - The actual size of the loaded iamge. If no images are loaded
151
+ * yet, the size is `undefined`.
152
+ */
153
+ onImageSizeChange?: ((size?: Size | undefined) => void) | undefined;
154
+ /**
155
+ * Handler invoked when the size of this component changes.
156
+ *
157
+ * @param size - The size of this component.
158
+ */
159
+ onResize?: ((size: Size) => void) | undefined;
160
+ } & React.RefAttributes<HTMLDivElement>>;
161
+ export default _default;
package/lib/Panorama.js CHANGED
@@ -1,8 +1,4 @@
1
1
  "use strict";
2
- var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3
- if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4
- return cooked;
5
- };
6
2
  var __assign = (this && this.__assign) || function () {
7
3
  __assign = Object.assign || function(t) {
8
4
  for (var s, i = 1, n = arguments.length; i < n; i++) {
@@ -70,52 +66,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
70
66
  Object.defineProperty(exports, "__esModule", { value: true });
71
67
  var react_1 = __importStar(require("react"));
72
68
  var spase_1 = require("spase");
73
- var styled_components_1 = __importDefault(require("styled-components"));
74
69
  var useDragEffect_1 = __importDefault(require("./hooks/useDragEffect"));
75
70
  var useLoadImageEffect_1 = __importDefault(require("./hooks/useLoadImageEffect"));
76
71
  var useResizeEffect_1 = __importDefault(require("./hooks/useResizeEffect"));
77
- function getFilledImageSize(originalSize, sizeToFill) {
78
- var originalWidth = originalSize.width, originalHeight = originalSize.height;
79
- var filledHeignt = sizeToFill.height;
80
- if (originalHeight <= 0)
81
- return new spase_1.Size();
82
- var aspectRatio = filledHeignt / originalHeight;
83
- var filledWidth = aspectRatio * originalWidth;
84
- return new spase_1.Size([filledWidth, filledHeignt]);
85
- }
86
- function getDisplacementFromAngle(angle, originalImageSize, componentSize, zeroAnchor) {
87
- var imageWidth = getFilledImageSize(originalImageSize, componentSize).width;
88
- var componentWidth = componentSize.width;
89
- var offset = componentWidth * zeroAnchor;
90
- return (angle / 360) * imageWidth - offset;
91
- }
92
- function getAngleFromDisplacement(displacement, originalImageSize, componentSize, zeroAnchor) {
93
- var imageWidth = getFilledImageSize(originalImageSize, componentSize).width;
94
- var componentWidth = componentSize.width;
95
- var offset = componentWidth * zeroAnchor;
96
- var angle = ((displacement + offset) % imageWidth) / imageWidth * 360;
97
- while (angle < 0)
98
- angle += 360;
99
- return angle;
100
- }
72
+ var asStyleDict_1 = __importDefault(require("./utils/asStyleDict"));
101
73
  /**
102
- * A component containing a pannable 360° panorama image. The angle supports two-way binding.
74
+ * A component containing a pannable 360° panorama image. The angle supports
75
+ * two-way binding.
103
76
  */
104
- function Panorama(_a) {
77
+ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
105
78
  var _b = _a.angle, externalAngle = _b === void 0 ? 0 : _b, _c = _a.speed, speed = _c === void 0 ? 1 : _c, src = _a.src, _d = _a.zeroAnchor, zeroAnchor = _d === void 0 ? 0 : _d, onAngleChange = _a.onAngleChange, onPositionChange = _a.onPositionChange, onDragStart = _a.onDragStart, onDragEnd = _a.onDragEnd, onImageLoadStart = _a.onImageLoadStart, onImageLoadComplete = _a.onImageLoadComplete, onImageLoadError = _a.onImageLoadError, onImageSizeChange = _a.onImageSizeChange, onResize = _a.onResize, props = __rest(_a, ["angle", "speed", "src", "zeroAnchor", "onAngleChange", "onPositionChange", "onDragStart", "onDragEnd", "onImageLoadStart", "onImageLoadComplete", "onImageLoadError", "onImageSizeChange", "onResize"]);
106
79
  var mapDragPositionToDisplacement = function (currentPosition, dx, dy) {
107
- var newDisplacement = currentPosition - (dx * speed);
80
+ var newDisplacement = currentPosition - dx * speed;
108
81
  return newDisplacement;
109
82
  };
110
- var rootRef = (0, react_1.useRef)(null);
111
- var _e = __read((0, useResizeEffect_1.default)(rootRef, { onResize: onResize }), 1), size = _e[0];
83
+ var bodyRef = (0, react_1.useRef)(null);
84
+ var _e = __read((0, useResizeEffect_1.default)(bodyRef, { onResize: onResize }), 1), size = _e[0];
112
85
  var _f = __read((0, react_1.useState)(externalAngle), 2), angle = _f[0], setAngle = _f[1];
113
86
  var _g = (0, useLoadImageEffect_1.default)(src, {
114
87
  onImageLoadComplete: onImageLoadComplete,
115
88
  onImageLoadError: onImageLoadError,
116
89
  onImageSizeChange: onImageSizeChange,
117
90
  }), _h = __read(_g.isLoading, 1), isLoading = _h[0], _j = __read(_g.imageSize, 1), imageSize = _j[0];
118
- var _k = (0, useDragEffect_1.default)(rootRef, {
91
+ var _k = (0, useDragEffect_1.default)(bodyRef, {
119
92
  initialValue: 0,
120
93
  transform: mapDragPositionToDisplacement,
121
94
  onDragStart: onDragStart,
@@ -144,14 +117,42 @@ function Panorama(_a) {
144
117
  onAngleChange === null || onAngleChange === void 0 ? void 0 : onAngleChange(angle, isDragging);
145
118
  onPositionChange === null || onPositionChange === void 0 ? void 0 : onPositionChange(angle / 360, isDragging);
146
119
  }, [angle]);
147
- return (react_1.default.createElement(StyledRoot, __assign({ ref: rootRef }, props),
148
- react_1.default.createElement(StyledImageContainer, { style: {
149
- backgroundImage: "url(".concat(src, ")"),
150
- backgroundPositionX: "".concat(-displacement, "px"),
151
- } })));
120
+ var fixedStyles = (0, asStyleDict_1.default)({
121
+ body: {
122
+ backgroundImage: "url(".concat(src, ")"),
123
+ backgroundPositionX: "".concat(-displacement, "px"),
124
+ backgroundRepeat: 'repeat',
125
+ backgroundSize: 'auto 100%',
126
+ height: '100%',
127
+ touchAction: 'none',
128
+ width: '100%',
129
+ },
130
+ });
131
+ return (react_1.default.createElement("div", __assign({}, props, { ref: ref }),
132
+ react_1.default.createElement("div", { ref: bodyRef, style: fixedStyles.body })));
133
+ });
134
+ function getFilledImageSize(originalSize, sizeToFill) {
135
+ var originalWidth = originalSize.width, originalHeight = originalSize.height;
136
+ var filledHeignt = sizeToFill.height;
137
+ if (originalHeight <= 0)
138
+ return new spase_1.Size();
139
+ var aspectRatio = filledHeignt / originalHeight;
140
+ var filledWidth = aspectRatio * originalWidth;
141
+ return new spase_1.Size([filledWidth, filledHeignt]);
142
+ }
143
+ function getDisplacementFromAngle(angle, originalImageSize, componentSize, zeroAnchor) {
144
+ var imageWidth = getFilledImageSize(originalImageSize, componentSize).width;
145
+ var componentWidth = componentSize.width;
146
+ var offset = componentWidth * zeroAnchor;
147
+ return angle / 360 * imageWidth - offset;
148
+ }
149
+ function getAngleFromDisplacement(displacement, originalImageSize, componentSize, zeroAnchor) {
150
+ var imageWidth = getFilledImageSize(originalImageSize, componentSize).width;
151
+ var componentWidth = componentSize.width;
152
+ var offset = componentWidth * zeroAnchor;
153
+ var angle = (displacement + offset) % imageWidth / imageWidth * 360;
154
+ while (angle < 0)
155
+ angle += 360;
156
+ return angle;
152
157
  }
153
- exports.default = Panorama;
154
- var StyledImageContainer = styled_components_1.default.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\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 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"])));
155
- var StyledRoot = styled_components_1.default.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n align-items: center;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n flex: 0 0 auto;\n height: 100%;\n justify-content: center;\n padding: 0;\n position: relative;\n touch-action: none;\n width: 100%;\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 align-items: center;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n flex: 0 0 auto;\n height: 100%;\n justify-content: center;\n padding: 0;\n position: relative;\n touch-action: none;\n width: 100%;\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"])));
156
- var templateObject_1, templateObject_2;
157
158
  //# sourceMappingURL=Panorama.js.map
@@ -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\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 */\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 const mapDragPositionToDisplacement = (currentPosition: number, dx: number, dy: number): number => {\n const newDisplacement = currentPosition - (dx * speed)\n return newDisplacement\n }\n\n const rootRef = useRef<HTMLDivElement>(null)\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: mapDragPositionToDisplacement,\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 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 height: 100%;\n justify-content: center;\n padding: 0;\n position: relative;\n touch-action: none;\n width: 100%;\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, { forwardRef, HTMLAttributes, useEffect, useRef, useState } from 'react'\nimport { Size } from 'spase'\nimport useDragEffect from './hooks/useDragEffect'\nimport useLoadImageEffect from './hooks/useLoadImageEffect'\nimport useResizeEffect from './hooks/useResizeEffect'\nimport asStyleDict from './utils/asStyleDict'\n\nexport type PanoramaProps = Omit<HTMLAttributes<HTMLDivElement>, 'onResize'> & {\n /**\n * The current angle in degrees, 0.0 - 360.0, inclusive. When angle is 0 or\n * 360, the left bound of 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,\n * i.e. when set to 1, the image will shift the same amount of pixels that\n * 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,\n * i.e. if `zeroAnchor` is `0`, the `angle` would be 0° when the left edge of\n * the image is at the left edge of the component.\n */\n zeroAnchor?: number\n\n /**\n * Handler invoked when the positionchanges. This can either be invoked from\n * the `angle` prop 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\n * `angle` prop being changed or from the image being dragged. When `angle` is\n * being double-binded, ensure that the value is only being set by this\n * handler when `isDragging` is `true` to avoid potential update 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\n * loaded image. When 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\n * yet, the size is `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\n/**\n * A component containing a pannable 360° panorama image. The angle supports\n * two-way binding.\n */\nexport default forwardRef<HTMLDivElement, PanoramaProps>(({\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}, ref) => {\n const mapDragPositionToDisplacement = (currentPosition: number, dx: number, dy: number): number => {\n const newDisplacement = currentPosition - dx * speed\n\n return newDisplacement\n }\n\n const bodyRef = useRef<HTMLDivElement>(null)\n const [size] = useResizeEffect(bodyRef, { 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(bodyRef, {\n initialValue: 0,\n transform: mapDragPositionToDisplacement,\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 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 const fixedStyles = asStyleDict({\n body: {\n backgroundImage: `url(${src})`,\n backgroundPositionX: `${-displacement}px`,\n backgroundRepeat: 'repeat',\n backgroundSize: 'auto 100%',\n height: '100%',\n touchAction: 'none',\n width: '100%',\n },\n })\n\n return (\n <div {...props} ref={ref}>\n <div ref={bodyRef} style={fixedStyles.body}/>\n </div>\n )\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\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\n return angle\n}\n"]}
@@ -1,36 +1,78 @@
1
- import { HTMLAttributes } from 'react';
1
+ import React, { HTMLAttributes, PropsWithChildren } from 'react';
2
2
  import { Size } from 'spase';
3
- import Panorama, { Props as PanoramaProps } from './Panorama';
4
- export declare type Props = HTMLAttributes<HTMLDivElement> & PanoramaProps & {
3
+ import { PanoramaProps } from './Panorama';
4
+ export declare type PanoramaSliderProps = HTMLAttributes<HTMLDivElement> & PanoramaProps & PropsWithChildren<{
5
5
  /**
6
- * Field-of-view (0.0 - 360.0 degrees, inclusive) that represents the size of the reticle. 360
7
- * indicates the reticle covers the entire image. If this is unspecified, the component will
8
- * attempt to automatically calculate the FOV using the `viewportSize` prop.
6
+ * Field-of-view (0.0 - 360.0 degrees, inclusive) that represents the size of
7
+ * the reticle. 360 indicates the reticle covers the entire image. If this is
8
+ * unspecified, the component will attempt to automatically calculate the FOV
9
+ * using the `viewportSize` prop.
9
10
  */
10
11
  fov?: number;
11
12
  /**
12
- * Specifies which length (width or height) should be automatically calculated. The counterpart
13
- * must be known (if `width` is specified here, the component's height must be known, i.e. it is
14
- * specified in the CSS). Defaults to `width`.
13
+ * Specifies which length (width or height) should be automatically
14
+ * calculated. The counterpart must be known (if `width` is specified here,
15
+ * the component's height must be known, i.e. it is specified in the CSS).
16
+ * Defaults to `width`.
15
17
  */
16
18
  autoDimension?: 'width' | 'height';
17
19
  /**
18
- * Size of the viewport that this component is controlling. A viewport can be thought of as a DOM
19
- * element containing an aspect-filled image. This is used to automatically calculate the FOV if
20
- * `fov` prop is not specified. If it is, this prop is ignored.
20
+ * Size of the viewport that this component is controlling. A viewport can be
21
+ * thought of as a DOM element containing an aspect-filled image. This is used
22
+ * to automatically calculate the FOV if `fov` prop is not specified. If it
23
+ * is, this prop is ignored.
21
24
  */
22
25
  viewportSize?: Size;
23
- };
26
+ }>;
24
27
  /**
25
- * A slider for {@link Panorama} components.
28
+ * A slider for a {@link Panorama} component.
26
29
  *
27
- * @exports PanoramaSliderImage
28
- * @exports PanoramaSliderIndicator
29
- * @exports PanoramaSliderTrack
30
- * @exports PanoramaSliderReticle
30
+ * @exports PanoramaSliderIndicator - The indicator that appears when the slider
31
+ * is being dragged.
32
+ * @exports PanoramaSliderReticle - The reticle that indicates the FOV of the
33
+ * backing {@link Panorama}.
34
+ * @exports PanoramaSliderTrack - The slide track.
31
35
  */
32
- export default function PanoramaSlider({ fov, autoDimension, viewportSize, angle, speed, src, zeroAnchor, onAngleChange, onPositionChange, onDragStart, onDragEnd, onImageLoadStart, onImageLoadComplete, onImageLoadError, onImageSizeChange, onResize, style, ...props }: Props): JSX.Element;
33
- export declare const PanoramaSliderReticle: import("styled-components").StyledComponent<"div", any, {}, never>;
34
- export declare const PanoramaSliderTrack: import("styled-components").StyledComponent<"div", any, {}, never>;
35
- export declare const PanoramaSliderIndicator: import("styled-components").StyledComponent<"div", any, {}, never>;
36
- export declare const PanoramaSliderImage: import("styled-components").StyledComponent<typeof Panorama, any, {}, never>;
36
+ declare const _default: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & Omit<React.HTMLAttributes<HTMLDivElement>, "onResize"> & {
37
+ angle?: number | undefined;
38
+ speed?: number | undefined;
39
+ src?: string | undefined;
40
+ zeroAnchor?: number | undefined;
41
+ onPositionChange?: ((position: number, isDragging: boolean) => void) | undefined;
42
+ onAngleChange?: ((angle: number, isDragging: boolean) => void) | undefined;
43
+ onDragStart?: (() => void) | undefined;
44
+ onDragEnd?: (() => void) | undefined;
45
+ onImageLoadStart?: (() => void) | undefined;
46
+ onImageLoadComplete?: ((imageElement: HTMLImageElement) => void) | undefined;
47
+ onImageLoadError?: (() => void) | undefined;
48
+ onImageSizeChange?: ((size?: Size | undefined) => void) | undefined;
49
+ onResize?: ((size: Size) => void) | undefined;
50
+ } & {
51
+ /**
52
+ * Field-of-view (0.0 - 360.0 degrees, inclusive) that represents the size of
53
+ * the reticle. 360 indicates the reticle covers the entire image. If this is
54
+ * unspecified, the component will attempt to automatically calculate the FOV
55
+ * using the `viewportSize` prop.
56
+ */
57
+ fov?: number | undefined;
58
+ /**
59
+ * Specifies which length (width or height) should be automatically
60
+ * calculated. The counterpart must be known (if `width` is specified here,
61
+ * the component's height must be known, i.e. it is specified in the CSS).
62
+ * Defaults to `width`.
63
+ */
64
+ autoDimension?: "width" | "height" | undefined;
65
+ /**
66
+ * Size of the viewport that this component is controlling. A viewport can be
67
+ * thought of as a DOM element containing an aspect-filled image. This is used
68
+ * to automatically calculate the FOV if `fov` prop is not specified. If it
69
+ * is, this prop is ignored.
70
+ */
71
+ viewportSize?: Size | undefined;
72
+ } & {
73
+ children?: React.ReactNode;
74
+ } & React.RefAttributes<HTMLDivElement>>;
75
+ export default _default;
76
+ export declare const PanoramaSliderTrack: ({ ...props }: HTMLAttributes<HTMLDivElement>) => JSX.Element;
77
+ export declare const PanoramaSliderReticle: ({ ...props }: HTMLAttributes<HTMLDivElement>) => JSX.Element;
78
+ export declare const PanoramaSliderIndicator: ({ ...props }: HTMLAttributes<HTMLDivElement>) => JSX.Element;