kitchen-simulator 1.1.1-test.7 → 1.1.1-test.71
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/es/KitchenConfigurator.js +34 -54
- package/es/KitchenConfiguratorApp.js +63 -81
- package/es/actions/holes-actions.js +1 -1
- package/es/actions/items-actions.js +1 -1
- package/es/actions/lines-actions.js +1 -1
- package/es/actions/project-actions.js +1 -1
- package/es/actions/scene-actions.js +1 -1
- package/es/actions/vertices-actions.js +1 -1
- package/es/actions/viewer2d-actions.js +1 -1
- package/es/actions/viewer3d-actions.js +1 -1
- package/es/catalog/areas/area/planner-element.js +10 -7
- package/es/catalog/catalog.js +3 -12
- package/es/catalog/factories/area-factory.js +1 -4
- package/es/catalog/factories/wall-factory-3d.js +1 -1
- package/es/catalog/holes/export.js +13 -13
- package/es/catalog/lines/wall/planner-element.js +13 -10
- package/es/catalog/properties/property-checkbox.js +64 -22
- package/es/catalog/properties/property-enum.js +52 -15
- package/es/catalog/properties/property-lenght-measure.js +4 -5
- package/es/catalog/properties/property-length-measure.js +55 -12
- package/es/catalog/properties/property-length-measure_hole.js +4 -5
- package/es/catalog/utils/FuseUtils.js +3 -6
- package/es/catalog/utils/exporter.js +2 -5
- package/es/catalog/utils/item-loader.js +4 -11
- package/es/catalog/utils/mtl-loader.js +3 -2
- package/es/catalog/utils/obj-loader.js +3 -2
- package/es/class/FuseUtils.js +3 -6
- package/es/class/area.js +4 -8
- package/es/class/group.js +6 -15
- package/es/class/guide.js +2 -6
- package/es/class/hole.js +7 -12
- package/es/class/item.js +12 -23
- package/es/class/layer.js +4 -8
- package/es/class/line.js +3 -12
- package/es/class/project.js +7 -11
- package/es/class/vertex.js +3 -7
- package/es/components/content.js +1 -0
- package/es/components/disclaimer/disclaimer.js +66 -86
- package/es/components/style/button.js +7 -14
- package/es/components/style/cancel-button.js +2 -3
- package/es/components/style/content-container.js +1 -4
- package/es/components/style/content-title.js +3 -7
- package/es/components/style/delete-button.js +2 -3
- package/es/components/style/form-block.js +3 -7
- package/es/components/style/form-color-input.js +2 -3
- package/es/components/style/form-label.js +3 -7
- package/es/components/style/form-number-input.js +36 -18
- package/es/components/style/form-number-input_2.js +6 -12
- package/es/components/style/form-select.js +50 -11
- package/es/components/style/form-slider.js +24 -9
- package/es/components/style/form-submit-button.js +2 -3
- package/es/components/style/form-text-input.js +38 -26
- package/es/components/viewer2d/area.js +4 -4
- package/es/components/viewer2d/grids/grid-horizontal-streak.js +0 -1
- package/es/components/viewer2d/grids/grid-streak.js +0 -1
- package/es/components/viewer2d/grids/grid-vertical-streak.js +0 -1
- package/es/components/viewer2d/grids/grids.js +1 -6
- package/es/components/viewer2d/item.js +4 -11
- package/es/components/viewer2d/line.js +2 -5
- package/es/components/viewer2d/ruler.js +2 -3
- package/es/components/viewer2d/rulerDist.js +1 -1
- package/es/components/viewer2d/rulerX.js +6 -12
- package/es/components/viewer2d/rulerY.js +6 -12
- package/es/components/viewer2d/scene.js +15 -27
- package/es/components/viewer2d/state.js +1 -6
- package/es/components/viewer2d/utils.js +33 -2
- package/es/components/viewer2d/viewer2d.js +13 -18
- package/es/components/viewer3d/camera-controls-module/camera-controls.module.js +6 -13
- package/es/components/viewer3d/front3D.js +1 -6
- package/es/components/viewer3d/libs/mtl-loader.js +2 -2
- package/es/components/viewer3d/libs/obj-loader.js +2 -2
- package/es/components/viewer3d/libs/orbit-controls.js +6 -5
- package/es/components/viewer3d/libs/pointer-lock-controls.js +5 -4
- package/es/components/viewer3d/ruler-utils/itemRect.js +1 -1
- package/es/components/viewer3d/ruler-utils/layer3D.js +2 -2
- package/es/components/viewer3d/ruler-utils/ruler3D.js +1 -4
- package/es/components/viewer3d/ruler-utils/scene3D.js +2 -3
- package/es/components/viewer3d/scene-creator.js +5 -11
- package/es/components/viewer3d/viewer3d-first-person.js +5 -11
- package/es/components/viewer3d/viewer3d.js +19 -26
- package/es/index.js +13 -14
- package/es/models.js +10 -15
- package/es/plugins/console-debugger.js +1 -4
- package/es/plugins/keyboard.js +2 -2
- package/es/reducers/holes-reducer.js +1 -1
- package/es/reducers/items-reducer.js +2 -5
- package/es/reducers/lines-reducer.js +1 -1
- package/es/reducers/project-reducer.js +1 -1
- package/es/reducers/reducer.js +2 -2
- package/es/reducers/scene-reducer.js +1 -1
- package/es/reducers/user-reducer.js +1 -2
- package/es/reducers/vertices-reducer.js +1 -1
- package/es/reducers/viewer2d-reducer.js +2 -2
- package/es/reducers/viewer3d-reducer.js +2 -2
- package/es/translator/translator.js +2 -6
- package/es/utils/convert-units-lite.js +29 -0
- package/es/utils/geometry.js +7 -16
- package/es/utils/get-edges-of-subgraphs.js +2 -1
- package/es/utils/graph-cycles.js +2 -3
- package/es/utils/graph.js +4 -7
- package/es/utils/helper.js +3 -73
- package/es/utils/id-broker.js +4 -8
- package/es/utils/molding.js +36 -42
- package/es/utils/name-generator.js +2 -6
- package/es/utils/objects-utils.js +1 -1
- package/es/utils/process-black-list.js +1 -4
- package/es/utils/snap-scene.js +1 -6
- package/es/utils/snap.js +6 -12
- package/es/utils/threeCSG.es6.js +2 -6
- package/lib/@history.js +3 -2
- package/lib/AppContext.js +3 -2
- package/lib/KitchenConfigurator.js +70 -88
- package/lib/KitchenConfiguratorApp.js +98 -113
- package/lib/actions/export.js +1 -1
- package/lib/catalog/areas/area/planner-element.js +13 -8
- package/lib/catalog/catalog.js +9 -16
- package/lib/catalog/factories/area-factory-3d.js +1 -1
- package/lib/catalog/factories/area-factory.js +6 -7
- package/lib/catalog/factories/export.js +1 -1
- package/lib/catalog/factories/wall-factory-3d.js +4 -4
- package/lib/catalog/factories/wall-factory.js +4 -3
- package/lib/catalog/holes/door-closet/planner-element.js +4 -3
- package/lib/catalog/holes/door-double/planner-element.js +4 -3
- package/lib/catalog/holes/door-exterior/planner-element.js +4 -3
- package/lib/catalog/holes/door-interior/planner-element.js +4 -3
- package/lib/catalog/holes/door-panic/planner-element.js +4 -3
- package/lib/catalog/holes/door-panic-double/planner-element.js +4 -3
- package/lib/catalog/holes/door-sliding/planner-element.js +4 -3
- package/lib/catalog/holes/doorway-framed/planner-element.js +4 -3
- package/lib/catalog/holes/doorway-frameless/planner-element.js +4 -3
- package/lib/catalog/holes/export.js +14 -14
- package/lib/catalog/holes/window-clear/planner-element.js +4 -3
- package/lib/catalog/holes/window-cross/planner-element.js +4 -3
- package/lib/catalog/holes/window-double-hung/planner-element.js +4 -3
- package/lib/catalog/holes/window-vertical/planner-element.js +4 -3
- package/lib/catalog/lines/wall/planner-element.js +16 -11
- package/lib/catalog/molding/molding-dcm/planner-element.js +4 -3
- package/lib/catalog/molding/molding-fbm/planner-element.js +4 -3
- package/lib/catalog/molding/molding-lrm/planner-element.js +4 -3
- package/lib/catalog/properties/export.js +1 -1
- package/lib/catalog/properties/property-checkbox.js +68 -25
- package/lib/catalog/properties/property-color.js +3 -2
- package/lib/catalog/properties/property-enum.js +54 -16
- package/lib/catalog/properties/property-hidden.js +3 -2
- package/lib/catalog/properties/property-lenght-measure.js +10 -10
- package/lib/catalog/properties/property-length-measure.js +61 -17
- package/lib/catalog/properties/property-length-measure_hole.js +10 -10
- package/lib/catalog/properties/property-number.js +3 -2
- package/lib/catalog/properties/property-read-only.js +3 -2
- package/lib/catalog/properties/property-string.js +3 -2
- package/lib/catalog/properties/property-toggle.js +3 -2
- package/lib/catalog/properties/shared-property-style.js +2 -1
- package/lib/catalog/utils/FuseUtils.js +10 -11
- package/lib/catalog/utils/exporter.js +10 -12
- package/lib/catalog/utils/geom-utils.js +1 -1
- package/lib/catalog/utils/item-loader.js +29 -35
- package/lib/catalog/utils/mtl-loader.js +7 -3
- package/lib/catalog/utils/obj-loader.js +7 -3
- package/lib/class/FuseUtils.js +10 -11
- package/lib/class/area.js +9 -11
- package/lib/class/export.js +1 -1
- package/lib/class/group.js +13 -20
- package/lib/class/guide.js +9 -12
- package/lib/class/hole.js +7 -9
- package/lib/class/item.js +25 -35
- package/lib/class/layer.js +7 -9
- package/lib/class/line.js +14 -20
- package/lib/class/project.js +10 -11
- package/lib/class/vertex.js +9 -11
- package/lib/components/content.js +5 -3
- package/lib/components/disclaimer/disclaimer.js +69 -88
- package/lib/components/export.js +1 -1
- package/lib/components/style/button.js +17 -22
- package/lib/components/style/cancel-button.js +7 -7
- package/lib/components/style/content-container.js +5 -7
- package/lib/components/style/content-title.js +10 -12
- package/lib/components/style/delete-button.js +8 -8
- package/lib/components/style/export.js +1 -1
- package/lib/components/style/form-block.js +9 -12
- package/lib/components/style/form-color-input.js +7 -7
- package/lib/components/style/form-label.js +9 -12
- package/lib/components/style/form-number-input.js +43 -23
- package/lib/components/style/form-number-input_2.js +15 -19
- package/lib/components/style/form-select.js +53 -15
- package/lib/components/style/form-slider.js +28 -12
- package/lib/components/style/form-submit-button.js +8 -8
- package/lib/components/style/form-text-input.js +46 -32
- package/lib/components/viewer2d/area.js +8 -7
- package/lib/components/viewer2d/export.js +1 -1
- package/lib/components/viewer2d/grids/grid-horizontal-streak.js +3 -3
- package/lib/components/viewer2d/grids/grid-streak.js +3 -3
- package/lib/components/viewer2d/grids/grid-vertical-streak.js +3 -3
- package/lib/components/viewer2d/grids/grids.js +6 -10
- package/lib/components/viewer2d/group.js +4 -3
- package/lib/components/viewer2d/item.js +14 -19
- package/lib/components/viewer2d/layer.js +3 -2
- package/lib/components/viewer2d/line.js +4 -7
- package/lib/components/viewer2d/ruler.js +9 -9
- package/lib/components/viewer2d/rulerDist.js +7 -6
- package/lib/components/viewer2d/rulerX.js +15 -19
- package/lib/components/viewer2d/rulerY.js +15 -19
- package/lib/components/viewer2d/scene.js +24 -34
- package/lib/components/viewer2d/snap.js +4 -3
- package/lib/components/viewer2d/state.js +7 -11
- package/lib/components/viewer2d/utils.js +35 -2
- package/lib/components/viewer2d/vertex.js +4 -3
- package/lib/components/viewer2d/viewer2d.js +40 -41
- package/lib/components/viewer3d/camera-controls-module/camera-controls.module.js +14 -20
- package/lib/components/viewer3d/dcm.js +2 -1
- package/lib/components/viewer3d/fbm.js +2 -1
- package/lib/components/viewer3d/front3D.js +6 -10
- package/lib/components/viewer3d/grid-creator.js +4 -3
- package/lib/components/viewer3d/grids/grid-horizontal-streak.js +3 -2
- package/lib/components/viewer3d/grids/grid-streak.js +3 -2
- package/lib/components/viewer3d/grids/grid-vertical-streak.js +3 -2
- package/lib/components/viewer3d/libs/mtl-loader.js +7 -2
- package/lib/components/viewer3d/libs/obj-loader.js +7 -2
- package/lib/components/viewer3d/libs/orbit-controls.js +10 -5
- package/lib/components/viewer3d/libs/pointer-lock-controls.js +9 -4
- package/lib/components/viewer3d/lrm.js +2 -1
- package/lib/components/viewer3d/pointer-lock-navigation.js +1 -1
- package/lib/components/viewer3d/ruler-utils/itemRect.js +10 -9
- package/lib/components/viewer3d/ruler-utils/layer3D.js +35 -34
- package/lib/components/viewer3d/ruler-utils/ruler3D.js +5 -7
- package/lib/components/viewer3d/ruler-utils/scene3D.js +4 -5
- package/lib/components/viewer3d/ruler-utils/state3D.js +3 -2
- package/lib/components/viewer3d/scene-creator.js +40 -45
- package/lib/components/viewer3d/three-memory-cleaner.js +1 -1
- package/lib/components/viewer3d/viewer3d-first-person.js +13 -17
- package/lib/components/viewer3d/viewer3d.js +34 -38
- package/lib/index.js +16 -88
- package/lib/models.js +58 -63
- package/lib/plugins/autosave.js +2 -1
- package/lib/plugins/console-debugger.js +5 -7
- package/lib/plugins/export.js +1 -1
- package/lib/plugins/keyboard.js +2 -1
- package/lib/reducers/areas-reducer.js +2 -1
- package/lib/reducers/export.js +1 -1
- package/lib/reducers/groups-reducer.js +2 -1
- package/lib/reducers/holes-reducer.js +2 -1
- package/lib/reducers/items-reducer.js +2 -1
- package/lib/reducers/lines-reducer.js +2 -1
- package/lib/reducers/project-reducer.js +2 -1
- package/lib/reducers/scene-reducer.js +2 -1
- package/lib/reducers/user-reducer.js +2 -2
- package/lib/reducers/vertices-reducer.js +2 -1
- package/lib/reducers/viewer2d-reducer.js +5 -5
- package/lib/reducers/viewer3d-reducer.js +5 -5
- package/lib/styles/export.js +1 -1
- package/lib/translator/en.js +2 -1
- package/lib/translator/it.js +2 -1
- package/lib/translator/ru.js +2 -1
- package/lib/translator/translator.js +7 -10
- package/lib/utils/convert-units-lite.js +35 -0
- package/lib/utils/export.js +2 -2
- package/lib/utils/geometry.js +20 -28
- package/lib/utils/get-edges-of-subgraphs.js +7 -1
- package/lib/utils/graph-cycles.js +9 -9
- package/lib/utils/graph-inner-cycles.js +1 -1
- package/lib/utils/graph.js +15 -12
- package/lib/utils/helper.js +14 -83
- package/lib/utils/history.js +1 -1
- package/lib/utils/id-broker.js +7 -10
- package/lib/utils/molding.js +66 -71
- package/lib/utils/name-generator.js +7 -9
- package/lib/utils/objects-utils.js +5 -3
- package/lib/utils/process-black-list.js +3 -5
- package/lib/utils/react-if.js +3 -2
- package/lib/utils/snap-scene.js +3 -7
- package/lib/utils/snap.js +22 -26
- package/lib/utils/threeCSG.es6.js +16 -15
- package/package.json +26 -54
- package/es/analytics/ga4.js +0 -191
- package/es/analytics/posthog.js +0 -60
- package/lib/analytics/ga4.js +0 -197
- package/lib/analytics/posthog.js +0 -68
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
3
5
|
Object.defineProperty(exports, "__esModule", {
|
|
4
6
|
value: true
|
|
5
7
|
});
|
|
6
8
|
exports["default"] = void 0;
|
|
9
|
+
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
10
|
+
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
7
11
|
var THREE = _interopRequireWildcard(require("three"));
|
|
8
12
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
|
|
12
|
-
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
|
|
13
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
14
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /*jshint esversion: 6 */
|
|
13
|
+
/*jshint esversion: 6 */
|
|
14
|
+
|
|
15
15
|
var EPSILON = 1e-5,
|
|
16
16
|
COPLANAR = 0,
|
|
17
17
|
FRONT = 1,
|
|
@@ -19,7 +19,7 @@ var EPSILON = 1e-5,
|
|
|
19
19
|
SPANNING = 3;
|
|
20
20
|
var ThreeBSP = exports["default"] = /*#__PURE__*/function () {
|
|
21
21
|
function ThreeBSP(geometry) {
|
|
22
|
-
|
|
22
|
+
(0, _classCallCheck2["default"])(this, ThreeBSP);
|
|
23
23
|
// Convert THREE.Geometry to ThreeBSP
|
|
24
24
|
var i,
|
|
25
25
|
_length_i,
|
|
@@ -68,7 +68,7 @@ var ThreeBSP = exports["default"] = /*#__PURE__*/function () {
|
|
|
68
68
|
}
|
|
69
69
|
this.tree = new Node(polygons);
|
|
70
70
|
}
|
|
71
|
-
return
|
|
71
|
+
return (0, _createClass2["default"])(ThreeBSP, [{
|
|
72
72
|
key: "subtract",
|
|
73
73
|
value: function subtract(other_tree) {
|
|
74
74
|
var a = this.tree.clone(),
|
|
@@ -165,7 +165,7 @@ var ThreeBSP = exports["default"] = /*#__PURE__*/function () {
|
|
|
165
165
|
}();
|
|
166
166
|
var Polygon = /*#__PURE__*/function () {
|
|
167
167
|
function Polygon(vertices, normal, w) {
|
|
168
|
-
|
|
168
|
+
(0, _classCallCheck2["default"])(this, Polygon);
|
|
169
169
|
if (!(vertices instanceof Array)) {
|
|
170
170
|
vertices = [];
|
|
171
171
|
}
|
|
@@ -176,7 +176,7 @@ var Polygon = /*#__PURE__*/function () {
|
|
|
176
176
|
this.normal = this.w = undefined;
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
|
-
return
|
|
179
|
+
return (0, _createClass2["default"])(Polygon, [{
|
|
180
180
|
key: "calculateProperties",
|
|
181
181
|
value: function calculateProperties() {
|
|
182
182
|
var a = this.vertices[0],
|
|
@@ -296,14 +296,14 @@ var Polygon = /*#__PURE__*/function () {
|
|
|
296
296
|
}();
|
|
297
297
|
var Vertex = /*#__PURE__*/function () {
|
|
298
298
|
function Vertex(x, y, z, normal, uv) {
|
|
299
|
-
|
|
299
|
+
(0, _classCallCheck2["default"])(this, Vertex);
|
|
300
300
|
this.x = x;
|
|
301
301
|
this.y = y;
|
|
302
302
|
this.z = z;
|
|
303
303
|
this.normal = normal || new THREE.Vector3();
|
|
304
304
|
this.uv = uv || new THREE.Vector2();
|
|
305
305
|
}
|
|
306
|
-
return
|
|
306
|
+
return (0, _createClass2["default"])(Vertex, [{
|
|
307
307
|
key: "clone",
|
|
308
308
|
value: function clone() {
|
|
309
309
|
return new Vertex(this.x, this.y, this.z, this.normal.clone(), this.uv.clone());
|
|
@@ -388,7 +388,7 @@ var Vertex = /*#__PURE__*/function () {
|
|
|
388
388
|
}();
|
|
389
389
|
var Node = /*#__PURE__*/function () {
|
|
390
390
|
function Node(polygons) {
|
|
391
|
-
|
|
391
|
+
(0, _classCallCheck2["default"])(this, Node);
|
|
392
392
|
var i,
|
|
393
393
|
polygon_count,
|
|
394
394
|
front = [],
|
|
@@ -407,7 +407,7 @@ var Node = /*#__PURE__*/function () {
|
|
|
407
407
|
this.back = new Node(back);
|
|
408
408
|
}
|
|
409
409
|
}
|
|
410
|
-
return
|
|
410
|
+
return (0, _createClass2["default"])(Node, [{
|
|
411
411
|
key: "isConvex",
|
|
412
412
|
value: function isConvex(polygons) {
|
|
413
413
|
var i, j;
|
|
@@ -500,4 +500,5 @@ var Node = /*#__PURE__*/function () {
|
|
|
500
500
|
}
|
|
501
501
|
}]);
|
|
502
502
|
}();
|
|
503
|
-
window.ThreeBSP = ThreeBSP;
|
|
503
|
+
window.ThreeBSP = ThreeBSP;
|
|
504
|
+
module.exports = exports.default;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kitchen-simulator",
|
|
3
|
-
"version": "1.1.1-test.
|
|
4
|
-
"description": "It is a kitchen simulator.",
|
|
3
|
+
"version": "1.1.1-test.71",
|
|
4
|
+
"description": "It is a kitchen simulator (self-contained micro-frontend).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"module": "es/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"clean": "rimraf lib es",
|
|
32
32
|
"update-version-file": "const-version ./package.json ./src/version.js",
|
|
33
33
|
"version": "npm run update-version-file && npm run build",
|
|
34
|
-
"prepublishOnly": "npm run build",
|
|
34
|
+
"prepublishOnly": "cross-env NODE_ENV=production npm run build",
|
|
35
35
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
36
36
|
},
|
|
37
37
|
"repository": {
|
|
@@ -57,84 +57,56 @@
|
|
|
57
57
|
"component",
|
|
58
58
|
"redux"
|
|
59
59
|
],
|
|
60
|
-
"peerDependencies": {
|
|
61
|
-
"react": ">=16.9 <19",
|
|
62
|
-
"react-dom": ">=16.9 <19"
|
|
63
|
-
},
|
|
64
60
|
"dependencies": {
|
|
65
|
-
"@
|
|
66
|
-
"@material-ui/core": "^4.12.3",
|
|
67
|
-
"@material-ui/icons": "^4.11.2",
|
|
68
|
-
"@material-ui/lab": "^4.0.0-alpha.61",
|
|
61
|
+
"@babel/runtime": "^7.28.4",
|
|
69
62
|
"@sentry/react": "^9.10.1",
|
|
70
|
-
"antd": "^4.24.16",
|
|
71
|
-
"area-polygon": "1.0.1",
|
|
72
|
-
"assert": "^2.1.0",
|
|
73
|
-
"aws-sdk": "^2.984.0",
|
|
74
63
|
"axios": "^0.20.0",
|
|
75
64
|
"browserify-zlib": "^0.2.0",
|
|
76
|
-
"buffer": "^6.0.3",
|
|
77
65
|
"camera-controls": "^2.8.5",
|
|
78
|
-
"convert-units": "2.3.4",
|
|
79
66
|
"dotenv": "^16.4.7",
|
|
80
67
|
"history": "4.10.1",
|
|
68
|
+
"hoist-non-react-statics": "2.5.5",
|
|
81
69
|
"immutable": "3.8.2",
|
|
82
70
|
"immutablediff": "0.4.4",
|
|
83
71
|
"immutablepatch": "0.5.0",
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"lodash": "^4.17.21",
|
|
88
|
-
"material-ui": "^0.20.2",
|
|
89
|
-
"mobile-detect": "^1.4.5",
|
|
72
|
+
"invariant": "^2.0.0",
|
|
73
|
+
"localstorage-slim": "^1.3.0",
|
|
74
|
+
"nanoid": "^5.1.6",
|
|
90
75
|
"path-browserify": "^1.0.1",
|
|
91
76
|
"polylabel": "1.0.2",
|
|
92
77
|
"posthog-js": "^1.271.0",
|
|
93
|
-
"prop-types": "15.
|
|
94
|
-
"react
|
|
95
|
-
"react-
|
|
96
|
-
"react-
|
|
78
|
+
"prop-types": "^15.8.1",
|
|
79
|
+
"react": "^16.9.0",
|
|
80
|
+
"react-container-dimensions": "1.4.1",
|
|
81
|
+
"react-dom": "16.9.0",
|
|
97
82
|
"react-icons": "3.5.0",
|
|
98
|
-
"react-player": "2.8.0",
|
|
99
|
-
"react-query": "^3.39.3",
|
|
100
83
|
"react-redux": "5.0.7",
|
|
101
|
-
"react-
|
|
102
|
-
"react-svg-pan-zoom": "2.18.0",
|
|
103
|
-
"react-tabs": "3.0.0",
|
|
104
|
-
"reactjs-popup": "^2.0.4",
|
|
84
|
+
"react-svg-pan-zoom": "^3.13.1",
|
|
105
85
|
"redux": "4.0.1",
|
|
106
|
-
"redux-thunk": "2.3.0",
|
|
107
|
-
"shortid": "2.2.14",
|
|
108
86
|
"stream-browserify": "^3.0.0",
|
|
109
|
-
"
|
|
110
|
-
"velocity-react": "1.4.3"
|
|
87
|
+
"three": "0.166.0"
|
|
111
88
|
},
|
|
112
89
|
"devDependencies": {
|
|
113
|
-
"@babel/cli": "^7.
|
|
114
|
-
"@babel/core": "^7.
|
|
115
|
-
"@babel/
|
|
116
|
-
"@babel/
|
|
90
|
+
"@babel/cli": "^7.28.3",
|
|
91
|
+
"@babel/core": "^7.28.4",
|
|
92
|
+
"@babel/plugin-transform-modules-commonjs": "^7.27.1",
|
|
93
|
+
"@babel/plugin-transform-runtime": "^7.28.3",
|
|
94
|
+
"@babel/preset-env": "^7.28.3",
|
|
95
|
+
"@babel/preset-react": "^7.27.1",
|
|
117
96
|
"@sentry/webpack-plugin": "^3.2.4",
|
|
118
97
|
"babel-loader": "^9.1.3",
|
|
98
|
+
"babel-plugin-add-module-exports": "^1.0.4",
|
|
119
99
|
"babel-plugin-import-glob": "^2.0.0",
|
|
120
100
|
"babel-plugin-module-resolver": "^5.0.2",
|
|
121
101
|
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
|
102
|
+
"babel-plugin-transform-rename-import": "^2.3.0",
|
|
122
103
|
"const-version": "2.0.0",
|
|
123
|
-
"cross-env": "5.2.0",
|
|
124
|
-
"css-loader": "
|
|
104
|
+
"cross-env": "^5.2.0",
|
|
105
|
+
"css-loader": "*",
|
|
125
106
|
"file-loader": "6.2.0",
|
|
126
|
-
"gh-pages": "2.0.1",
|
|
127
107
|
"html-webpack-plugin": "5.6.0",
|
|
128
|
-
"
|
|
129
|
-
"
|
|
130
|
-
"react": "^16.9.0",
|
|
131
|
-
"react-container-dimensions": "1.4.1",
|
|
132
|
-
"react-dom": "16.9.0",
|
|
133
|
-
"rimraf": "2.6.3",
|
|
134
|
-
"sass": "^1.29.0",
|
|
135
|
-
"sass-loader": "^10.0.5",
|
|
136
|
-
"style-loader": "0.23.1",
|
|
137
|
-
"three": "0.166.0",
|
|
108
|
+
"rimraf": "^2.6.3",
|
|
109
|
+
"style-loader": "*",
|
|
138
110
|
"webpack": "5.92.1",
|
|
139
111
|
"webpack-cli": "5.1.4",
|
|
140
112
|
"webpack-dev-server": "5.0.4"
|
package/es/analytics/ga4.js
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
6
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
-
import ReactGA from 'react-ga4';
|
|
8
|
-
|
|
9
|
-
// ---------- Helpers ----------
|
|
10
|
-
function nowMs() {
|
|
11
|
-
return Date.now();
|
|
12
|
-
}
|
|
13
|
-
function getClientName() {
|
|
14
|
-
return sessionStorage.getItem('visualizerName');
|
|
15
|
-
}
|
|
16
|
-
function isDesktopUA() {
|
|
17
|
-
// Lightweight heuristic; GA4 also provides device.category. This flag can help ad-hoc filtering.
|
|
18
|
-
var ua = navigator.userAgent.toLowerCase();
|
|
19
|
-
var isMobile = /mobi|android|iphone|ipad|ipod|windows phone/.test(ua);
|
|
20
|
-
return !isMobile;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// ---------- Keys for storage ----------
|
|
24
|
-
var SSN_KEYS = {
|
|
25
|
-
sessionStartMs: 'ga4_session_start_ms',
|
|
26
|
-
introChoiceMs: 'ga4_intro_choice_ms',
|
|
27
|
-
firstCabinetPlaced: 'ga4_first_cabinet_placed',
|
|
28
|
-
contextBooted: 'ga4_context_booted',
|
|
29
|
-
enteredCanvasSent: 'ga4_entered_canvas_sent'
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// ---------- Core GA wrapper ----------
|
|
33
|
-
export var GA = {
|
|
34
|
-
init: function init(_ref) {
|
|
35
|
-
var measurementId = _ref.measurementId;
|
|
36
|
-
ReactGA.initialize([{
|
|
37
|
-
trackingId: measurementId
|
|
38
|
-
}], {
|
|
39
|
-
testMode: false
|
|
40
|
-
});
|
|
41
|
-
},
|
|
42
|
-
resetSessionKeys: function resetSessionKeys() {
|
|
43
|
-
Object.values(SSN_KEYS).forEach(function (key) {
|
|
44
|
-
sessionStorage.removeItem(key);
|
|
45
|
-
});
|
|
46
|
-
},
|
|
47
|
-
/**
|
|
48
|
-
* Must be called ONCE per page load, *before* other events.
|
|
49
|
-
* Sets user properties (project_entry, cross_auth) and sends an initial page_view with client_name.
|
|
50
|
-
*/
|
|
51
|
-
bootSessionContext: function bootSessionContext(_ref2) {
|
|
52
|
-
var projectEntry = _ref2.projectEntry,
|
|
53
|
-
crossAuth = _ref2.crossAuth;
|
|
54
|
-
try {
|
|
55
|
-
var resolvedClient = getClientName();
|
|
56
|
-
|
|
57
|
-
// Persist session start for timing metrics (if not already set for this tab)
|
|
58
|
-
if (!sessionStorage.getItem(SSN_KEYS.sessionStartMs)) {
|
|
59
|
-
sessionStorage.setItem(SSN_KEYS.sessionStartMs, String(nowMs()));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Mark context as booted to avoid duplicate property sets on hot reloads
|
|
63
|
-
if (!sessionStorage.getItem(SSN_KEYS.contextBooted)) {
|
|
64
|
-
sessionStorage.setItem(SSN_KEYS.contextBooted, '1');
|
|
65
|
-
|
|
66
|
-
// Set GA4 user_properties (user-scoped dimensions)
|
|
67
|
-
ReactGA.gtag('set', 'user_properties', {
|
|
68
|
-
project_entry: projectEntry,
|
|
69
|
-
// user scope dimension
|
|
70
|
-
cross_auth: crossAuth // user scope dimension (boolean serialized)
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Send first page_view hit enriched with event-scoped client_name
|
|
75
|
-
ReactGA.send({
|
|
76
|
-
hitType: 'pageview',
|
|
77
|
-
page: window.location.pathname + window.location.search,
|
|
78
|
-
// @ts-expect-error react-ga4 passes along additional params into gtag
|
|
79
|
-
client_name: resolvedClient
|
|
80
|
-
});
|
|
81
|
-
} catch (e) {
|
|
82
|
-
// eslint-disable-next-line no-console
|
|
83
|
-
console.warn('GA.bootSessionContext error', e);
|
|
84
|
-
}
|
|
85
|
-
},
|
|
86
|
-
// Utility to derive cross_auth from URL (token or details query params)
|
|
87
|
-
deriveCrossAuthFromUrl: function deriveCrossAuthFromUrl(search) {
|
|
88
|
-
var sp = new URLSearchParams(search);
|
|
89
|
-
return sp.has('token') || sp.has('details');
|
|
90
|
-
},
|
|
91
|
-
// Utility to derive project entry (best-effort). You can also pass explicitly from router logic.
|
|
92
|
-
deriveProjectEntry: function deriveProjectEntry() {
|
|
93
|
-
var projectId = sessionStorage.getItem('projectId');
|
|
94
|
-
|
|
95
|
-
// If a project id exists, consider it "open_existing"; otherwise fallback to "new"
|
|
96
|
-
if (projectId) return 'open_existing';
|
|
97
|
-
return 'new';
|
|
98
|
-
},
|
|
99
|
-
// ---------- Event API ----------
|
|
100
|
-
events: {
|
|
101
|
-
/**
|
|
102
|
-
* intro_choice(option) — records the user's entry choice.
|
|
103
|
-
* Also stores a timestamp for later time_to_canvas calculation.
|
|
104
|
-
*/
|
|
105
|
-
introChoice: function introChoice(option, extra) {
|
|
106
|
-
var client_name = getClientName();
|
|
107
|
-
sessionStorage.setItem(SSN_KEYS.introChoiceMs, String(nowMs()));
|
|
108
|
-
ReactGA.event('intro_choice', _objectSpread({
|
|
109
|
-
client_name: client_name,
|
|
110
|
-
option: option
|
|
111
|
-
}, extra || {}));
|
|
112
|
-
},
|
|
113
|
-
/**
|
|
114
|
-
* entered_canvas(time_to_canvas) — compute (now - intro_choice)
|
|
115
|
-
*/
|
|
116
|
-
enteredCanvas: function enteredCanvas() {
|
|
117
|
-
// fire only once per tab/session
|
|
118
|
-
if (sessionStorage.getItem(SSN_KEYS.enteredCanvasSent)) return;
|
|
119
|
-
var client_name = getClientName();
|
|
120
|
-
var introMs = Number(sessionStorage.getItem(SSN_KEYS.introChoiceMs) || 0);
|
|
121
|
-
var timeSec = introMs ? Math.max(0, Math.round((Date.now() - introMs) / 1000)) : undefined;
|
|
122
|
-
ReactGA.event('entered_canvas', _objectSpread({
|
|
123
|
-
client_name: client_name
|
|
124
|
-
}, typeof timeSec === 'number' ? {
|
|
125
|
-
time_to_canvas: timeSec
|
|
126
|
-
} : {}));
|
|
127
|
-
sessionStorage.setItem(SSN_KEYS.enteredCanvasSent, '1'); // 👈 lock it
|
|
128
|
-
},
|
|
129
|
-
/**
|
|
130
|
-
* cabinet_placed(time_to_first_cabinet) — send only for the *first* cabinet of the session.
|
|
131
|
-
*/
|
|
132
|
-
cabinetPlaced: function cabinetPlaced() {
|
|
133
|
-
var already = sessionStorage.getItem(SSN_KEYS.firstCabinetPlaced);
|
|
134
|
-
var client_name = getClientName();
|
|
135
|
-
var params = {
|
|
136
|
-
client_name: client_name
|
|
137
|
-
};
|
|
138
|
-
if (!already) {
|
|
139
|
-
var startMs = Number(sessionStorage.getItem(SSN_KEYS.sessionStartMs) || 0);
|
|
140
|
-
var timeSec = startMs ? Math.max(0, Math.round((nowMs() - startMs) / 1000)) : undefined;
|
|
141
|
-
if (typeof timeSec === 'number') params.time_to_first_cabinet = timeSec; // custom metric (seconds)
|
|
142
|
-
sessionStorage.setItem(SSN_KEYS.firstCabinetPlaced, '1');
|
|
143
|
-
}
|
|
144
|
-
ReactGA.event('cabinet_placed', params);
|
|
145
|
-
},
|
|
146
|
-
/**
|
|
147
|
-
* door_changed(door_id)
|
|
148
|
-
*/
|
|
149
|
-
doorChanged: function doorChanged(door_id) {
|
|
150
|
-
var client_name = getClientName();
|
|
151
|
-
ReactGA.event('door_changed', {
|
|
152
|
-
client_name: client_name,
|
|
153
|
-
door_id: door_id
|
|
154
|
-
});
|
|
155
|
-
},
|
|
156
|
-
/**
|
|
157
|
-
* project_saved(project_id, save_method) — mark as conversion in GA UI.
|
|
158
|
-
*/
|
|
159
|
-
projectSaved: function projectSaved(project_id, save_method) {
|
|
160
|
-
var client_name = getClientName();
|
|
161
|
-
ReactGA.event('project_saved', {
|
|
162
|
-
client_name: client_name,
|
|
163
|
-
project_id: project_id,
|
|
164
|
-
save_method: save_method
|
|
165
|
-
});
|
|
166
|
-
},
|
|
167
|
-
/**
|
|
168
|
-
* assistance_requested(method, project_id) — mark as conversion in GA UI.
|
|
169
|
-
*/
|
|
170
|
-
assistanceRequested: function assistanceRequested(method, project_id) {
|
|
171
|
-
var client_name = getClientName();
|
|
172
|
-
ReactGA.event('assistance_requested', {
|
|
173
|
-
client_name: client_name,
|
|
174
|
-
method: method,
|
|
175
|
-
project_id: project_id
|
|
176
|
-
});
|
|
177
|
-
},
|
|
178
|
-
/**
|
|
179
|
-
* add_to_cart(project_id, sku_count, price_total) — mark as conversion in GA UI.
|
|
180
|
-
*/
|
|
181
|
-
addToCart: function addToCart(project_id, sku_count, price_total) {
|
|
182
|
-
var client_name = getClientName();
|
|
183
|
-
ReactGA.event('add_to_cart', {
|
|
184
|
-
client_name: client_name,
|
|
185
|
-
project_id: project_id,
|
|
186
|
-
sku_count: sku_count,
|
|
187
|
-
price_total: price_total
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
};
|
package/es/analytics/posthog.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import posthog from 'posthog-js';
|
|
2
|
-
|
|
3
|
-
// ---- session context ----
|
|
4
|
-
export function bootSessionContext() {
|
|
5
|
-
var url = new URL(window.location.href);
|
|
6
|
-
var client_name = sessionStorage.getItem('visualizerName');
|
|
7
|
-
var project_entry = sessionStorage.getItem('projectId') ? 'open_existing' : 'new';
|
|
8
|
-
var cross_auth = url.searchParams.has('token') || url.searchParams.has('details');
|
|
9
|
-
|
|
10
|
-
// Persist context on the client/session
|
|
11
|
-
posthog.register({
|
|
12
|
-
client_name: client_name,
|
|
13
|
-
project_entry: project_entry,
|
|
14
|
-
cross_auth: cross_auth
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
// First-hit event for qualitative flow
|
|
18
|
-
posthog.capture('session_started', {
|
|
19
|
-
client_name: client_name,
|
|
20
|
-
project_entry: project_entry,
|
|
21
|
-
cross_auth: cross_auth
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Optional: expose session id for replay linkage
|
|
26
|
-
export function getSessionId() {
|
|
27
|
-
try {
|
|
28
|
-
return posthog.get_session_id();
|
|
29
|
-
} catch (_unused) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// ---- event wrappers (mirror GA4 conversions) ----
|
|
35
|
-
export var PH = {
|
|
36
|
-
projectSaved: function projectSaved(project_id) {
|
|
37
|
-
posthog.capture('project_saved', {
|
|
38
|
-
project_id: project_id,
|
|
39
|
-
client_name: sessionStorage.getItem('visualizerName'),
|
|
40
|
-
session_id: getSessionId()
|
|
41
|
-
});
|
|
42
|
-
},
|
|
43
|
-
assistanceRequested: function assistanceRequested(method, project_id) {
|
|
44
|
-
posthog.capture('assistance_requested', {
|
|
45
|
-
method: method,
|
|
46
|
-
project_id: project_id,
|
|
47
|
-
client_name: sessionStorage.getItem('visualizerName'),
|
|
48
|
-
session_id: getSessionId()
|
|
49
|
-
});
|
|
50
|
-
},
|
|
51
|
-
addToCart: function addToCart(project_id, sku_count, price_total) {
|
|
52
|
-
posthog.capture('add_to_cart', {
|
|
53
|
-
project_id: project_id,
|
|
54
|
-
sku_count: sku_count,
|
|
55
|
-
price_total: price_total,
|
|
56
|
-
client_name: sessionStorage.getItem('visualizerName'),
|
|
57
|
-
session_id: getSessionId()
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
};
|
package/lib/analytics/ga4.js
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.GA = void 0;
|
|
7
|
-
var _reactGa = _interopRequireDefault(require("react-ga4"));
|
|
8
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
9
|
-
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
10
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
11
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
12
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
13
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
14
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
15
|
-
// ---------- Helpers ----------
|
|
16
|
-
function nowMs() {
|
|
17
|
-
return Date.now();
|
|
18
|
-
}
|
|
19
|
-
function getClientName() {
|
|
20
|
-
return sessionStorage.getItem('visualizerName');
|
|
21
|
-
}
|
|
22
|
-
function isDesktopUA() {
|
|
23
|
-
// Lightweight heuristic; GA4 also provides device.category. This flag can help ad-hoc filtering.
|
|
24
|
-
var ua = navigator.userAgent.toLowerCase();
|
|
25
|
-
var isMobile = /mobi|android|iphone|ipad|ipod|windows phone/.test(ua);
|
|
26
|
-
return !isMobile;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// ---------- Keys for storage ----------
|
|
30
|
-
var SSN_KEYS = {
|
|
31
|
-
sessionStartMs: 'ga4_session_start_ms',
|
|
32
|
-
introChoiceMs: 'ga4_intro_choice_ms',
|
|
33
|
-
firstCabinetPlaced: 'ga4_first_cabinet_placed',
|
|
34
|
-
contextBooted: 'ga4_context_booted',
|
|
35
|
-
enteredCanvasSent: 'ga4_entered_canvas_sent'
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
// ---------- Core GA wrapper ----------
|
|
39
|
-
var GA = exports.GA = {
|
|
40
|
-
init: function init(_ref) {
|
|
41
|
-
var measurementId = _ref.measurementId;
|
|
42
|
-
_reactGa["default"].initialize([{
|
|
43
|
-
trackingId: measurementId
|
|
44
|
-
}], {
|
|
45
|
-
testMode: false
|
|
46
|
-
});
|
|
47
|
-
},
|
|
48
|
-
resetSessionKeys: function resetSessionKeys() {
|
|
49
|
-
Object.values(SSN_KEYS).forEach(function (key) {
|
|
50
|
-
sessionStorage.removeItem(key);
|
|
51
|
-
});
|
|
52
|
-
},
|
|
53
|
-
/**
|
|
54
|
-
* Must be called ONCE per page load, *before* other events.
|
|
55
|
-
* Sets user properties (project_entry, cross_auth) and sends an initial page_view with client_name.
|
|
56
|
-
*/
|
|
57
|
-
bootSessionContext: function bootSessionContext(_ref2) {
|
|
58
|
-
var projectEntry = _ref2.projectEntry,
|
|
59
|
-
crossAuth = _ref2.crossAuth;
|
|
60
|
-
try {
|
|
61
|
-
var resolvedClient = getClientName();
|
|
62
|
-
|
|
63
|
-
// Persist session start for timing metrics (if not already set for this tab)
|
|
64
|
-
if (!sessionStorage.getItem(SSN_KEYS.sessionStartMs)) {
|
|
65
|
-
sessionStorage.setItem(SSN_KEYS.sessionStartMs, String(nowMs()));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Mark context as booted to avoid duplicate property sets on hot reloads
|
|
69
|
-
if (!sessionStorage.getItem(SSN_KEYS.contextBooted)) {
|
|
70
|
-
sessionStorage.setItem(SSN_KEYS.contextBooted, '1');
|
|
71
|
-
|
|
72
|
-
// Set GA4 user_properties (user-scoped dimensions)
|
|
73
|
-
_reactGa["default"].gtag('set', 'user_properties', {
|
|
74
|
-
project_entry: projectEntry,
|
|
75
|
-
// user scope dimension
|
|
76
|
-
cross_auth: crossAuth // user scope dimension (boolean serialized)
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Send first page_view hit enriched with event-scoped client_name
|
|
81
|
-
_reactGa["default"].send({
|
|
82
|
-
hitType: 'pageview',
|
|
83
|
-
page: window.location.pathname + window.location.search,
|
|
84
|
-
// @ts-expect-error react-ga4 passes along additional params into gtag
|
|
85
|
-
client_name: resolvedClient
|
|
86
|
-
});
|
|
87
|
-
} catch (e) {
|
|
88
|
-
// eslint-disable-next-line no-console
|
|
89
|
-
console.warn('GA.bootSessionContext error', e);
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
// Utility to derive cross_auth from URL (token or details query params)
|
|
93
|
-
deriveCrossAuthFromUrl: function deriveCrossAuthFromUrl(search) {
|
|
94
|
-
var sp = new URLSearchParams(search);
|
|
95
|
-
return sp.has('token') || sp.has('details');
|
|
96
|
-
},
|
|
97
|
-
// Utility to derive project entry (best-effort). You can also pass explicitly from router logic.
|
|
98
|
-
deriveProjectEntry: function deriveProjectEntry() {
|
|
99
|
-
var projectId = sessionStorage.getItem('projectId');
|
|
100
|
-
|
|
101
|
-
// If a project id exists, consider it "open_existing"; otherwise fallback to "new"
|
|
102
|
-
if (projectId) return 'open_existing';
|
|
103
|
-
return 'new';
|
|
104
|
-
},
|
|
105
|
-
// ---------- Event API ----------
|
|
106
|
-
events: {
|
|
107
|
-
/**
|
|
108
|
-
* intro_choice(option) — records the user's entry choice.
|
|
109
|
-
* Also stores a timestamp for later time_to_canvas calculation.
|
|
110
|
-
*/
|
|
111
|
-
introChoice: function introChoice(option, extra) {
|
|
112
|
-
var client_name = getClientName();
|
|
113
|
-
sessionStorage.setItem(SSN_KEYS.introChoiceMs, String(nowMs()));
|
|
114
|
-
_reactGa["default"].event('intro_choice', _objectSpread({
|
|
115
|
-
client_name: client_name,
|
|
116
|
-
option: option
|
|
117
|
-
}, extra || {}));
|
|
118
|
-
},
|
|
119
|
-
/**
|
|
120
|
-
* entered_canvas(time_to_canvas) — compute (now - intro_choice)
|
|
121
|
-
*/
|
|
122
|
-
enteredCanvas: function enteredCanvas() {
|
|
123
|
-
// fire only once per tab/session
|
|
124
|
-
if (sessionStorage.getItem(SSN_KEYS.enteredCanvasSent)) return;
|
|
125
|
-
var client_name = getClientName();
|
|
126
|
-
var introMs = Number(sessionStorage.getItem(SSN_KEYS.introChoiceMs) || 0);
|
|
127
|
-
var timeSec = introMs ? Math.max(0, Math.round((Date.now() - introMs) / 1000)) : undefined;
|
|
128
|
-
_reactGa["default"].event('entered_canvas', _objectSpread({
|
|
129
|
-
client_name: client_name
|
|
130
|
-
}, typeof timeSec === 'number' ? {
|
|
131
|
-
time_to_canvas: timeSec
|
|
132
|
-
} : {}));
|
|
133
|
-
sessionStorage.setItem(SSN_KEYS.enteredCanvasSent, '1'); // 👈 lock it
|
|
134
|
-
},
|
|
135
|
-
/**
|
|
136
|
-
* cabinet_placed(time_to_first_cabinet) — send only for the *first* cabinet of the session.
|
|
137
|
-
*/
|
|
138
|
-
cabinetPlaced: function cabinetPlaced() {
|
|
139
|
-
var already = sessionStorage.getItem(SSN_KEYS.firstCabinetPlaced);
|
|
140
|
-
var client_name = getClientName();
|
|
141
|
-
var params = {
|
|
142
|
-
client_name: client_name
|
|
143
|
-
};
|
|
144
|
-
if (!already) {
|
|
145
|
-
var startMs = Number(sessionStorage.getItem(SSN_KEYS.sessionStartMs) || 0);
|
|
146
|
-
var timeSec = startMs ? Math.max(0, Math.round((nowMs() - startMs) / 1000)) : undefined;
|
|
147
|
-
if (typeof timeSec === 'number') params.time_to_first_cabinet = timeSec; // custom metric (seconds)
|
|
148
|
-
sessionStorage.setItem(SSN_KEYS.firstCabinetPlaced, '1');
|
|
149
|
-
}
|
|
150
|
-
_reactGa["default"].event('cabinet_placed', params);
|
|
151
|
-
},
|
|
152
|
-
/**
|
|
153
|
-
* door_changed(door_id)
|
|
154
|
-
*/
|
|
155
|
-
doorChanged: function doorChanged(door_id) {
|
|
156
|
-
var client_name = getClientName();
|
|
157
|
-
_reactGa["default"].event('door_changed', {
|
|
158
|
-
client_name: client_name,
|
|
159
|
-
door_id: door_id
|
|
160
|
-
});
|
|
161
|
-
},
|
|
162
|
-
/**
|
|
163
|
-
* project_saved(project_id, save_method) — mark as conversion in GA UI.
|
|
164
|
-
*/
|
|
165
|
-
projectSaved: function projectSaved(project_id, save_method) {
|
|
166
|
-
var client_name = getClientName();
|
|
167
|
-
_reactGa["default"].event('project_saved', {
|
|
168
|
-
client_name: client_name,
|
|
169
|
-
project_id: project_id,
|
|
170
|
-
save_method: save_method
|
|
171
|
-
});
|
|
172
|
-
},
|
|
173
|
-
/**
|
|
174
|
-
* assistance_requested(method, project_id) — mark as conversion in GA UI.
|
|
175
|
-
*/
|
|
176
|
-
assistanceRequested: function assistanceRequested(method, project_id) {
|
|
177
|
-
var client_name = getClientName();
|
|
178
|
-
_reactGa["default"].event('assistance_requested', {
|
|
179
|
-
client_name: client_name,
|
|
180
|
-
method: method,
|
|
181
|
-
project_id: project_id
|
|
182
|
-
});
|
|
183
|
-
},
|
|
184
|
-
/**
|
|
185
|
-
* add_to_cart(project_id, sku_count, price_total) — mark as conversion in GA UI.
|
|
186
|
-
*/
|
|
187
|
-
addToCart: function addToCart(project_id, sku_count, price_total) {
|
|
188
|
-
var client_name = getClientName();
|
|
189
|
-
_reactGa["default"].event('add_to_cart', {
|
|
190
|
-
client_name: client_name,
|
|
191
|
-
project_id: project_id,
|
|
192
|
-
sku_count: sku_count,
|
|
193
|
-
price_total: price_total
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
};
|