ebta-workflow-prod 4.1.2 → 4.1.4

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ebta-workflow-prod",
3
3
  "private": false,
4
- "version": "4.1.2",
4
+ "version": "4.1.4",
5
5
  "description": "",
6
6
  "license": "UNLICENSED",
7
7
  "author": "",
@@ -32,8 +32,8 @@
32
32
  "@fseehawer/react-circular-slider": "^3.2.7",
33
33
  "@mantine/core": "^7.16.0",
34
34
  "@mantine/hooks": "^9.5.1",
35
- "@mui/icons-material": "^5.17.1",
36
35
  "@mui/base": "5.0.0-beta.70",
36
+ "@mui/icons-material": "^5.17.1",
37
37
  "@mui/material": "^5.17.1",
38
38
  "@mui/x-charts": "^7.6.2",
39
39
  "@turf/turf": "^6.5.0",
@@ -44,6 +44,7 @@
44
44
  "axios": "^1.7.7",
45
45
  "dayjs": "^1.11.23",
46
46
  "html2canvas": "^1.4.1",
47
+ "marzipano": "^0.10.2",
47
48
  "pannellum-react-update": "^1.0.0",
48
49
  "pdf-lib": "^1.17.1",
49
50
  "qrcode": "^1.5.4",
@@ -0,0 +1,239 @@
1
+ import type { IActivityHandler } from "@vertigis/workflow";
2
+
3
+ import Polygon from "@arcgis/core/geometry/Polygon";
4
+ import SpatialReference from "@arcgis/core/geometry/SpatialReference";
5
+
6
+
7
+ /** An interface that defines the inputs of the activity. */
8
+ interface SimplifyGeometryInputs {
9
+ /**
10
+ * @displayName Geometry
11
+ * @description The geometry to be simplified.
12
+ * @required
13
+ */
14
+ geometry: Polygon;
15
+
16
+ /**
17
+ * @displayName Vertex Limit
18
+ * @description The maximum number of vertices allowed in the simplified geometry.
19
+ */
20
+ vertlimit?: number;
21
+ }
22
+
23
+ /** An interface that defines the outputs of the activity. */
24
+ interface SimplifyGeometryOutputs {
25
+ /**
26
+ * @description The result of the activity.
27
+ */
28
+ result: Polygon;
29
+ }
30
+
31
+ /**
32
+ * @displayName SimplifyGeometry
33
+ * @category Custom Activities
34
+ * @description Simplify geometry - covering the whole geometry and increase minimum extra area, under required vertex amount.
35
+ */
36
+ export default class SimplifyGeometryActivity implements IActivityHandler {
37
+ /** Perform the execution logic of the activity. */
38
+
39
+ execute(inputs: SimplifyGeometryInputs): SimplifyGeometryOutputs {
40
+
41
+ // Clone the whole result so we never touch the original $permitFeature.result
42
+ let simplifyresult = inputs.geometry;
43
+ let limit = inputs.vertlimit || 30;
44
+
45
+ let ring = simplifyresult.rings[0];
46
+
47
+ if (ring.length > limit) {
48
+ ring = coveringSimplify(ring, limit);
49
+
50
+ simplifyresult.rings[0] = ring;
51
+ }
52
+
53
+ return { result: simplifyresult };
54
+
55
+
56
+
57
+
58
+ // ---- geometry helpers ----
59
+ function cross(o, a, b) {
60
+ return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
61
+ }
62
+ function triangleArea(a, b, c) {
63
+ return Math.abs(cross(a, b, c)) / 2;
64
+ }
65
+ function signedArea(points) {
66
+ var area = 0, n = points.length;
67
+ for (var i = 0; i < n; i++) {
68
+ var p1 = points[i], p2 = points[(i + 1) % n];
69
+ area += p1[0] * p2[1] - p2[0] * p1[1];
70
+ }
71
+ return area / 2;
72
+ }
73
+
74
+ // orientation: >0 CCW turn, <0 CW turn, 0 collinear
75
+ function orient(a, b, c) {
76
+ var v = (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
77
+ if (v > 1e-9) return 1;
78
+ if (v < -1e-9) return -1;
79
+ return 0;
80
+ }
81
+
82
+ // true only for a PROPER crossing (interior intersection), not shared endpoints/touching
83
+ function properlyIntersects(p1, p2, p3, p4) {
84
+ var d1 = orient(p3, p4, p1);
85
+ var d2 = orient(p3, p4, p2);
86
+ var d3 = orient(p1, p2, p3);
87
+ var d4 = orient(p1, p2, p4);
88
+ return (d1 !== d2 && d1 !== 0 && d2 !== 0) && (d3 !== d4 && d3 !== 0 && d4 !== 0);
89
+ }
90
+
91
+ // does chording out vertex i (prev->next) cross any OTHER edge of
92
+ // the polygon? Required check — without it, concave removal can
93
+ // fold the polygon over itself into a self-intersecting bowtie on
94
+ // complex shapes (forks, interchanges, multiple concavities).
95
+ function chordIsSafe(pts, i) {
96
+ var n = pts.length;
97
+ var prev = pts[(i - 1 + n) % n];
98
+ var next = pts[(i + 1) % n];
99
+
100
+ for (var k = 0; k < n; k++) {
101
+ var a = pts[k];
102
+ var b = pts[(k + 1) % n];
103
+ if (k === (i - 1 + n) % n || k === i) continue; // the two edges being replaced
104
+ if (properlyIntersects(prev, next, a, b)) return false;
105
+ }
106
+ return true;
107
+ }
108
+
109
+ // Remove reflex (concave) vertices, cheapest-area first, but only
110
+ // when the resulting chord doesn't self-intersect the polygon.
111
+ // Chording a safe concave notch always ADDS area outside the
112
+ // original shape, so coverage is preserved automatically.
113
+ function removeReflexVertices(points, maxVertices) {
114
+ var pts = points.slice();
115
+ var orientSign = signedArea(pts) >= 0 ? 1 : -1;
116
+
117
+ var progress = true;
118
+ while (pts.length > maxVertices && progress) {
119
+ progress = false;
120
+ var n = pts.length;
121
+ var candidates = [];
122
+
123
+ for (var i = 0; i < n; i++) {
124
+ var prev = pts[(i - 1 + n) % n];
125
+ var curr = pts[i];
126
+ var next = pts[(i + 1) % n];
127
+ var c = cross(prev, curr, next);
128
+ var isReflexOrFlat = c * orientSign <= 1e-9;
129
+ if (isReflexOrFlat) {
130
+ candidates.push({ idx: i, area: triangleArea(prev, curr, next) });
131
+ }
132
+ }
133
+
134
+ candidates.sort(function (a, b) { return a.area - b.area; });
135
+
136
+ for (var ci = 0; ci < candidates.length; ci++) {
137
+ var idx = candidates[ci].idx;
138
+ if (chordIsSafe(pts, idx)) {
139
+ pts.splice(idx, 1);
140
+ progress = true;
141
+ break; // recompute fresh each removal since indices shift
142
+ }
143
+ }
144
+ }
145
+
146
+ return pts;
147
+ }
148
+
149
+ // Infinite-line intersection of (p1,p2) and (p3,p4).
150
+ function lineIntersection(p1, p2, p3, p4) {
151
+ var x1 = p1[0], y1 = p1[1], x2 = p2[0], y2 = p2[1];
152
+ var x3 = p3[0], y3 = p3[1], x4 = p4[0], y4 = p4[1];
153
+ var denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
154
+ if (Math.abs(denom) < 1e-9) return [(x2 + x3) / 2, (y2 + y3) / 2];
155
+ var pxNum = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);
156
+ var pyNum = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);
157
+ return [pxNum / denom, pyNum / denom];
158
+ }
159
+
160
+ // Standard monotone-chain convex hull — guaranteed simple and
161
+ // guaranteed to cover any input point set, regardless of how tangled
162
+ // the remaining shape is. Used as a safe fallback.
163
+ function convexHull(points) {
164
+ var sorted = points.slice().sort(function (a, b) { return a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]; });
165
+ var pts = [];
166
+ for (var i = 0; i < sorted.length; i++) {
167
+ var p = sorted[i], prev = pts[pts.length - 1];
168
+ if (!prev || prev[0] !== p[0] || prev[1] !== p[1]) pts.push(p);
169
+ }
170
+ var n = pts.length;
171
+ if (n < 3) return pts.slice();
172
+ var lower = [];
173
+ for (var i2 = 0; i2 < n; i2++) {
174
+ while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], pts[i2]) <= 0) lower.pop();
175
+ lower.push(pts[i2]);
176
+ }
177
+ var upper = [];
178
+ for (var i3 = n - 1; i3 >= 0; i3--) {
179
+ while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], pts[i3]) <= 0) upper.pop();
180
+ upper.push(pts[i3]);
181
+ }
182
+ lower.pop(); upper.pop();
183
+ return lower.concat(upper);
184
+ }
185
+
186
+ // Reduce an already-convex polygon to maxVertices by selecting
187
+ // maxVertices of its edges (evenly spaced) as infinite support lines
188
+ // and intersecting consecutive ones. Always contains the input.
189
+ function reduceConvexBySupportLines(points, maxVertices) {
190
+ var n = points.length;
191
+ if (n <= maxVertices) return points.slice();
192
+ var chosen = [];
193
+ for (var k = 0; k < maxVertices; k++) chosen.push(Math.floor((k * n) / maxVertices));
194
+ var newPts = [];
195
+ for (var k2 = 0; k2 < maxVertices; k2++) {
196
+ var iPrevEdge = chosen[(k2 - 1 + maxVertices) % maxVertices];
197
+ var iCurrEdge = chosen[k2];
198
+ var a1 = points[iPrevEdge], a2 = points[(iPrevEdge + 1) % n];
199
+ var b1 = points[iCurrEdge], b2 = points[(iCurrEdge + 1) % n];
200
+ newPts.push(lineIntersection(a1, a2, b1, b2));
201
+ }
202
+ return newPts;
203
+ }
204
+
205
+ // Simplify a ring to at most maxVertices points, guaranteeing the
206
+ // result is both SIMPLE (no self-intersections) and always covers
207
+ // (contains) the original shape.
208
+ function coveringSimplify(ring, maxVertices) {
209
+ var first = ring[0], last = ring[ring.length - 1];
210
+ var isClosed = first[0] === last[0] && first[1] === last[1];
211
+ var open = isClosed ? ring.slice(0, ring.length - 1) : ring.slice();
212
+ var budgetOpen = isClosed ? maxVertices - 1 : maxVertices;
213
+
214
+ if (open.length <= budgetOpen) return ring.slice();
215
+
216
+ var afterReflex = removeReflexVertices(open, budgetOpen);
217
+
218
+ var result;
219
+ if (afterReflex.length > budgetOpen) {
220
+ // Couldn't safely get all the way there via reflex removal
221
+ // (or the remainder is genuinely convex) — fall back to the
222
+ // convex hull, which is always simple and always covers.
223
+ var hull = convexHull(afterReflex);
224
+ result = hull.length > budgetOpen
225
+ ? reduceConvexBySupportLines(hull, budgetOpen)
226
+ : hull;
227
+ } else {
228
+ result = afterReflex;
229
+ }
230
+
231
+ return isClosed ? result.concat([result[0]]) : result;
232
+ }
233
+
234
+
235
+ return {
236
+ result: simplifyresult
237
+ };
238
+ }
239
+ }
@@ -1310,7 +1310,7 @@ function AttributeFilter(props: AttributeFilterProps): React.ReactElement {
1310
1310
  setProperty("filteredValues" as any, filterrangeResult)
1311
1311
  };
1312
1312
 
1313
- const normalizeNumber = (value: number) => Number(value.toFixed(10));
1313
+ const normalizeNumber = (value: number) => Number(value.toFixed(1));
1314
1314
 
1315
1315
  const maxStringLength = 28
1316
1316
  function itemText(item: fieldValue, type?: string) {
@@ -1419,8 +1419,8 @@ function AttributeFilter(props: AttributeFilterProps): React.ReactElement {
1419
1419
  ISnumberAttribute && (attribute.uniqValue.length > 6) ?
1420
1420
  //Display String search or number Range , don't display if value amount is limited
1421
1421
  <Box display="flex" alignItems="center">
1422
- <CustomNumberInput aria-label="min value input" placeholder={`Min (${attributeMin} ~ ${attributeMax})`} min={attributeMin - 1} max={attributeMax + 1}
1423
- value={minValue == -Infinity ? undefined : minValue} step={0.1}
1422
+ <CustomNumberInput aria-label="min value input" placeholder={`Min (${normalizeNumber(attributeMin)} ~ ${normalizeNumber(attributeMax)})`} min={attributeMin - 1} max={attributeMax + 1}
1423
+ value={minValue == -Infinity ? undefined : normalizeNumber(minValue)} step={0.1}
1424
1424
  onChange={(event, val) => {
1425
1425
  const normalizedValue = typeof val === 'number' ? normalizeNumber(val) : val;
1426
1426
  if (((normalizedValue || normalizedValue == 0) && (normalizedValue <= maxValue))) { setProperty("minValue" as any, normalizedValue) };
@@ -1437,8 +1437,8 @@ function AttributeFilter(props: AttributeFilterProps): React.ReactElement {
1437
1437
  }
1438
1438
  }}
1439
1439
  />
1440
- <CustomNumberInput aria-label="max value input" placeholder={`Max (${attributeMin} ~ ${attributeMax})`} min={attributeMin - 1} max={attributeMax + 1}
1441
- value={maxValue == Infinity ? undefined : maxValue} step={0.1}
1440
+ <CustomNumberInput aria-label="max value input" placeholder={`Max (${normalizeNumber(attributeMin)} ~ ${normalizeNumber(attributeMax)})`} min={attributeMin - 1} max={attributeMax + 1}
1441
+ value={maxValue == Infinity ? undefined : normalizeNumber(maxValue)} step={0.1}
1442
1442
  onChange={(_event, val) => {
1443
1443
  const normalizedValue = typeof val === 'number' ? normalizeNumber(val) : val;
1444
1444
  if ((normalizedValue || normalizedValue == 0) && (normalizedValue >= minValue)) { setProperty("maxValue" as any, normalizedValue) };
@@ -4,8 +4,9 @@ import { FormElementProps, FormElementRegistration } from "@vertigis/workflow";
4
4
  import { ColorInput, ColorPicker } from '@mantine/core';
5
5
  type ColorFormat = "hex" | "rgba" | "rgb" | "hsl" | "hsla";
6
6
 
7
- import "@mantine/core/styles.css";
8
-
7
+ //import "@mantine/core/styles.css";
8
+ //Causing shrink
9
+ import "../styles/mantine-scoped.css";
9
10
  import Color from "@arcgis/core/Color";
10
11
 
11
12
 
@@ -79,6 +80,7 @@ function CsColorPickerV2(props: CsColorPickerV2Props): React.ReactElement {
79
80
  };
80
81
 
81
82
  return (
83
+ <div className="vertigis-mantine-scope">
82
84
  <MantineProvider withStaticClasses withGlobalClasses classNamesPrefix="ebta-mantime">
83
85
  {componentType === "ColorInput" ? (
84
86
  <ColorInput
@@ -105,6 +107,7 @@ function CsColorPickerV2(props: CsColorPickerV2Props): React.ReactElement {
105
107
  />
106
108
  )}
107
109
  </MantineProvider>
110
+ </div>
108
111
  );
109
112
  }
110
113
 
@@ -0,0 +1,225 @@
1
+ import * as React from "react";
2
+ import { FormElementProps, FormElementRegistration } from "@vertigis/workflow";
3
+ import Marzipano from "marzipano";
4
+
5
+
6
+ /**
7
+ * The generic type argument provided to `FormElementProps<T>` controls the type
8
+ * of `props.value` and `props.setValue(value)`. If your element doesn't need a
9
+ * `value`, you can omit the type argument.
10
+ *
11
+ * You can also declare additional public properties of your element by adding
12
+ * properties to this interface. The properties will be managed by the Workflow
13
+ * runtime, and passed in as `props`. You can update the properties by using
14
+ * `props.setProperty(key, value)`.
15
+ */
16
+ interface PanovideoPlayerProps extends FormElementProps<string> {}
17
+
18
+ class VideoAsset extends (Marzipano as any).util.Emitter {
19
+ private _element: HTMLVideoElement;
20
+
21
+ constructor(videoElement: HTMLVideoElement) {
22
+ super();
23
+ this._element = videoElement;
24
+ // Marzipano polls isDynamic()/emits('change') to know when to redraw.
25
+ this._element.addEventListener("timeupdate", () => {
26
+ this.emit("change");
27
+ });
28
+ }
29
+
30
+ element(): HTMLVideoElement {
31
+ return this._element;
32
+ }
33
+
34
+ width(): number {
35
+ return this._element.videoWidth;
36
+ }
37
+
38
+ height(): number {
39
+ return this._element.videoHeight;
40
+ }
41
+
42
+ isDynamic(): boolean {
43
+ return true;
44
+ }
45
+ }
46
+
47
+ /**
48
+ * A Workflow element built using React.
49
+ * @displayName PanovideoPlayer
50
+ * @description Marzipano library panoramic video player
51
+ * @param props The props that will be provided by the Workflow runtime.
52
+ */
53
+ function PanovideoPlayer(props: PanovideoPlayerProps): React.ReactElement {
54
+ const { setValue, value } = props;
55
+
56
+ const containerRef = React.useRef<HTMLDivElement | null>(null);
57
+ const videoElRef = React.useRef<HTMLVideoElement | null>(null);
58
+ const viewerRef = React.useRef<any>(null);
59
+ const [isPlaying, setIsPlaying] = React.useState(false);
60
+ const [error, setError] = React.useState<string | null>(null);
61
+
62
+ // (Re)builds the Marzipano viewer whenever the video URL (props.value) changes.
63
+ React.useEffect(() => {
64
+ if (!value || !containerRef.current) {
65
+ return undefined;
66
+ }
67
+
68
+ setError(null);
69
+
70
+ // Create a hidden video element to drive the panorama. We don't
71
+ // attach it to the DOM directly - Marzipano reads frames from it
72
+ // and draws them into its own WebGL canvas.
73
+ const videoEl = document.createElement("video");
74
+ videoEl.crossOrigin = "anonymous";
75
+ videoEl.loop = true;
76
+ videoEl.muted = true; // required for autoplay in most browsers
77
+ videoEl.playsInline = true;
78
+ videoEl.src = value;
79
+ videoElRef.current = videoEl;
80
+
81
+ let viewer: any;
82
+ let cancelled = false;
83
+
84
+ const onLoadedMetadata = () => {
85
+ if (cancelled || !containerRef.current) {
86
+ return;
87
+ }
88
+
89
+ try {
90
+ viewer = new (Marzipano as any).Viewer(containerRef.current);
91
+ viewerRef.current = viewer;
92
+
93
+ const asset = new VideoAsset(videoEl);
94
+ const source = (Marzipano as any).SingleAssetSource.fromAsset(asset);
95
+
96
+ const geometry = new (Marzipano as any).EquirectGeometry([
97
+ { width: videoEl.videoWidth || 1920 },
98
+ ]);
99
+
100
+ const limiter = (Marzipano as any).RectilinearView.limit.traditional(
101
+ 1024,
102
+ (100 * Math.PI) / 180
103
+ );
104
+ const view = new (Marzipano as any).RectilinearView(
105
+ { yaw: 0, pitch: 0, fov: Math.PI / 2 },
106
+ limiter
107
+ );
108
+
109
+ const scene = viewer.createScene({
110
+ source,
111
+ geometry,
112
+ view,
113
+ pinFirstLevel: true,
114
+ });
115
+
116
+ scene.switchTo();
117
+
118
+ videoEl
119
+ .play()
120
+ .then(() => setIsPlaying(true))
121
+ .catch(() => {
122
+ // Autoplay was blocked - user needs to tap play.
123
+ setIsPlaying(false);
124
+ });
125
+ } catch (e) {
126
+ setError(
127
+ e instanceof Error ? e.message : "Failed to initialize panoramic video."
128
+ );
129
+ }
130
+ };
131
+
132
+ const onVideoError = () => {
133
+ if (!cancelled) {
134
+ setError("Unable to load video from the provided URL.");
135
+ }
136
+ };
137
+
138
+ videoEl.addEventListener("loadedmetadata", onLoadedMetadata);
139
+ videoEl.addEventListener("error", onVideoError);
140
+
141
+ return () => {
142
+ cancelled = true;
143
+ videoEl.removeEventListener("loadedmetadata", onLoadedMetadata);
144
+ videoEl.removeEventListener("error", onVideoError);
145
+ videoEl.pause();
146
+ videoEl.removeAttribute("src");
147
+ videoEl.load();
148
+
149
+ if (viewerRef.current) {
150
+ try {
151
+ // Not all Marzipano versions expose destroy(); guard defensively.
152
+ viewerRef.current.destroy?.();
153
+ } catch {
154
+ // no-op
155
+ }
156
+ viewerRef.current = null;
157
+ }
158
+
159
+ if (containerRef.current) {
160
+ containerRef.current.innerHTML = "";
161
+ }
162
+ };
163
+ }, [value]);
164
+
165
+ const togglePlayback = () => {
166
+ const videoEl = videoElRef.current;
167
+ if (!videoEl) {
168
+ return;
169
+ }
170
+ if (videoEl.paused) {
171
+ videoEl.play().then(() => setIsPlaying(true));
172
+ } else {
173
+ videoEl.pause();
174
+ setIsPlaying(false);
175
+ }
176
+ };
177
+
178
+ return (
179
+ <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
180
+ <input
181
+ type="text"
182
+ placeholder="Enter 360° equirectangular video URL"
183
+ onChange={(event) => setValue(event.currentTarget.value)}
184
+ value={value ?? ""}
185
+ style={{ width: "100%" }}
186
+ />
187
+
188
+ {error && (
189
+ <div style={{ color: "red", fontSize: 12 }}>{error}</div>
190
+ )}
191
+
192
+ {value && (
193
+ <div style={{ position: "relative" }}>
194
+ <div
195
+ ref={containerRef}
196
+ style={{
197
+ width: "100%",
198
+ height: 400,
199
+ background: "#000",
200
+ }}
201
+ />
202
+ <button
203
+ type="button"
204
+ onClick={togglePlayback}
205
+ style={{
206
+ position: "absolute",
207
+ bottom: 8,
208
+ left: 8,
209
+ }}
210
+ >
211
+ {isPlaying ? "Pause" : "Play"}
212
+ </button>
213
+ </div>
214
+ )}
215
+ </div>
216
+ );
217
+ }
218
+
219
+ const PanovideoPlayerElementRegistration: FormElementRegistration<PanovideoPlayerProps> = {
220
+ component: PanovideoPlayer,
221
+ getInitialProperties: () => ({ value: "" }),
222
+ id: "PanovideoPlayer",
223
+ };
224
+
225
+ export default PanovideoPlayerElementRegistration;
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { FormElementProps, FormElementRegistration } from "@vertigis/workflow";
3
3
  import { Timeline as MainTimeLine, Text } from '@mantine/core';
4
4
  import { MantineProvider } from '@mantine/core';
5
-
5
+ import "../styles/mantine-scoped.css";
6
6
 
7
7
  /**
8
8
  * The generic type argument provided to `FormElementProps<T>` controls the type
@@ -38,30 +38,33 @@ interface TimelineProps extends FormElementProps<string> {
38
38
  * @param props The props that will be provided by the Workflow runtime.
39
39
  */
40
40
  function Timeline(props: TimelineProps): React.ReactElement {
41
- const { itemDetails,iconSize,lineWidth,active,color,reverseActive } = props;
41
+ const { itemDetails, iconSize, lineWidth, active, color, reverseActive } = props;
42
42
  iconSize * 0.6
43
43
  return (
44
- <MantineProvider>
45
- <MainTimeLine active={active} bulletSize={iconSize} lineWidth={lineWidth} color={color} reverseActive={reverseActive}>
44
+ <div className="vertigis-mantine-scope">
45
+ <MantineProvider>
46
+ <MainTimeLine active={active} bulletSize={iconSize} lineWidth={lineWidth} color={color} reverseActive={reverseActive}>
47
+
48
+ {itemDetails.map((item, index) => {
49
+
50
+ return (
51
+
52
+ <MainTimeLine.Item
53
+ key={index}
54
+ title={item.title}
55
+ lineVariant={item.lineVariant}
56
+ >
57
+
58
+ {item.description ? <Text c="dimmed" size="sm">{item.description}</Text> : undefined}
59
+ {item.time ? <Text size="xs" mt={4}>{item.time}</Text> : undefined}
46
60
 
47
- {itemDetails.map((item, index) => {
48
-
49
- return (
50
-
51
- <MainTimeLine.Item
52
- key={index}
53
- title={item.title}
54
- lineVariant={item.lineVariant}
55
- >
56
-
57
- {item.description ? <Text c="dimmed" size="sm">{item.description}</Text> : undefined}
58
- {item.time ? <Text size="xs" mt={4}>{item.time}</Text> : undefined}
59
-
60
- </MainTimeLine.Item>
61
- )})}
62
- </MainTimeLine>
61
+ </MainTimeLine.Item>
62
+ )
63
+ })}
64
+ </MainTimeLine>
63
65
 
64
- </MantineProvider>
66
+ </MantineProvider>
67
+ </div>
65
68
  );
66
69
  }
67
70
 
@@ -72,7 +75,7 @@ const TimelineElementRegistration: FormElementRegistration<TimelineProps> = {
72
75
  lineWidth: 1,
73
76
  iconSize: 40,
74
77
  active: 2,
75
- color:'var(--buttonIcon)',
78
+ color: 'var(--buttonIcon)',
76
79
  reverseActive: true,
77
80
  itemDetails: [
78
81
  {
@@ -114,6 +114,16 @@ const StyledButton = styled('button')(
114
114
  `,
115
115
  )
116
116
 
117
+ const StyledIncrementButton = styled(StyledButton)({
118
+ gridColumn: 2,
119
+ gridRow: 1,
120
+ });
121
+
122
+ const StyledDecrementButton = styled(StyledButton)({
123
+ gridColumn: 2,
124
+ gridRow: 2,
125
+ });
126
+
117
127
 
118
128
 
119
129
 
@@ -151,8 +161,8 @@ const CustomNumberInput = React.forwardRef(function CustomNumberInput(
151
161
  slots={{
152
162
  root: StyledInputRoot,
153
163
  input: StyledInputElement,
154
- incrementButton: StyledButton,
155
- decrementButton: StyledButton,
164
+ incrementButton: StyledIncrementButton,
165
+ decrementButton: StyledDecrementButton,
156
166
  }}
157
167
  slotProps={{
158
168
  incrementButton: {
package/src/index.ts CHANGED
@@ -18,6 +18,7 @@ export { default as HTMLextractorActivity } from "./activities/HTMLextractor";
18
18
  export { default as AttributeFilterElementRegistration } from "./elements/AttributeFilter"
19
19
  export { default as ItemSearcher_V2DEVRegistration } from "./elements/ItemSearcher_v2";
20
20
  export { default as Viewer360Registration } from "./elements/Viewer360";
21
+ export { default as PanovideoPlayerRegistration} from "./elements/PanovideoPlayer";
21
22
  export { default as TableRadioGroupElementRegistration } from "./elements/TableRadioGoup";
22
23
  export { MuiSingleToggleButtonGroupElementRegistration, MuiMultipleToggleButtonGroupElementRegistration } from "./elements/ToggleButtonGroup";
23
24
 
@@ -40,3 +41,6 @@ export { default as DrapGeometryActivity } from "./activities/DrapGeometry";
40
41
  export { default as SampleActivity } from "./activities/Sample";
41
42
  export { default as SampleInputRegistration } from "./elements/SampleInput";
42
43
 
44
+
45
+
46
+ export { default as SimplifyGeometryActivity } from "./activities/SimplifyGeometry";
@@ -0,0 +1,3 @@
1
+ .vertigis-mantine-scope {
2
+ @import "@mantine/core/styles.css";
3
+ }