@tulipnpm/timekit_project_selector 2.1.2 → 2.1.3-rc.1

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.
@@ -0,0 +1,87 @@
1
+ # Strategies and Steps Architecture
2
+
3
+ This document outlines the architectural patterns used in the Tulip Appointments Web Widget to manage the flow of user selection ("Steps") and the logic for data retrieval ("Strategies").
4
+
5
+ ## Overview
6
+
7
+ The application is built around a "Wizard" concept where a user progresses through a series of choices (e.g., Select a Store -> Select a Service -> Book).
8
+ - **Steps** define the *configuration* and *state* of each stage in this wizard.
9
+ - **Strategies** define the *logic* for fetching and filtering the data shown in each step.
10
+
11
+ ## Strategies
12
+
13
+ Located in `src/Strategy/`, Strategies encapsulate the logic for interacting with the TimeKit API to retrieve specific types of projects (Stores, Services, etc.).
14
+
15
+ ### Key Components
16
+
17
+ * **`ProjectsStrategy.js` (The Factory)**
18
+ * Acts as the central registry and factory for all strategies.
19
+ * Exposes `getStrategy(type)` which returns a specific strategy instance based on a string key (e.g., `'store_project'`, `'service_project'`).
20
+ * Manages the singleton instances of the specific strategies.
21
+
22
+ * **`LocationsStrategy.js` (`store_project`)**
23
+ * Responsible for fetching "Store" projects.
24
+ * Handles filtering by `t_store_id`.
25
+ * Used when the step requires the user to pick a physical location.
26
+
27
+ * **`ServiceProjectsStatergy.js` (`service_project`)**
28
+ * Responsible for fetching "Service" or "Appointment Type" projects.
29
+ * Handles filtering by `t_service_id` (and potentially cross-referencing with selected stores).
30
+
31
+ * **`DefaultProjectStrategy.js`**
32
+ * Provides a fallback or combined logic flow, often chaining location and service retrieval.
33
+
34
+ ### Usage
35
+ The UI layer typically requests a strategy via the factory:
36
+ ```javascript
37
+ const strategy = projectsStrategy.getStrategy('store_project');
38
+ const projects = await strategy.getProjects(filters);
39
+ ```
40
+
41
+ ## Steps
42
+
43
+ Located in `src/Steps/`, the Steps system manages the configuration provided by the user (via `selectorOptions`) and tracks the user's progress.
44
+
45
+ ### Key Components
46
+
47
+ * **`StepsFactory.js` (The Manager)**
48
+ * Initialized with the `selectorOptions` object from the main configuration.
49
+ * Converts the configuration object into an array of `Step` instances.
50
+ * Tracks the `currentStepNum`.
51
+ * Provides methods for navigation (`nextStep()`, `previousStep()`, `currentStep()`).
52
+
53
+ * **`Step.js`**
54
+ * Represents a single screen or stage in the widget.
55
+ * **Links to Strategy:** Contains a `projectType` or `strategy` field (e.g., `'store_project'`) that tells the UI which Strategy to use to fetch data for this step.
56
+ * **Filters:** Holds `defaultFilters` (configured globally) and `stepFilters` (dynamic filters for this specific step).
57
+
58
+ * **`StepOptions.js`**
59
+ * Encapsulates configuration for the step's container UI.
60
+ * Properties: `title`, `description`, `searchBar` config, `geoSearchBar` config.
61
+
62
+ * **`StepDataOptions.js`**
63
+ * Encapsulates configuration for how *items* within the step are rendered (the cards).
64
+ * Properties: `cardTitle`, `cardBody`, `cardFooter`, `cardImage`.
65
+ * Supports template strings (e.g., `{{[meta]city}}`).
66
+
67
+ ## Interaction Flow
68
+
69
+ 1. **Initialization:**
70
+ * The user configures `selectorOptions` in `timekit_project_selector.init()`.
71
+ * `StepsFactory` reads this and creates a list of `Step` objects.
72
+
73
+ 2. **Rendering a Step:**
74
+ * The UI asks `StepsFactory` for the `currentStep()`.
75
+ * The UI reads the `StepOptions` to render the header (Title, Search Bar).
76
+ * The UI reads the `strategy` key from the `Step`.
77
+ * The UI uses `ProjectsStrategy` to get the actual Strategy object.
78
+ * The UI calls `strategy.getProjects()` to get the data.
79
+
80
+ 3. **Rendering Items:**
81
+ * The UI iterates over the returned projects.
82
+ * It uses `StepDataOptions` from the current `Step` to resolve template strings and render the cards.
83
+
84
+ 4. **Navigation:**
85
+ * When a user selects an item, the UI captures the selection.
86
+ * It may add a filter to the `StepsFactory` for the *next* step (e.g., "User selected Store A, so filter Services by Store A").
87
+ * The UI calls `StepsFactory.nextStep()` and repeats the process.
package/junit.xml CHANGED
@@ -1,116 +1,148 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <testsuites name="jest tests" tests="49" failures="0" errors="0" time="2.708">
3
- <testsuite name="Search Bar functionality" errors="0" failures="0" skipped="0" timestamp="2022-07-21T20:17:19" time="1.019" tests="2">
4
- <testcase classname="Search Bar functionality Init search bar" name="Search Bar functionality Init search bar" time="0.002">
2
+ <testsuites name="jest tests" tests="62" failures="0" errors="0" time="2.492">
3
+ <testsuite name="Initialization" errors="0" failures="0" skipped="0" timestamp="2026-01-06T21:15:33" time="0.296" tests="2">
4
+ <testcase classname="Initialization Contstructor" name="Initialization Contstructor" time="0.001">
5
5
  </testcase>
6
- <testcase classname="Search Bar functionality Search Bar - Helper Functions" name="Search Bar functionality Search Bar - Helper Functions" time="0.001">
6
+ <testcase classname="Projects Set Projects" name="Projects Set Projects" time="0">
7
7
  </testcase>
8
8
  </testsuite>
9
- <testsuite name="Basic" errors="0" failures="0" skipped="0" timestamp="2022-07-21T20:17:19" time="1.026" tests="5">
10
- <testcase classname="Basic Init" name="Basic Init" time="0.001">
9
+ <testsuite name="Setup Default UI" errors="0" failures="0" skipped="1" timestamp="2026-01-06T21:15:33" time="0.172" tests="6">
10
+ <testcase classname="Setup Default UI Missing Container" name="Setup Default UI Missing Container" time="0.006">
11
11
  </testcase>
12
- <testcase classname="Basic Setup - No Location" name="Basic Setup - No Location" time="0">
12
+ <testcase classname="Setup Default UI Adds Container Objects" name="Setup Default UI Adds Container Objects" time="0.014">
13
13
  </testcase>
14
- <testcase classname="Basic Setup - Mocked Location" name="Basic Setup - Mocked Location" time="0.001">
14
+ <testcase classname="Setup Default UI Missing Search Bar Required &apos;enabled&apos; Field" name="Setup Default UI Missing Search Bar Required &apos;enabled&apos; Field" time="0.002">
15
15
  </testcase>
16
- <testcase classname="Calculations Distance Between Coordinates" name="Calculations Distance Between Coordinates" time="0.001">
16
+ <testcase classname="Widget Specific Has Close Button" name="Widget Specific Has Close Button" time="0">
17
+ <skipped/>
17
18
  </testcase>
18
- <testcase classname="Calculations Degrees To Radians" name="Calculations Degrees To Radians" time="0">
19
+ <testcase classname="Embedded Specific No Close Button" name="Embedded Specific No Close Button" time="0.003">
20
+ </testcase>
21
+ <testcase classname="Embedded Specific Check embedded width" name="Embedded Specific Check embedded width" time="0.003">
19
22
  </testcase>
20
23
  </testsuite>
21
- <testsuite name="Initialization" errors="0" failures="0" skipped="0" timestamp="2022-07-21T20:17:19" time="1.029" tests="4">
22
- <testcase classname="Initialization Contstructor" name="Initialization Contstructor" time="0.001">
24
+ <testsuite name="Initalization" errors="0" failures="0" skipped="0" timestamp="2026-01-06T21:15:33" time="0.047" tests="14">
25
+ <testcase classname="Initalization Default" name="Initalization Default" time="0">
23
26
  </testcase>
24
- <testcase classname="Projects Set Projects" name="Projects Set Projects" time="0.001">
27
+ <testcase classname="Initalization Default" name="Initalization Default" time="0">
25
28
  </testcase>
26
- <testcase classname="Projects Get Projects w No Filters" name="Projects Get Projects w No Filters" time="0">
29
+ <testcase classname="Initalization Set count" name="Initalization Set count" time="0">
27
30
  </testcase>
28
- <testcase classname="Projects Get Projects w Filter" name="Projects Get Projects w Filter" time="0">
31
+ <testcase classname="Initalization Set count string" name="Initalization Set count string" time="0">
29
32
  </testcase>
30
- </testsuite>
31
- <testsuite name="Initialization" errors="0" failures="0" skipped="0" timestamp="2022-07-21T20:17:19" time="1.039" tests="14">
32
- <testcase classname="Initialization Contstructor" name="Initialization Contstructor" time="0.001">
33
+ <testcase classname="Stack Tests Push" name="Stack Tests Push" time="0">
33
34
  </testcase>
34
- <testcase classname="Bulk Set Setting all" name="Bulk Set Setting all" time="0.001">
35
+ <testcase classname="Stack Tests Push over limit" name="Stack Tests Push over limit" time="0">
35
36
  </testcase>
36
- <testcase classname="Bulk Set Expecting some default" name="Bulk Set Expecting some default" time="0">
37
+ <testcase classname="Stack Tests Pop" name="Stack Tests Pop" time="0">
37
38
  </testcase>
38
- <testcase classname="Bulk Set Unknown Value in Config" name="Bulk Set Unknown Value in Config" time="0.001">
39
+ <testcase classname="Stack Tests Pop Empty" name="Stack Tests Pop Empty" time="0">
39
40
  </testcase>
40
- <testcase classname="Validate Require Fields All set" name="Validate Require Fields All set" time="0">
41
+ <testcase classname="Stack Tests Get Current" name="Stack Tests Get Current" time="0">
41
42
  </testcase>
42
- <testcase classname="Validate Require Fields Set but empty" name="Validate Require Fields Set but empty" time="0">
43
+ <testcase classname="UI Changes Tests Missing timekit-project-selector-container" name="UI Changes Tests Missing timekit-project-selector-container" time="0">
43
44
  </testcase>
44
- <testcase classname="Validate Require Fields Missing" name="Validate Require Fields Missing" time="0">
45
+ <testcase classname="UI Changes Tests Setup" name="UI Changes Tests Setup" time="0.002">
45
46
  </testcase>
46
- <testcase classname="Get Methods shouldUseDefaultUI" name="Get Methods shouldUseDefaultUI" time="0">
47
+ <testcase classname="UI Changes Tests Navigation Bar - Count Matches Dots + Lines" name="UI Changes Tests Navigation Bar - Count Matches Dots + Lines" time="0.002">
47
48
  </testcase>
48
- <testcase classname="Get Methods isEmbedded" name="Get Methods isEmbedded" time="0">
49
+ <testcase classname="UI Changes Tests Navigation Bar - Active Elements" name="UI Changes Tests Navigation Bar - Active Elements" time="0.007">
49
50
  </testcase>
50
- <testcase classname="Get Methods Get config" name="Get Methods Get config" time="0.001">
51
+ <testcase classname="UI Changes Tests Navigation Bar - Calculate Length of Lines" name="UI Changes Tests Navigation Bar - Calculate Length of Lines" time="0.003">
51
52
  </testcase>
52
- <testcase classname="Get Methods Get config - missing" name="Get Methods Get config - missing" time="0">
53
+ </testsuite>
54
+ <testsuite name="modifyFetchedAvailability()" errors="0" failures="0" skipped="0" timestamp="2026-01-06T21:15:33" time="0.032" tests="5">
55
+ <testcase classname="modifyFetchedAvailability() SHOULD retrieve employees assigned to project&apos;s store and service" name="modifyFetchedAvailability() SHOULD retrieve employees assigned to project&apos;s store and service" time="0.001">
53
56
  </testcase>
54
- <testcase classname="Selector Options Get selectorOptions by key" name="Selector Options Get selectorOptions by key" time="0">
57
+ <testcase classname="modifyFetchedAvailability() SHOULD retrieve availability for each individual employee" name="modifyFetchedAvailability() SHOULD retrieve availability for each individual employee" time="0">
55
58
  </testcase>
56
- <testcase classname="Selector Options Get selectorOptions by key - missing key" name="Selector Options Get selectorOptions by key - missing key" time="0">
59
+ <testcase classname="modifyFetchedAvailability() WHEN adjusting the projects available timeslots SHOULD return time slots unchanged if at least one employee is available for every time slot" name="modifyFetchedAvailability() WHEN adjusting the projects available timeslots SHOULD return time slots unchanged if at least one employee is available for every time slot" time="0.001">
57
60
  </testcase>
58
- <testcase classname="Selector Options SelectorOptions Count" name="Selector Options SelectorOptions Count" time="0">
61
+ <testcase classname="modifyFetchedAvailability() WHEN adjusting the projects available timeslots SHOULD return zero timeslots when no employee is available" name="modifyFetchedAvailability() WHEN adjusting the projects available timeslots SHOULD return zero timeslots when no employee is available" time="0">
62
+ </testcase>
63
+ <testcase classname="modifyFetchedAvailability() WHEN adjusting the projects available timeslots SHOULD return timeslots which can be covered by at least one employee" name="modifyFetchedAvailability() WHEN adjusting the projects available timeslots SHOULD return timeslots which can be covered by at least one employee" time="0">
59
64
  </testcase>
60
65
  </testsuite>
61
- <testsuite name="getKeyValue" errors="0" failures="0" skipped="0" timestamp="2022-07-21T20:17:19" time="1.041" tests="4">
62
- <testcase classname="getKeyValue Basic" name="getKeyValue Basic" time="0.001">
66
+ <testsuite name="TimekitApiClient" errors="0" failures="0" skipped="0" timestamp="2026-01-06T21:15:33" time="0.026" tests="5">
67
+ <testcase classname="TimekitApiClient getEmployeeUUIDsByServiceAndStore SHOULD retrieve employees assigned to the store" name="TimekitApiClient getEmployeeUUIDsByServiceAndStore SHOULD retrieve employees assigned to the store" time="0">
63
68
  </testcase>
64
- <testcase classname="getKeyValue Meta Replacement" name="getKeyValue Meta Replacement" time="0.001">
69
+ <testcase classname="TimekitApiClient getEmployeeUUIDsByServiceAndStore SHOULD only return employees assigned to the service or assigned to no service." name="TimekitApiClient getEmployeeUUIDsByServiceAndStore SHOULD only return employees assigned to the service or assigned to no service." time="0">
65
70
  </testcase>
66
- <testcase classname="getKeyValue Missing Key" name="getKeyValue Missing Key" time="0">
71
+ <testcase classname="TimekitApiClient getEmployeeUUIDsByServiceAndStore SHOULD auto assign employee no assigned services if employee does not have service type ids set." name="TimekitApiClient getEmployeeUUIDsByServiceAndStore SHOULD auto assign employee no assigned services if employee does not have service type ids set." time="0.001">
67
72
  </testcase>
68
- <testcase classname="doesIdExist Basic" name="doesIdExist Basic" time="0.003">
73
+ <testcase classname="TimekitApiClient getEmployeeUUIDsByServiceAndStore SHOULD not fail if the t_service_type_ids is not a string" name="TimekitApiClient getEmployeeUUIDsByServiceAndStore SHOULD not fail if the t_service_type_ids is not a string" time="0">
74
+ </testcase>
75
+ <testcase classname="TimekitApiClient getEmployeeUUIDsByServiceAndStore SHOULD not return disabled employees" name="TimekitApiClient getEmployeeUUIDsByServiceAndStore SHOULD not return disabled employees" time="0">
69
76
  </testcase>
70
77
  </testsuite>
71
- <testsuite name="Initalization" errors="0" failures="0" skipped="0" timestamp="2022-07-21T20:17:19" time="1.099" tests="14">
72
- <testcase classname="Initalization Default" name="Initalization Default" time="0.001">
78
+ <testsuite name="autoAssignAssociateToBooking()" errors="0" failures="0" skipped="0" timestamp="2026-01-06T21:15:33" time="0.029" tests="5">
79
+ <testcase classname="autoAssignAssociateToBooking() SHOULD retrieve employees assigned to project&apos;s store and service" name="autoAssignAssociateToBooking() SHOULD retrieve employees assigned to project&apos;s store and service" time="0">
73
80
  </testcase>
74
- <testcase classname="Initalization Default" name="Initalization Default" time="0.001">
81
+ <testcase classname="autoAssignAssociateToBooking() SHOULD retrieve availability for identified employees" name="autoAssignAssociateToBooking() SHOULD retrieve availability for identified employees" time="0">
75
82
  </testcase>
76
- <testcase classname="Initalization Set count" name="Initalization Set count" time="0">
83
+ <testcase classname="autoAssignAssociateToBooking() SHOULD add first available employee to booking" name="autoAssignAssociateToBooking() SHOULD add first available employee to booking" time="0">
77
84
  </testcase>
78
- <testcase classname="Initalization Set count string" name="Initalization Set count string" time="0">
85
+ <testcase classname="autoAssignAssociateToBooking() SHOULD not attempt to modify booking if no employees are available" name="autoAssignAssociateToBooking() SHOULD not attempt to modify booking if no employees are available" time="0">
79
86
  </testcase>
80
- <testcase classname="Stack Tests Push" name="Stack Tests Push" time="0.001">
87
+ <testcase classname="autoAssignAssociateToBooking() SHOULD not attempt to modify booking if no employees have availablility" name="autoAssignAssociateToBooking() SHOULD not attempt to modify booking if no employees have availablility" time="0.001">
81
88
  </testcase>
82
- <testcase classname="Stack Tests Push over limit" name="Stack Tests Push over limit" time="0.001">
89
+ </testsuite>
90
+ <testsuite name="Initialization" errors="0" failures="0" skipped="0" timestamp="2026-01-06T21:15:33" time="0.023" tests="14">
91
+ <testcase classname="Initialization Contstructor" name="Initialization Contstructor" time="0">
83
92
  </testcase>
84
- <testcase classname="Stack Tests Pop" name="Stack Tests Pop" time="0">
93
+ <testcase classname="Bulk Set Setting all" name="Bulk Set Setting all" time="0">
94
+ </testcase>
95
+ <testcase classname="Bulk Set Expecting some default" name="Bulk Set Expecting some default" time="0">
85
96
  </testcase>
86
- <testcase classname="Stack Tests Pop Empty" name="Stack Tests Pop Empty" time="0.001">
97
+ <testcase classname="Bulk Set Unknown Value in Config" name="Bulk Set Unknown Value in Config" time="0">
87
98
  </testcase>
88
- <testcase classname="Stack Tests Get Current" name="Stack Tests Get Current" time="0">
99
+ <testcase classname="Validate Require Fields All set" name="Validate Require Fields All set" time="0">
100
+ </testcase>
101
+ <testcase classname="Validate Require Fields Set but empty" name="Validate Require Fields Set but empty" time="0">
102
+ </testcase>
103
+ <testcase classname="Validate Require Fields Missing" name="Validate Require Fields Missing" time="0">
104
+ </testcase>
105
+ <testcase classname="Get Methods shouldUseDefaultUI" name="Get Methods shouldUseDefaultUI" time="0">
106
+ </testcase>
107
+ <testcase classname="Get Methods isEmbedded" name="Get Methods isEmbedded" time="0">
108
+ </testcase>
109
+ <testcase classname="Get Methods Get config" name="Get Methods Get config" time="0.001">
110
+ </testcase>
111
+ <testcase classname="Get Methods Get config - missing" name="Get Methods Get config - missing" time="0">
112
+ </testcase>
113
+ <testcase classname="Selector Options Get selectorOptions by key" name="Selector Options Get selectorOptions by key" time="0">
114
+ </testcase>
115
+ <testcase classname="Selector Options Get selectorOptions by key - missing key" name="Selector Options Get selectorOptions by key - missing key" time="0">
116
+ </testcase>
117
+ <testcase classname="Selector Options SelectorOptions Count" name="Selector Options SelectorOptions Count" time="0">
89
118
  </testcase>
90
- <testcase classname="UI Changes Tests Missing timekit-project-selector-container" name="UI Changes Tests Missing timekit-project-selector-container" time="0.001">
119
+ </testsuite>
120
+ <testsuite name="Basic" errors="0" failures="0" skipped="0" timestamp="2026-01-06T21:15:33" time="0.021" tests="5">
121
+ <testcase classname="Basic Init" name="Basic Init" time="0.001">
91
122
  </testcase>
92
- <testcase classname="UI Changes Tests Setup" name="UI Changes Tests Setup" time="0.009">
123
+ <testcase classname="Basic Setup - No Location" name="Basic Setup - No Location" time="0">
93
124
  </testcase>
94
- <testcase classname="UI Changes Tests Navigation Bar - Count Matches Dots + Lines" name="UI Changes Tests Navigation Bar - Count Matches Dots + Lines" time="0.006">
125
+ <testcase classname="Basic Setup - Mocked Location" name="Basic Setup - Mocked Location" time="0.001">
95
126
  </testcase>
96
- <testcase classname="UI Changes Tests Navigation Bar - Active Elements" name="UI Changes Tests Navigation Bar - Active Elements" time="0.006">
127
+ <testcase classname="Calculations Distance Between Coordinates" name="Calculations Distance Between Coordinates" time="0">
97
128
  </testcase>
98
- <testcase classname="UI Changes Tests Navigation Bar - Calculate Length of Lines" name="UI Changes Tests Navigation Bar - Calculate Length of Lines" time="0.01">
129
+ <testcase classname="Calculations Degrees To Radians" name="Calculations Degrees To Radians" time="0">
99
130
  </testcase>
100
131
  </testsuite>
101
- <testsuite name="Setup Default UI" errors="0" failures="0" skipped="1" timestamp="2022-07-21T20:17:19" time="1.157" tests="6">
102
- <testcase classname="Setup Default UI Missing Container" name="Setup Default UI Missing Container" time="0.017">
132
+ <testsuite name="getKeyValue" errors="0" failures="0" skipped="0" timestamp="2026-01-06T21:15:33" time="0.022" tests="4">
133
+ <testcase classname="getKeyValue Basic" name="getKeyValue Basic" time="0">
103
134
  </testcase>
104
- <testcase classname="Setup Default UI Adds Container Objects" name="Setup Default UI Adds Container Objects" time="0.03">
135
+ <testcase classname="getKeyValue Meta Replacement" name="getKeyValue Meta Replacement" time="0">
105
136
  </testcase>
106
- <testcase classname="Setup Default UI Missing Search Bar Required &apos;enabled&apos; Field" name="Setup Default UI Missing Search Bar Required &apos;enabled&apos; Field" time="0.005">
137
+ <testcase classname="getKeyValue Missing Key" name="getKeyValue Missing Key" time="0">
107
138
  </testcase>
108
- <testcase classname="Widget Specific Has Close Button" name="Widget Specific Has Close Button" time="0">
109
- <skipped/>
139
+ <testcase classname="doesIdExist Basic" name="doesIdExist Basic" time="0.001">
110
140
  </testcase>
111
- <testcase classname="Embedded Specific No Close Button" name="Embedded Specific No Close Button" time="0.004">
141
+ </testsuite>
142
+ <testsuite name="Search Bar functionality" errors="0" failures="0" skipped="0" timestamp="2026-01-06T21:15:33" time="0.02" tests="2">
143
+ <testcase classname="Search Bar functionality Init search bar" name="Search Bar functionality Init search bar" time="0">
112
144
  </testcase>
113
- <testcase classname="Embedded Specific Check embedded width" name="Embedded Specific Check embedded width" time="0.004">
145
+ <testcase classname="Search Bar functionality Search Bar - Helper Functions" name="Search Bar functionality Search Bar - Helper Functions" time="0">
114
146
  </testcase>
115
147
  </testsuite>
116
148
  </testsuites>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tulipnpm/timekit_project_selector",
3
3
  "description": "Tulip Appointments Web Widget",
4
- "version": "2.1.2",
4
+ "version": "2.1.3-rc.1",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "build": "webpack",
@@ -20,7 +20,9 @@
20
20
  "@fontsource/open-sans": "^4.2.2",
21
21
  "babel-jest": "^26.6.3",
22
22
  "babel-loader": "^8.2.2",
23
+ "babel-plugin-dynamic-import-node": "^2.3.3",
23
24
  "babel-plugin-syntax-dynamic-import": "^6.18.0",
25
+ "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
24
26
  "babel-preset-env": "^1.7.0",
25
27
  "css-loader": "^5.2.7",
26
28
  "file-loader": "^6.2.0",