@jotul/jotul-widgets 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/JotulWidget.css +253 -0
- package/dist/JotulWidget.d.ts +1 -0
- package/dist/JotulWidget.js +61 -13
- package/package.json +5 -3
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
.jwi-root {
|
|
2
|
+
width: 100%;
|
|
3
|
+
color: #111111;
|
|
4
|
+
font-family:
|
|
5
|
+
Inter,
|
|
6
|
+
ui-sans-serif,
|
|
7
|
+
system-ui,
|
|
8
|
+
-apple-system,
|
|
9
|
+
BlinkMacSystemFont,
|
|
10
|
+
"Segoe UI",
|
|
11
|
+
sans-serif;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.jwi-shell {
|
|
15
|
+
width: 100%;
|
|
16
|
+
border: 1px solid #e9e5dc;
|
|
17
|
+
border-radius: 32px;
|
|
18
|
+
background: #f8f6f2;
|
|
19
|
+
padding: 16px;
|
|
20
|
+
box-shadow: 0 6px 20px rgba(17, 17, 17, 0.04);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.jwi-searchBox {
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
border: 1px solid #d8d2c7;
|
|
26
|
+
border-radius: 24px;
|
|
27
|
+
background: #ffffff;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.jwi-searchRow {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.jwi-inputWrap {
|
|
36
|
+
display: flex;
|
|
37
|
+
min-width: 0;
|
|
38
|
+
flex: 1;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: 12px;
|
|
41
|
+
padding: 16px 20px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.jwi-pin {
|
|
45
|
+
display: inline-flex;
|
|
46
|
+
flex-shrink: 0;
|
|
47
|
+
color: #000000;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.jwi-input {
|
|
51
|
+
width: 100%;
|
|
52
|
+
border: 0;
|
|
53
|
+
background: transparent;
|
|
54
|
+
color: #111111;
|
|
55
|
+
font-size: 16px;
|
|
56
|
+
line-height: 1.4;
|
|
57
|
+
outline: none;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.jwi-input::placeholder {
|
|
61
|
+
color: #767676;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.jwi-findButton {
|
|
65
|
+
min-height: 64px;
|
|
66
|
+
border: 0;
|
|
67
|
+
background: #000000;
|
|
68
|
+
padding: 0 32px;
|
|
69
|
+
color: #ffffff;
|
|
70
|
+
font-size: 16px;
|
|
71
|
+
font-weight: 500;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.jwi-findButton:hover {
|
|
76
|
+
background: #1f1f1f;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.jwi-findButton:disabled {
|
|
80
|
+
cursor: not-allowed;
|
|
81
|
+
background: #444444;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.jwi-error {
|
|
85
|
+
margin-top: 16px;
|
|
86
|
+
border: 1px solid #f0c7c2;
|
|
87
|
+
border-radius: 16px;
|
|
88
|
+
background: #fff3f1;
|
|
89
|
+
padding: 12px 16px;
|
|
90
|
+
color: #8f2d21;
|
|
91
|
+
font-size: 14px;
|
|
92
|
+
line-height: 1.4;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.jwi-results {
|
|
96
|
+
margin-top: 20px;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.jwi-resultsHeader {
|
|
100
|
+
border-bottom: 1px solid #e6e1d7;
|
|
101
|
+
padding-bottom: 16px;
|
|
102
|
+
color: #111111;
|
|
103
|
+
font-size: 16px;
|
|
104
|
+
font-weight: 500;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.jwi-resultsList {
|
|
108
|
+
margin-top: 20px;
|
|
109
|
+
display: flex;
|
|
110
|
+
max-height: 700px;
|
|
111
|
+
flex-direction: column;
|
|
112
|
+
gap: 16px;
|
|
113
|
+
overflow-y: auto;
|
|
114
|
+
padding-right: 4px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.jwi-card {
|
|
118
|
+
border: 1px solid #e6e1d7;
|
|
119
|
+
border-radius: 24px;
|
|
120
|
+
background: #ffffff;
|
|
121
|
+
padding: 20px;
|
|
122
|
+
box-shadow: 0 1px 2px rgba(17, 17, 17, 0.03);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.jwi-cardTop {
|
|
126
|
+
display: flex;
|
|
127
|
+
align-items: flex-start;
|
|
128
|
+
justify-content: space-between;
|
|
129
|
+
gap: 16px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.jwi-cardTitleWrap {
|
|
133
|
+
max-width: 70%;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.jwi-cardTitle {
|
|
137
|
+
margin: 0;
|
|
138
|
+
color: #111111;
|
|
139
|
+
font-size: 22px;
|
|
140
|
+
font-weight: 600;
|
|
141
|
+
line-height: 1.15;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.jwi-distance {
|
|
145
|
+
border-radius: 9999px;
|
|
146
|
+
background: #fbf3db;
|
|
147
|
+
padding: 8px 16px;
|
|
148
|
+
color: #111111;
|
|
149
|
+
font-size: 20px;
|
|
150
|
+
font-weight: 500;
|
|
151
|
+
line-height: 1;
|
|
152
|
+
white-space: nowrap;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.jwi-address {
|
|
156
|
+
margin-top: 20px;
|
|
157
|
+
display: flex;
|
|
158
|
+
flex-direction: column;
|
|
159
|
+
gap: 4px;
|
|
160
|
+
color: #111111;
|
|
161
|
+
font-size: 18px;
|
|
162
|
+
line-height: 1.15;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.jwi-cardActions {
|
|
166
|
+
margin-top: 24px;
|
|
167
|
+
display: flex;
|
|
168
|
+
flex-direction: column;
|
|
169
|
+
gap: 16px;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.jwi-cta {
|
|
173
|
+
display: inline-flex;
|
|
174
|
+
min-height: 70px;
|
|
175
|
+
width: 100%;
|
|
176
|
+
align-items: center;
|
|
177
|
+
justify-content: space-between;
|
|
178
|
+
border: 0;
|
|
179
|
+
border-radius: 16px;
|
|
180
|
+
background: #ef2b18;
|
|
181
|
+
padding: 0 28px;
|
|
182
|
+
color: #ffffff;
|
|
183
|
+
font-size: 18px;
|
|
184
|
+
font-weight: 500;
|
|
185
|
+
cursor: pointer;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.jwi-cta:hover {
|
|
189
|
+
background: #d92817;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.jwi-phoneLink {
|
|
193
|
+
display: inline-flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
gap: 12px;
|
|
196
|
+
color: #111111;
|
|
197
|
+
font-size: 18px;
|
|
198
|
+
font-weight: 500;
|
|
199
|
+
text-decoration: none;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.jwi-phoneLink:hover {
|
|
203
|
+
text-decoration: underline;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.jwi-icon16 {
|
|
207
|
+
width: 16px;
|
|
208
|
+
height: 16px;
|
|
209
|
+
flex-shrink: 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.jwi-icon22 {
|
|
213
|
+
width: 22px;
|
|
214
|
+
height: 22px;
|
|
215
|
+
flex-shrink: 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.jwi-loading,
|
|
219
|
+
.jwi-message {
|
|
220
|
+
color: #111111;
|
|
221
|
+
font-family:
|
|
222
|
+
Inter,
|
|
223
|
+
ui-sans-serif,
|
|
224
|
+
system-ui,
|
|
225
|
+
-apple-system,
|
|
226
|
+
BlinkMacSystemFont,
|
|
227
|
+
"Segoe UI",
|
|
228
|
+
sans-serif;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@media (min-width: 768px) {
|
|
232
|
+
.jwi-shell {
|
|
233
|
+
padding: 24px;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.jwi-searchRow {
|
|
237
|
+
flex-direction: row;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.jwi-inputWrap {
|
|
241
|
+
padding: 16px 24px;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.jwi-cardActions {
|
|
245
|
+
flex-direction: row;
|
|
246
|
+
align-items: center;
|
|
247
|
+
justify-content: space-between;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.jwi-cta {
|
|
251
|
+
width: 390px;
|
|
252
|
+
}
|
|
253
|
+
}
|
package/dist/JotulWidget.d.ts
CHANGED
package/dist/JotulWidget.js
CHANGED
|
@@ -1,11 +1,49 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import './JotulWidget.css';
|
|
3
4
|
import { useEffect, useMemo, useState } from 'react';
|
|
4
5
|
const VALID_WIDGET_TYPES = [
|
|
5
6
|
'productPage',
|
|
6
7
|
'dealerFinder',
|
|
7
8
|
'warrantyForm',
|
|
8
9
|
];
|
|
10
|
+
function PinIcon() {
|
|
11
|
+
return (_jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", className: "jwi-icon16", children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M2.70895 0.833313H5.20957C5.41781 0.833313 5.60425 0.962386 5.67756 1.15731L6.64785 3.73723C6.68 3.82263 6.68813 3.91519 6.6714 4.00488L6.1852 6.61285C6.7828 8.01818 7.76987 8.96258 9.40693 9.80971L11.9836 9.31045C12.0751 9.29271 12.1697 9.30091 12.2567 9.33411L14.8446 10.3202C15.0385 10.3941 15.1665 10.58 15.1665 10.7874V13.177C15.1665 14.2606 14.2117 15.14 13.0949 14.897C11.0592 14.454 7.28767 13.3282 4.64633 10.6868C2.11624 8.15678 1.26855 4.66166 0.983187 2.77244C0.820367 1.69446 1.6849 0.833313 2.70895 0.833313Z", fill: "currentColor" }) }));
|
|
12
|
+
}
|
|
13
|
+
function ArrowRightIcon() {
|
|
14
|
+
return (_jsx("svg", { width: "22", height: "22", viewBox: "0 0 22 22", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", className: "jwi-icon22", children: _jsx("path", { d: "M2.75 11L19.25 11M19.25 11L11.4583 3.20836M19.25 11L11.4583 18.7917", stroke: "currentColor", strokeWidth: "2.08333", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
15
|
+
}
|
|
16
|
+
function TelephoneIcon() {
|
|
17
|
+
return (_jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", className: "jwi-icon16", children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M2.70895 0.833313H5.20957C5.41781 0.833313 5.60425 0.962386 5.67756 1.15731L6.64785 3.73723C6.68 3.82263 6.68813 3.91519 6.6714 4.00488L6.1852 6.61285C6.7828 8.01818 7.76987 8.96258 9.40693 9.80971L11.9836 9.31045C12.0751 9.29271 12.1697 9.30091 12.2567 9.33411L14.8446 10.3202C15.0385 10.3941 15.1665 10.58 15.1665 10.7874V13.177C15.1665 14.2606 14.2117 15.14 13.0949 14.897C11.0592 14.454 7.28767 13.3282 4.64633 10.6868C2.11624 8.15678 1.26855 4.66166 0.983187 2.77244C0.820367 1.69446 1.6849 0.833313 2.70895 0.833313Z", fill: "currentColor" }) }));
|
|
18
|
+
}
|
|
19
|
+
function asText(value) {
|
|
20
|
+
return typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
21
|
+
}
|
|
22
|
+
function asNumber(value) {
|
|
23
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
24
|
+
}
|
|
25
|
+
function formatDistance(dealer) {
|
|
26
|
+
const distanceKm = asNumber(dealer.distanceKm);
|
|
27
|
+
if (distanceKm !== null) {
|
|
28
|
+
return `${Math.round(distanceKm)} km`;
|
|
29
|
+
}
|
|
30
|
+
const postalDistance = asNumber(dealer.postalDistance);
|
|
31
|
+
if (postalDistance !== null) {
|
|
32
|
+
return `${Math.round(postalDistance)} km`;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function getDealerKey(dealer, index) {
|
|
37
|
+
return String(dealer.dealerId ?? dealer.name ?? index);
|
|
38
|
+
}
|
|
39
|
+
function getDealerName(dealer) {
|
|
40
|
+
return asText(dealer.name) ?? asText(dealer.dealerId) ?? 'Unknown dealer';
|
|
41
|
+
}
|
|
42
|
+
function getDealerAddressLines(dealer) {
|
|
43
|
+
const address = asText(dealer.address);
|
|
44
|
+
const postalCode = asText(dealer.postalCode);
|
|
45
|
+
return [address, postalCode].filter((value) => Boolean(value));
|
|
46
|
+
}
|
|
9
47
|
export async function checkWidgetAuthorization(options) {
|
|
10
48
|
const endpoint = options?.endpoint ?? '/api/jotul/widget';
|
|
11
49
|
const fetcher = options?.fetcher ?? fetch;
|
|
@@ -107,25 +145,35 @@ export function JotulWidget({ type, endpoint = '/api/jotul/widget', className, }
|
|
|
107
145
|
return 'typeReady';
|
|
108
146
|
}, [type]);
|
|
109
147
|
if (isLoading) {
|
|
110
|
-
return _jsx("div", { className: className, children: "Loading JotulWidget\u2026" });
|
|
148
|
+
return _jsx("div", { className: className ? `jwi-loading ${className}` : 'jwi-loading', children: "Loading JotulWidget\u2026" });
|
|
111
149
|
}
|
|
112
150
|
if (!auth?.ok || !auth.authorized) {
|
|
113
|
-
return (_jsxs("div", { className: className, children: ["JotulWidget auth failed: ", auth?.error ?? 'Unknown authorization error'] }));
|
|
151
|
+
return (_jsxs("div", { className: className ? `jwi-message ${className}` : 'jwi-message', children: ["JotulWidget auth failed: ", auth?.error ?? 'Unknown authorization error'] }));
|
|
114
152
|
}
|
|
115
153
|
if (typeState === 'typeMissing') {
|
|
116
|
-
return _jsx("div", { className: className, children: "JotulWidget type missing" });
|
|
154
|
+
return _jsx("div", { className: className ? `jwi-message ${className}` : 'jwi-message', children: "JotulWidget type missing" });
|
|
117
155
|
}
|
|
118
156
|
if (typeState === 'typeInvalid') {
|
|
119
|
-
return _jsx("div", { className: className, children: "Invalid widget type" });
|
|
157
|
+
return _jsx("div", { className: className ? `jwi-message ${className}` : 'jwi-message', children: "Invalid widget type" });
|
|
120
158
|
}
|
|
121
159
|
if (type === 'productPage') {
|
|
122
|
-
const dealers = searchResult?.dealers ?? [];
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
160
|
+
const dealers = (searchResult?.dealers ?? []);
|
|
161
|
+
const canSearch = postalCode.trim().length > 0;
|
|
162
|
+
const total = searchResult?.total ?? dealers.length;
|
|
163
|
+
return (_jsx("div", { className: className ? `jwi-root ${className}` : 'jwi-root', children: _jsxs("div", { className: "jwi-shell", children: [_jsx("div", { className: "jwi-searchBox", children: _jsxs("div", { className: "jwi-searchRow", children: [_jsxs("div", { className: "jwi-inputWrap", children: [_jsx("span", { className: "jwi-pin", children: _jsx(PinIcon, {}) }), _jsx("input", { type: "text", inputMode: "numeric", autoComplete: "postal-code", pattern: "[0-9]*", maxLength: 10, value: postalCode, onChange: (event) => {
|
|
164
|
+
const next = event.target.value.replace(/\D+/g, '');
|
|
165
|
+
setPostalCode(next);
|
|
166
|
+
}, placeholder: "Enter postcode", className: "jwi-input" })] }), _jsx("button", { type: "button", disabled: isSearching || !canSearch, onClick: async () => {
|
|
167
|
+
setIsSearching(true);
|
|
168
|
+
const result = await searchDealersByPostalCode(postalCode, { endpoint });
|
|
169
|
+
setSearchResult(result);
|
|
170
|
+
setIsSearching(false);
|
|
171
|
+
}, className: "jwi-findButton", children: isSearching ? 'Finding...' : 'Find' })] }) }), searchResult?.ok === false && (_jsx("div", { className: "jwi-error", children: searchResult.error ?? 'Unknown widget error' })), searchResult?.ok && (_jsxs("div", { className: "jwi-results", children: [_jsxs("div", { className: "jwi-resultsHeader", children: [total, " dealers near you"] }), _jsx("div", { className: "jwi-resultsList", children: dealers.map((dealer, index) => {
|
|
172
|
+
const addressLines = getDealerAddressLines(dealer);
|
|
173
|
+
const phone = asText(dealer.phone);
|
|
174
|
+
const distance = formatDistance(dealer);
|
|
175
|
+
return (_jsxs("div", { className: "jwi-card", children: [_jsxs("div", { className: "jwi-cardTop", children: [_jsx("div", { className: "jwi-cardTitleWrap", children: _jsx("h3", { className: "jwi-cardTitle", children: getDealerName(dealer) }) }), distance && (_jsx("div", { className: "jwi-distance", children: distance }))] }), addressLines.length > 0 && (_jsx("div", { className: "jwi-address", children: addressLines.map((line) => (_jsx("div", { children: line }, line))) })), _jsxs("div", { className: "jwi-cardActions", children: [_jsxs("button", { type: "button", className: "jwi-cta", children: [_jsx("span", { children: "Send foresporsel" }), _jsx(ArrowRightIcon, {})] }), phone && (_jsxs("a", { href: `tel:${phone.replace(/\s+/g, '')}`, className: "jwi-phoneLink", children: [_jsx(TelephoneIcon, {}), _jsx("span", { children: phone })] }))] })] }, getDealerKey(dealer, index)));
|
|
176
|
+
}) })] }))] }) }));
|
|
177
|
+
}
|
|
178
|
+
return _jsx("div", { className: className ? `jwi-message ${className}` : 'jwi-message', children: renderReadyState(type) });
|
|
131
179
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jotul/jotul-widgets",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
|
-
"sideEffects":
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"**/*.css"
|
|
8
|
+
],
|
|
7
9
|
"files": [
|
|
8
10
|
"dist",
|
|
9
11
|
"README.md"
|
|
@@ -17,7 +19,7 @@
|
|
|
17
19
|
}
|
|
18
20
|
},
|
|
19
21
|
"scripts": {
|
|
20
|
-
"build": "tsc -p tsconfig.build.json",
|
|
22
|
+
"build": "tsc -p tsconfig.build.json && cp src/JotulWidget.css dist/JotulWidget.css",
|
|
21
23
|
"clean": "rm -rf dist",
|
|
22
24
|
"prepublishOnly": "npm run clean && npm run build"
|
|
23
25
|
},
|