@thefittingroom/shop-ui 3.2.3 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/.env.development +13 -0
  2. package/.env.example +20 -0
  3. package/.env.production +14 -0
  4. package/AGENTS.md +8 -0
  5. package/dist/index.js +22198 -0
  6. package/dist/index.umd.cjs +22202 -0
  7. package/index.html +246 -98
  8. package/package.json +17 -22
  9. package/vite.config.js +39 -0
  10. package/.env.dev +0 -2
  11. package/.env.prod +0 -2
  12. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/ErrorModal.js +0 -43
  13. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/ErrorModal.js.map +0 -1
  14. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/FitModal.js +0 -106
  15. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/FitModal.js.map +0 -1
  16. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/ForgotPasswordModal.js +0 -43
  17. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/ForgotPasswordModal.js.map +0 -1
  18. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/LoadingAvatarModal.js +0 -38
  19. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/LoadingAvatarModal.js.map +0 -1
  20. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/LoggedOutModal.js +0 -36
  21. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/LoggedOutModal.js.map +0 -1
  22. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/ModalManager.js +0 -107
  23. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/ModalManager.js.map +0 -1
  24. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/NoAvatarModal.js +0 -19
  25. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/NoAvatarModal.js.map +0 -1
  26. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/ResetLinkModal.js +0 -31
  27. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/ResetLinkModal.js.map +0 -1
  28. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/ScanCodeModal.js +0 -77
  29. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/ScanCodeModal.js.map +0 -1
  30. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/SignInModal.js +0 -94
  31. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/SignInModal.js.map +0 -1
  32. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/SizeErrorModal.js +0 -43
  33. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/SizeErrorModal.js.map +0 -1
  34. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/TryOnModal.js +0 -51
  35. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Modals/TryOnModal.js.map +0 -1
  36. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/SizeRec.js +0 -365
  37. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/SizeRec.js.map +0 -1
  38. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Vto.js +0 -52
  39. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/Vto.js.map +0 -1
  40. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/index.js +0 -16
  41. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/index.js.map +0 -1
  42. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/locale.js +0 -108
  43. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/locale.js.map +0 -1
  44. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/slider.js +0 -44
  45. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/slider.js.map +0 -1
  46. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/svgs.js +0 -33
  47. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/svgs.js.map +0 -1
  48. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/uiError.js +0 -8
  49. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/components/uiError.js.map +0 -1
  50. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/helpers/telephone.js +0 -12368
  51. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/helpers/telephone.js.map +0 -1
  52. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/helpers/validations.js +0 -15
  53. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/helpers/validations.js.map +0 -1
  54. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/index.js +0 -3
  55. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/index.js.map +0 -1
  56. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/init.js +0 -7
  57. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/init.js.map +0 -1
  58. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/styles/index.js +0 -12
  59. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/styles/index.js.map +0 -1
  60. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/tfr-modal.js +0 -77
  61. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/tfr-modal.js.map +0 -1
  62. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/tfr-size-rec.js +0 -202
  63. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/tfr-size-rec.js.map +0 -1
  64. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/tfr.js +0 -212
  65. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/tfr.js.map +0 -1
  66. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/types/index.js +0 -15
  67. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/esm/types/index.js.map +0 -1
  68. package/.rollup.cache/home/runner/work/shop-sdk-ui/shop-sdk-ui/dist/tsconfig.tsbuildinfo +0 -1
  69. package/README.md +0 -153
  70. package/dist/esm/index.js +0 -28142
  71. package/dist/esm/index.js.map +0 -1
  72. package/dist/esm/index.min.js +0 -3399
  73. package/dist/esm/index.min.js.map +0 -1
  74. package/dist/tsconfig.tsbuildinfo +0 -1
package/index.html CHANGED
@@ -1,126 +1,274 @@
1
+ <!DOCTYPE html>
1
2
  <html lang="en">
2
- <head>
3
- <title>TheFittingRoom</title>
4
- <meta name="viewport" content="width=device-width, initial-scale=1" />
5
-
6
- <link href="https://fonts.googleapis.com" rel="preconnect" />
7
- <link href="https://fonts.gstatic.com" rel="preconnect" crossorigin />
8
- <link
9
- href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500&family=Roboto&display=swap"
10
- rel="stylesheet"
11
- />
12
-
13
- <script type="module">
14
- import { InitFittingRoom, InitLocale, comps } from 'http://localhost:3030/dist/esm/index.js?language=en'
15
-
16
- InitLocale()
17
- window.mm = comps.InitModalManager('tfr-manual-modal')
18
- window.comps = comps
19
- window.onSignout = (colorwaySizeAssetSKU) => {
20
- console.log('signout', colorwaySizeAssetSKU)
21
- }
22
- window.onClose = () => {
23
- console.log('close')
24
- }
25
- window.onNavBack = () => {
26
- console.log('back')
27
- }
28
- window.onTryOn = (colorwaySizeAssetSKU) => {
29
- console.log('try on', colorwaySizeAssetSKU)
30
- }
31
- window.whenSignedIn = (user, colorwaySizeAssetSKU) => {
32
- console.log('after sign in', user, colorwaySizeAssetSKU)
33
- }
34
- window.onSignIn = (colorwaySizeAssetSKU) => (username, password, validationError) => {
35
- if (username.length == 0 || password.length == 0) {
36
- validationError('Username or password is empty')
3
+
4
+ <head>
5
+ <title>TheFittingRoom Widget Demo</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+
8
+ <link href="https://fonts.googleapis.com" rel="preconnect" />
9
+ <link href="https://fonts.gstatic.com" rel="preconnect" crossorigin />
10
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500&family=Roboto&display=swap"
11
+ rel="stylesheet" />
12
+ <!-- CSS is generated during build to dist/ directory -->
13
+ <!-- <link href="/dist/index.css" rel="stylesheet" /> -->
14
+
15
+ <style>
16
+ body {
17
+ font-family: 'Roboto', sans-serif;
18
+ margin: 0;
19
+ padding: 20px;
20
+ background-color: #f5f5f5;
21
+ }
22
+
23
+ .demo-container {
24
+ max-width: 800px;
25
+ margin: 0 auto;
26
+ background: white;
27
+ padding: 20px;
28
+ border-radius: 8px;
29
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
30
+ }
31
+
32
+ .product-selector {
33
+ margin-bottom: 20px;
34
+ padding: 15px;
35
+ border: 1px solid #ddd;
36
+ border-radius: 5px;
37
+ }
38
+
39
+ .product-selector h3 {
40
+ margin-top: 0;
41
+ color: #333;
42
+ }
43
+
44
+ select {
45
+ width: 100%;
46
+ padding: 8px;
47
+ margin: 10px 0;
48
+ border: 1px solid #ccc;
49
+ border-radius: 4px;
50
+ }
51
+
52
+ .tfr-widget-container {
53
+ margin-top: 20px;
54
+ }
55
+
56
+ .tfr-home-button-container {
57
+ margin-top: 20px;
58
+ text-align: center;
59
+ }
60
+
61
+ .tfr-home-button-container button {
62
+ margin: 5px;
63
+ padding: 10px 15px;
64
+ background-color: #007bff;
65
+ color: white;
66
+ border: none;
67
+ border-radius: 4px;
68
+ cursor: pointer;
69
+ }
70
+
71
+ .tfr-home-button-container button:hover {
72
+ background-color: #0056b3;
73
+ }
74
+
75
+ #tfr-tryon-image {
76
+ max-width: 100%;
77
+ height: auto;
78
+ margin: 20px 0;
79
+ border: 1px solid #ddd;
80
+ border-radius: 4px;
81
+ }
82
+
83
+ #tfr-slider {
84
+ width: 100%;
85
+ margin: 10px 0;
86
+ }
87
+ </style>
88
+
89
+ <script type="module">
90
+ import { comps, initFittingRoom } from '/src/index.js'
91
+
92
+ const ENV = 'development'
93
+
94
+ const brandID = 1
95
+
96
+
97
+ const productSKU = 'TFR_FITTED-DRESS_178cm_BlackBa'
98
+ const variantSKUs = [
99
+ 'TFR_Fitted-Dress_178_BlackBandana_2',
100
+ 'TFR_Fitted-Dress_178_BlackBandana_4',
101
+ 'TFR_Fitted-Dress_178_BlackBandana_6',
102
+ 'TFR_Fitted-Dress_178_BlackBandana_8',
103
+ 'TFR_Fitted-Dress_178_BlackBandana_10',
104
+ ]
105
+
106
+ // Mock product variants for demonstration
107
+ const productVariants = [
108
+ { option1: '2', option2: 'BlackBandana', sku: 'TFR_Fitted-Dress_178_BlackBandana_2' },
109
+ { option1: '4', option2: 'BlackBandana', sku: 'TFR_Fitted-Dress_178_BlackBandana_4' },
110
+ { option1: '6', option2: 'BlackBandana', sku: 'TFR_Fitted-Dress_178_BlackBandana_6' },
111
+ { option1: '8', option2: 'BlackBandana', sku: 'TFR_Fitted-Dress_178_BlackBandana_8' },
112
+ { option1: '10', option2: 'BlackBandana', sku: 'TFR_Fitted-Dress_178_BlackBandana_10' },
113
+ ]
114
+
115
+ const getSku = () => {
116
+ try {
117
+ if (typeof productVariants === 'undefined' || !Array.isArray(productVariants)) {
118
+ throw new Error(
119
+ 'productVariants is not defined or is not an array. The Fitting Room cannot determine product SKUs without this data.',
120
+ )
37
121
  }
122
+
123
+ const colorInput = document.getElementsByName(`options[Color]`)?.[0]
124
+ const sizeInput = document.getElementsByName(`options[Size]`)?.[0]
125
+
126
+ const color = colorInput ? colorInput.value : undefined
127
+ const size = sizeInput ? sizeInput.value : undefined
128
+
129
+ if (!colorInput) {
130
+ console.error('Error in getSku: Color input element (options[Color]) not found on the page.')
131
+ }
132
+ if (!sizeInput) {
133
+ console.error('Error in getSku: Size input element (options[Size]) not found on the page.')
134
+ }
135
+
136
+ const activeVariant = productVariants.find((item) => {
137
+ const hasSizeMatch = !size || item.option1 === size || item.option2 === size
138
+ const hasColorMatch = !color || item.option1 === color || item.option2 === color
139
+ return hasSizeMatch && hasColorMatch
140
+ })
141
+
142
+ if (!activeVariant) {
143
+ throw new Error(
144
+ 'No product variant found for the selected color and size combination. Please check product data.',
145
+ )
146
+ }
147
+
148
+ return activeVariant?.sku
149
+ } catch (error) {
150
+ console.error(`Error in getSku: ${error.message}. SKU retrieval failed.`)
151
+ return null
38
152
  }
39
- window.onNavSignIn = (colorwaySizeAssetSKU) => (email) => {
40
- console.log('nav sign in', colorwaySizeAssetSKU, email)
41
- }
42
- window.onPasswordReset = (colorwaySizeAssetSKU) => (email) => {
43
- console.log('password reset', colorwaySizeAssetSKU, email)
44
- }
45
- window.onNavForgotPassword = (colorwaySizeAssetSKU) => (email) => {
46
- console.log('nav forgot password', colorwaySizeAssetSKU, email)
47
- }
48
- window.onNavScanCode = () => {
49
- console.log('nav scan code')
50
- }
153
+ }
51
154
 
52
- window.addEventListener('load', (e) => {
53
- let tryOnImage = document.getElementById('tfr-tryon-image')
54
- let signout = document.getElementById('signout')
55
- let onChange = (slider, imageUrl) => {
56
- tryOnImage.src = imageUrl
155
+ window.addEventListener('DOMContentLoaded', async (e) => {
156
+ let tfr = null
157
+
158
+ try {
159
+
160
+ const config = {
161
+ shopId: brandID,
162
+ styleSKU: productSKU,
163
+ modalDivId: 'thefittingroom-modal',
164
+ sizeRecMainDivId: 'tfr-size-recommendation-main',
165
+ vtoMainDivId: 'tfr-vto',
166
+ noCacheOnRetry: true,
167
+ env: typeof ENV !== 'undefined' ? ENV : 'development',
57
168
  }
58
- let slider = comps.InitImageSlider('tfr-slider', onChange)
59
- let tfr = InitFittingRoom(1, 'tfr-tryon-modal')
60
169
 
61
- tfr.whenFramesReady = (sku, frames) => {
62
- console.log('frames ready', sku, frames)
63
- slider.Load(frames)
170
+ const sku = getSku()
171
+ if (!sku) {
172
+ console.warn('SKU not retrieved. The Fitting Room will initialize but may not function optimally without a specific SKU.')
64
173
  }
174
+ const tfr = await initFittingRoom(config)
65
175
 
66
- signout.addEventListener('click', () => {
67
- tfr
68
- .onSignout('')()
69
- .then(() => {
70
- console.log('signout')
71
- })
72
- })
176
+ if (sku) {
177
+ tfr.SetColorwaySizeAssetBySKU(sku, variantSKUs, true)
178
+ }
73
179
 
74
- document.getElementById('tryon').addEventListener('click', (e) => {
75
- tfr.TryOn('5003-007-08')
76
- })
77
- })
78
- </script>
79
- </head>
180
+ // Add event listeners for product selection changes
181
+ const sizeSelect = document.querySelector('select[name="options[Size]"]')
182
+ const colorSelect = document.querySelector('select[name="options[Color]"]')
183
+
184
+ if (sizeSelect) {
185
+ sizeSelect.addEventListener('change', () => {
186
+ const newSku = getSku()
187
+ if (newSku && tfr) {
188
+ tfr.SetColorwaySizeAssetBySKU(newSku, false)
189
+ console.debug('SKU updated to:', newSku)
190
+ }
191
+ })
192
+ }
193
+ if (colorSelect) {
194
+ colorSelect.addEventListener('change', () => {
195
+ const newSku = getSku()
196
+ if (newSku && tfr) {
197
+ tfr.SetColorwaySizeAssetBySKU(newSku, false)
198
+ console.debug('SKU updated to:', newSku)
199
+ }
200
+ })
201
+ }
202
+ } catch (error) {
203
+ console.error(
204
+ `Error during window load event for The Fitting Room: ${error.message}. The functionality might be impacted or disabled.`,
205
+ )
206
+ }
207
+ })
208
+ </script>
209
+ </head>
210
+
211
+ <body>
212
+ <div class="demo-container">
213
+ <h1>TheFittingRoom Widget Demo</h1>
214
+ <p>This demo showcases a fully functioning widget with brand_id 1 and hardcoded SKUs.</p>
215
+
216
+ <div class="product-selector">
217
+ <h3>Product Options</h3>
218
+ <label for="size-select">Size:</label>
219
+ <select name="options[Size]" id="size-select">
220
+ <option value="">Select Size</option>
221
+ <option value="2">Size 2</option>
222
+ <option value="4">Size 4</option>
223
+ <option value="6">Size 6</option>
224
+ <option value="8">Size 8</option>
225
+ <option value="10">Size 10</option>
226
+ </select>
227
+
228
+ <label for="color-select">Color:</label>
229
+ <select name="options[Color]" id="color-select">
230
+ <option value="">Select Color</option>
231
+ <option value="BlackBandana">Black Bandana</option>
232
+ </select>
233
+ </div>
234
+
235
+ <div class="tfr-widget-container">
236
+ <h3>TheFittingRoom Widget</h3>
237
+ <div id="thefittingroom-modal"></div>
238
+ <div id="tfr-size-recommendation-main"></div>
239
+ <div id="tfr-vto"></div>
240
+ </div>
241
+
242
+ <!-- Hidden modal container for manual modal triggers -->
243
+ <div id="tfr-manual-modal" style="display: none"></div>
80
244
 
81
- <body>
82
245
  <div class="tfr-home-button-container">
83
246
  <button
84
- onclick="window.mm.Open(window.comps.ErrorModal({error: 'custom error message', onNavBack: window.onNavBack, onClose: window.onClose}))"
85
- >
247
+ onclick="window.mm.open(window.comps.ErrorModal({error: 'custom error message', onNavBack: window.onNavBack, onClose: window.onClose}))">
86
248
  Error Modal
87
249
  </button>
88
- <br />
89
- <button onclick="window.mm.Open(window.comps.ScanCodeModal())">Scan Code Modal</button>
90
- <br />
250
+ <button onclick="window.mm.open(window.comps.ScanCodeModal())">Scan Code Modal</button>
91
251
  <button
92
- onclick="window.mm.Open(window.comps.SignInModal({email:'email@mail.com', onSignIn: window.onSignIn('abc'), onNavForgotPassword: window.onNavForgotPassword('123'), onNavScanCode: window.onNavScanCode}))"
93
- >
252
+ onclick="window.mm.open(window.comps.SignInModal({email:'email@mail.com', onSignIn: window.onSignIn('abc'), onNavForgotPassword: window.onNavForgotPassword('123'), onNavScanCode: window.onNavScanCode}))">
94
253
  Sign In Modal
95
254
  </button>
96
- <br />
97
255
  <button
98
- onclick="window.mm.Open(window.comps.ForgotPasswordModal({email: 'email@mail.com', onNavSignIn: window.onNavSignIn('123'), onPasswordReset: window.onPasswordReset('123')}))"
99
- >
256
+ onclick="window.mm.open(window.comps.ForgotPasswordModal({email: 'email@mail.com', onNavSignIn: window.onNavSignIn('123'), onPasswordReset: window.onPasswordReset('123')}))">
100
257
  Forgot Password Modal
101
258
  </button>
102
- <br />
103
- <button onclick="window.mm.Open(window.comps.NoAvatarModal({}))">No Avatar Modal</button>
104
- <br />
105
- <button onclick="window.mm.Open(window.comps.LoadingAvatarModal({timeoutMS: 12000}))">
259
+ <button onclick="window.mm.open(window.comps.NoAvatarModal({}))">No Avatar Modal</button>
260
+ <button onclick="window.mm.open(window.comps.LoadingAvatarModal({timeoutMS: 12000}))">
106
261
  Loading Avatar Modal
107
262
  </button>
108
- <br />
109
263
  <button
110
- onclick="window.mm.Open(window.comps.SizeErrorModal({onNavBack: window.onNavBack, onClose: window.onClose, sizes: {recommended: 'large', avaliable: ['small', 'medium', 'large']}}))"
111
- >
264
+ onclick="window.mm.open(window.comps.SizeErrorModal({onNavBack: window.onNavBack, onClose: window.onClose, sizes: {recommended: 'large', avaliable: ['small', 'medium', 'large']}}))">
112
265
  Size Error Modal
113
266
  </button>
114
- <br />
115
- <button onclick="window.mm.Open(window.comps.ResetLinkModal({onNavSignIn: window.onNavSignIn('abc')}))">
267
+ <button onclick="window.mm.open(window.comps.ResetLinkModal({onNavSignIn: window.onNavSignIn('abc')}))">
116
268
  Reset Link Modal
117
269
  </button>
118
- <button id="tryon">Try On</button>
119
- <button id="signout">Sign Out</button>
120
270
  </div>
121
- <div id="tfr-manual-modal"></div>
122
- <div id="tfr-tryon-modal"></div>
123
- <input type="range" id="tfr-slider" />
124
- <img id="tfr-tryon-image" src="" />
125
- </body>
126
- </html>
271
+ </div>
272
+ </body>
273
+
274
+ </html>
package/package.json CHANGED
@@ -1,38 +1,33 @@
1
1
  {
2
2
  "name": "@thefittingroom/shop-ui",
3
- "version": "3.2.3",
3
+ "version": "4.1.0",
4
4
  "description": "the fitting room UI library",
5
5
  "type": "module",
6
- "main": "./dist/esm/index.js",
6
+ "main": "./dist/index.js",
7
7
  "scripts": {
8
8
  "clean": "rm -rf dist",
9
- "clean:all": "rm -rf dist build .rollup.cache",
10
- "build:prod": "npm run clean && NODE_ENV=prod rollup --config",
11
- "build:dev": "npm run clean && NODE_ENV=dev rollup --config",
12
- "watch:prod": "npm run clean && NODE_ENV=prod rollup --config -w",
13
- "watch:dev": "npm run clean && NODE_ENV=dev rollup --config -w",
14
- "serve": "live-server --host=localhost --port=3030 --cors",
15
- "pub": "npm run build:prod && npm publish --access public"
9
+ "clean:all": "rm -rf dist build",
10
+ "build:prod": "npm run clean && vite build --mode production",
11
+ "build:dev": "npm run clean && vite build --mode development",
12
+ "dev": "vite --mode development",
13
+ "watch:prod": "vite build --mode production --watch",
14
+ "watch:dev": "vite build --mode development --watch",
15
+ "serve": "vite preview",
16
+ "prune": "ts-prune"
16
17
  },
17
18
  "engines": {
18
19
  "node": ">=20"
19
20
  },
20
21
  "devDependencies": {
21
- "@rollup/plugin-node-resolve": "^16.0.1",
22
- "@rollup/plugin-terser": "^0.4.4",
23
- "@rollup/plugin-typescript": "^12.1.4",
24
- "@trivago/prettier-plugin-sort-imports": "^5.2.2",
25
- "live-server": "^1.2.0",
26
- "postcss": "^8.5.6",
22
+ "@biomejs/biome": "2.3.5",
23
+ "@trivago/prettier-plugin-sort-imports": "^6.0.0",
27
24
  "prettier": "^3.6.2",
28
- "rollup": "^4.18.1",
29
- "rollup-plugin-dotenv": "^0.5.1",
30
- "rollup-plugin-postcss": "^4.0.2",
31
- "ts-node": "^10.9.2",
32
- "tslib": "^2.6.3",
33
- "typescript": "^5.5.4"
25
+ "ts-prune": "^0.10.3",
26
+ "typescript": "^5.9.3",
27
+ "vite": "^7.2.2"
34
28
  },
35
29
  "dependencies": {
36
- "@thefittingroom/sdk": "2.0.8"
30
+ "dayjs": "^1.11.19",
31
+ "firebase": "^12.5.0"
37
32
  }
38
33
  }
package/vite.config.js ADDED
@@ -0,0 +1,39 @@
1
+ import { resolve } from 'path'
2
+ import { defineConfig } from 'vite'
3
+
4
+ const server = {
5
+ port: 5173,
6
+ host: true,
7
+ cors: true,
8
+ headers: {
9
+ 'Access-Control-Allow-Origin': '*',
10
+ 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
11
+ 'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
12
+ },
13
+ }
14
+
15
+ const lib = {
16
+ lib: {
17
+ entry: resolve('src/index.ts'),
18
+ name: 'TheFittingRoom',
19
+ fileName: 'index',
20
+ },
21
+ minify: false,
22
+ }
23
+
24
+ export default defineConfig(({ mode, command }) => {
25
+ if (command === 'serve') {
26
+ return {
27
+ server: {
28
+ ...server,
29
+ watch: { usePolling: true },
30
+ },
31
+ }
32
+ }
33
+
34
+ if (mode === 'production' || process.env.CI) {
35
+ return { build: lib, server }
36
+ }
37
+
38
+ return { build: { minify: false }, server }
39
+ })
package/.env.dev DELETED
@@ -1,2 +0,0 @@
1
- LANGUAGE_URL=https://assets.dev.thefittingroom.xyz/shop-sdk/${GITHUB_SHA_7}/languages
2
- ASSETS_URL=https://assets.dev.thefittingroom.xyz/shop-sdk/assets
package/.env.prod DELETED
@@ -1,2 +0,0 @@
1
- LANGUAGE_URL=https://assets.p.thefittingroom.xyz/shop-sdk/${GITHUB_REF}/languages
2
- ASSETS_URL=https://assets.p.thefittingroom.xyz/shop-sdk/assets
@@ -1,43 +0,0 @@
1
- import { L } from '../locale';
2
- const ErrorModal = (props) => {
3
- const { error } = props;
4
- const onNavBack = () => {
5
- props.onNavBack();
6
- };
7
- const onClose = () => {
8
- props.onClose();
9
- };
10
- const Hook = () => {
11
- var _a, _b;
12
- (_a = document.getElementById('tfr-back')) === null || _a === void 0 ? void 0 : _a.addEventListener('click', onNavBack);
13
- (_b = document.getElementById('tfr-close')) === null || _b === void 0 ? void 0 : _b.addEventListener('click', onClose);
14
- };
15
- const Unhook = () => {
16
- var _a, _b;
17
- (_a = document.getElementById('tfr-back')) === null || _a === void 0 ? void 0 : _a.removeEventListener('click', onNavBack);
18
- (_b = document.getElementById('tfr-close')) === null || _b === void 0 ? void 0 : _b.removeEventListener('click', onClose);
19
- };
20
- const Body = () => {
21
- if (!error) {
22
- console.error('ErrorModal: No error provided');
23
- }
24
- return `
25
- <div class="tfr-mt-15-p tfr-mb-13-p">
26
- <div tfr-element="true" class="tfr-title-font tfr-light-22-300 tfr-c-black">${error || L.SomethingWentWrong}</div>
27
- </div>
28
-
29
- <div class="tfr-t-a-center">
30
- <span id="tfr-back" tfr-element="true" class="tfr-body-font tfr-16-default tfr-c-black-o5 tfr-underline tfr-cursor tfr-mr-20">${L.ReturnToCatalogPage || 'Return to Catalog Page'}</span>
31
- <span id="tfr-close" tfr-element="true" class="tfr-body-font tfr-16-default tfr-c-black-o5 tfr-underline tfr-cursor" id="returnToSite">${L.ReturnToProductPage || 'Return to Product Page'}</span>
32
- </div>
33
- `;
34
- };
35
- return {
36
- Hook,
37
- Unhook,
38
- Body,
39
- useFullModalContent: true,
40
- };
41
- };
42
- export default ErrorModal;
43
- //# sourceMappingURL=ErrorModal.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ErrorModal.js","sourceRoot":"","sources":["../../../../src/components/Modals/ErrorModal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,WAAW,CAAA;AAE7B,MAAM,UAAU,GAAG,CAAC,KAAsB,EAAE,EAAE;IAC5C,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;IAEvB,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,KAAK,CAAC,SAAS,EAAE,CAAA;IACnB,CAAC,CAAA;IAED,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,KAAK,CAAC,OAAO,EAAE,CAAA;IACjB,CAAC,CAAA;IAED,MAAM,IAAI,GAAG,GAAG,EAAE;;QAChB,MAAA,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,0CAAE,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;QACzE,MAAA,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,0CAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC1E,CAAC,CAAA;IAED,MAAM,MAAM,GAAG,GAAG,EAAE;;QAClB,MAAA,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,0CAAE,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;QAC5E,MAAA,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,0CAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC7E,CAAC,CAAA;IAED,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAA;QAChD,CAAC;QACD,OAAO;;0FAGG,KAAK,IAAI,CAAC,CAAC,kBACb;;;;4IAKE,CAAC,CAAC,mBAAmB,IAAI,wBAC3B;qJAEE,CAAC,CAAC,mBAAmB,IAAI,wBAC3B;;SAEH,CAAA;IACP,CAAC,CAAA;IAED,OAAO;QACL,IAAI;QACJ,MAAM;QACN,IAAI;QACJ,mBAAmB,EAAE,IAAI;KAC1B,CAAA;AACH,CAAC,CAAA;AAED,eAAe,UAAU,CAAA","sourcesContent":["import { ErrorModalProps } from '../../types'\nimport { L } from '../locale'\n\nconst ErrorModal = (props: ErrorModalProps) => {\n const { error } = props\n\n const onNavBack = () => {\n props.onNavBack()\n }\n\n const onClose = () => {\n props.onClose()\n }\n\n const Hook = () => {\n document.getElementById('tfr-back')?.addEventListener('click', onNavBack)\n document.getElementById('tfr-close')?.addEventListener('click', onClose)\n }\n\n const Unhook = () => {\n document.getElementById('tfr-back')?.removeEventListener('click', onNavBack)\n document.getElementById('tfr-close')?.removeEventListener('click', onClose)\n }\n\n const Body = () => {\n if (!error) {\n console.error('ErrorModal: No error provided')\n }\n return `\n <div class=\"tfr-mt-15-p tfr-mb-13-p\">\n <div tfr-element=\"true\" class=\"tfr-title-font tfr-light-22-300 tfr-c-black\">${\n error || L.SomethingWentWrong\n }</div>\n </div>\n\n <div class=\"tfr-t-a-center\">\n <span id=\"tfr-back\" tfr-element=\"true\" class=\"tfr-body-font tfr-16-default tfr-c-black-o5 tfr-underline tfr-cursor tfr-mr-20\">${\n L.ReturnToCatalogPage || 'Return to Catalog Page'\n }</span>\n <span id=\"tfr-close\" tfr-element=\"true\" class=\"tfr-body-font tfr-16-default tfr-c-black-o5 tfr-underline tfr-cursor\" id=\"returnToSite\">${\n L.ReturnToProductPage || 'Return to Product Page'\n }</span>\n </div>\n `\n }\n\n return {\n Hook,\n Unhook,\n Body,\n useFullModalContent: true,\n }\n}\n\nexport default ErrorModal\n"]}
@@ -1,106 +0,0 @@
1
- import { tfrDoor } from '../svgs';
2
- const FitModal = (props) => {
3
- const imageBaseUrl = 'https://assets.dev.thefittingroom.xyz/images/';
4
- const onSignInNav = () => props.onSignInNav();
5
- const Hook = () => {
6
- document.getElementById('cta-link').addEventListener('click', onSignInNav);
7
- };
8
- const Unhook = () => {
9
- document.getElementById('cta-link').removeEventListener('click', onSignInNav);
10
- };
11
- const Body = () => {
12
- return `
13
- <div>
14
- <div id="fit-title">Fit Scale</div>
15
-
16
- <div id="fit-line-container">
17
- <div id="fit-line-text-container">
18
- <div class="fit-line-item mobile-hidden">Too Tight</div>
19
-
20
- <div class="fit-line-item">
21
- <div>Tight <span class="light-text">or</span><br /> More fitted</div>
22
-
23
- <div class="desktop-hidden margin-top-10">Too Tight</div>
24
- </div>
25
-
26
- <div class="fit-line-item fit-line-item-green">Slightly tight <br /><span class="light-text">or</span> Fitted</div>
27
- <div class="fit-line-item fit-line-item-green">Perfect Fit</div>
28
- <div class="fit-line-item fit-line-item-green">Slightly loose <br /><span class="light-text">or</span> Less fitted</div>
29
-
30
- <div class="fit-line-item">
31
- <div>Loose <span class="light-text">or</span><br /> Not fitted</div>
32
-
33
- <div class="desktop-hidden margin-top-10">Oversized</div>
34
- </div>
35
-
36
- <div class="fit-line-item mobile-hidden">Oversized</div>
37
- </div>
38
-
39
- <div id="fit-line">
40
- <div id="fit-line-1" class="mobile-hidden">&nbsp;</div>
41
- <div id="fit-line-2">&nbsp;</div>
42
- <div id="fit-line-3">&nbsp;</div>
43
- <div id="fit-line-4">&nbsp;</div>
44
- <div id="fit-line-5">&nbsp;</div>
45
- <div id="fit-line-6">&nbsp;</div>
46
- <div id="fit-line-7" class="mobile-hidden">&nbsp;</div>
47
- </div>
48
-
49
- <div id="fit-line-texts">
50
- <div>Poor Fit</div>
51
- <div>Acceptable Fit</div>
52
- <div>Poor Fit</div>
53
- </div>
54
- </div>
55
-
56
- <div id="fit-subtitle-mobile" class="desktop-hidden">Measurement&nbsp;Points</div>
57
-
58
- <div id="fit-outline-container">
59
- <div id="fit-outline-inner-left">
60
- <div class="fit-outline-line-text fit-outline-line-p-waist-text">Pant&nbsp;Waist</div>
61
- <div class="fit-outline-line-text fit-outline-line-thigh-text">Thigh</div>
62
- </div>
63
-
64
- <div id="fit-outline-inner">
65
- <div class="fit-outline-line fit-outline-line-chest"></div>
66
- <div class="fit-outline-line fit-outline-line-n-waist"></div>
67
- <div class="fit-outline-line fit-outline-line-p-waist"></div>
68
- <div class="fit-outline-line fit-outline-line-h-hip"></div>
69
- <div class="fit-outline-line fit-outline-line-l-hip"></div>
70
- <div class="fit-outline-line fit-outline-line-thigh-l"></div>
71
- <div class="fit-outline-line fit-outline-line-thigh-r"></div>
72
-
73
- <img id="tfr-fit-outline-img" src="${imageBaseUrl}fit-outline.png" />
74
- </div>
75
-
76
- <div id="fit-outline-inner-right">
77
- <div id="fit-subtitle" class="mobile-hidden">Measurement&nbsp;Points</div>
78
-
79
- <div class="fit-outline-line-text fit-outline-line-chest-text">Chest/Bust</div>
80
- <div class="fit-outline-line-text fit-outline-line-n-waist-text">Natural&nbsp;Waist</div>
81
- <div class="fit-outline-line-text fit-outline-line-h-hip-text">High&nbsp;Hip</div>
82
- <div class="fit-outline-line-text fit-outline-line-l-hip-text">Low&nbsp;Hip</div>
83
- </div>
84
- </div>
85
- </div>
86
-
87
- <div id="cta-section">
88
- <div id="cta-link">Sign Up or Login</div>
89
-
90
- <div class="powered-by">
91
- <div>Powered by</div>
92
- <div class="tfr-powered-by-logo">${tfrDoor}</div>
93
- <div class="tfr-powered-by-text-bold">The Fitting Room</div>
94
- </div>
95
- </div>
96
- `;
97
- };
98
- return {
99
- Hook,
100
- Unhook,
101
- Body,
102
- useFullModalContent: false,
103
- };
104
- };
105
- export default FitModal;
106
- //# sourceMappingURL=FitModal.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FitModal.js","sourceRoot":"","sources":["../../../../src/components/Modals/FitModal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEjC,MAAM,QAAQ,GAAG,CAAC,KAAoB,EAAgB,EAAE;IACtD,MAAM,YAAY,GAAG,+CAA+C,CAAA;IACpE,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAA;IAE7C,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;IAC5E,CAAC,CAAA;IAED,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;IAC/E,CAAC,CAAA;IAED,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iDA6DsC,YAAY;;;;;;;;;;;;;;;;;;;6CAmBhB,OAAO;;;;KAI/C,CAAA;IACH,CAAC,CAAA;IAED,OAAO;QACL,IAAI;QACJ,MAAM;QACN,IAAI;QACJ,mBAAmB,EAAE,KAAK;KAC3B,CAAA;AACH,CAAC,CAAA;AAED,eAAe,QAAQ,CAAA","sourcesContent":["import { FitModalProps, ModalContent } from '../../types'\nimport { tfrDoor } from '../svgs'\n\nconst FitModal = (props: FitModalProps): ModalContent => {\n const imageBaseUrl = 'https://assets.dev.thefittingroom.xyz/images/'\n const onSignInNav = () => props.onSignInNav()\n\n const Hook = () => {\n document.getElementById('cta-link').addEventListener('click', onSignInNav)\n }\n\n const Unhook = () => {\n document.getElementById('cta-link').removeEventListener('click', onSignInNav)\n }\n\n const Body = () => {\n return `\n <div>\n <div id=\"fit-title\">Fit Scale</div>\n\n <div id=\"fit-line-container\">\n <div id=\"fit-line-text-container\">\n <div class=\"fit-line-item mobile-hidden\">Too Tight</div>\n\n <div class=\"fit-line-item\">\n <div>Tight <span class=\"light-text\">or</span><br /> More fitted</div>\n\n <div class=\"desktop-hidden margin-top-10\">Too Tight</div>\n </div>\n\n <div class=\"fit-line-item fit-line-item-green\">Slightly tight <br /><span class=\"light-text\">or</span> Fitted</div>\n <div class=\"fit-line-item fit-line-item-green\">Perfect Fit</div>\n <div class=\"fit-line-item fit-line-item-green\">Slightly loose <br /><span class=\"light-text\">or</span> Less fitted</div>\n\n <div class=\"fit-line-item\">\n <div>Loose <span class=\"light-text\">or</span><br /> Not fitted</div>\n\n <div class=\"desktop-hidden margin-top-10\">Oversized</div>\n </div>\n\n <div class=\"fit-line-item mobile-hidden\">Oversized</div>\n </div>\n\n <div id=\"fit-line\">\n <div id=\"fit-line-1\" class=\"mobile-hidden\">&nbsp;</div>\n <div id=\"fit-line-2\">&nbsp;</div>\n <div id=\"fit-line-3\">&nbsp;</div>\n <div id=\"fit-line-4\">&nbsp;</div>\n <div id=\"fit-line-5\">&nbsp;</div>\n <div id=\"fit-line-6\">&nbsp;</div>\n <div id=\"fit-line-7\" class=\"mobile-hidden\">&nbsp;</div>\n </div>\n\n <div id=\"fit-line-texts\">\n <div>Poor Fit</div>\n <div>Acceptable Fit</div>\n <div>Poor Fit</div>\n </div>\n </div>\n\n <div id=\"fit-subtitle-mobile\" class=\"desktop-hidden\">Measurement&nbsp;Points</div>\n\n <div id=\"fit-outline-container\">\n <div id=\"fit-outline-inner-left\">\n <div class=\"fit-outline-line-text fit-outline-line-p-waist-text\">Pant&nbsp;Waist</div>\n <div class=\"fit-outline-line-text fit-outline-line-thigh-text\">Thigh</div>\n </div>\n\n <div id=\"fit-outline-inner\">\n <div class=\"fit-outline-line fit-outline-line-chest\"></div>\n <div class=\"fit-outline-line fit-outline-line-n-waist\"></div>\n <div class=\"fit-outline-line fit-outline-line-p-waist\"></div>\n <div class=\"fit-outline-line fit-outline-line-h-hip\"></div>\n <div class=\"fit-outline-line fit-outline-line-l-hip\"></div>\n <div class=\"fit-outline-line fit-outline-line-thigh-l\"></div>\n <div class=\"fit-outline-line fit-outline-line-thigh-r\"></div>\n\n <img id=\"tfr-fit-outline-img\" src=\"${imageBaseUrl}fit-outline.png\" />\n </div>\n\n <div id=\"fit-outline-inner-right\">\n <div id=\"fit-subtitle\" class=\"mobile-hidden\">Measurement&nbsp;Points</div>\n\n <div class=\"fit-outline-line-text fit-outline-line-chest-text\">Chest/Bust</div>\n <div class=\"fit-outline-line-text fit-outline-line-n-waist-text\">Natural&nbsp;Waist</div>\n <div class=\"fit-outline-line-text fit-outline-line-h-hip-text\">High&nbsp;Hip</div>\n <div class=\"fit-outline-line-text fit-outline-line-l-hip-text\">Low&nbsp;Hip</div>\n </div>\n </div>\n </div>\n\n <div id=\"cta-section\">\n <div id=\"cta-link\">Sign Up or Login</div>\n\n <div class=\"powered-by\">\n <div>Powered by</div>\n <div class=\"tfr-powered-by-logo\">${tfrDoor}</div>\n <div class=\"tfr-powered-by-text-bold\">The Fitting Room</div>\n </div>\n </div>\n `\n }\n\n return {\n Hook,\n Unhook,\n Body,\n useFullModalContent: false,\n }\n}\n\nexport default FitModal\n"]}