@namphuongtechnologi/np-hub 0.1.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.
- package/LICENSE +21 -0
- package/README.md +276 -0
- package/dist/chunk-ZZ63ZHC7.js +612 -0
- package/dist/chunk-ZZ63ZHC7.js.map +1 -0
- package/dist/index.cjs +640 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +89 -0
- package/dist/index.d.ts +89 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/np-hub.min.global.js +802 -0
- package/dist/register.cjs +636 -0
- package/dist/register.cjs.map +1 -0
- package/dist/register.d.cts +3 -0
- package/dist/register.d.ts +3 -0
- package/dist/register.js +7 -0
- package/dist/register.js.map +1 -0
- package/docs/DEVELOPER_GUIDE.md +91 -0
- package/docs/PUBLIC_RELEASE.md +84 -0
- package/docs/USAGE_STATIC_REACT.md +216 -0
- package/package.json +56 -0
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
// src/core/config/endpoints.ts
|
|
2
|
+
var PROD_API_URL = "https://namphuong-api.azurewebsites.net";
|
|
3
|
+
var DEV_API_URL = "https://namphuong-api-dev.azurewebsites.net";
|
|
4
|
+
function resolveBaseUrl(input) {
|
|
5
|
+
return input.isDev ? DEV_API_URL : PROD_API_URL;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// src/core/validation/request-validator.ts
|
|
9
|
+
function validateWidgetConfig(config) {
|
|
10
|
+
if (!config.projectId || config.projectId.trim().length === 0) {
|
|
11
|
+
throw new Error("projectId is required.");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function validateUser(user) {
|
|
15
|
+
if (!user.name?.trim()) {
|
|
16
|
+
throw new Error("user.name is required.");
|
|
17
|
+
}
|
|
18
|
+
if (!user.email?.trim()) {
|
|
19
|
+
throw new Error("user.email is required.");
|
|
20
|
+
}
|
|
21
|
+
if (!user.phoneNumber?.trim()) {
|
|
22
|
+
throw new Error("user.phoneNumber is required.");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function validateSubmission(input) {
|
|
26
|
+
if (!input.content?.trim()) {
|
|
27
|
+
throw new Error("Content is required.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/services/api/http-client.ts
|
|
32
|
+
async function postFormData(url, body) {
|
|
33
|
+
const response = await fetch(url, {
|
|
34
|
+
method: "POST",
|
|
35
|
+
body
|
|
36
|
+
});
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
const message = await response.text();
|
|
39
|
+
throw new Error(`Request failed (${response.status}): ${message}`);
|
|
40
|
+
}
|
|
41
|
+
return await response.json();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/services/api/support-api.ts
|
|
45
|
+
async function createSupportRequest(baseUrl, formData) {
|
|
46
|
+
const endpoint = `${baseUrl.replace(/\/$/, "")}/api/supportcenter/create-request-anonymous`;
|
|
47
|
+
return postFormData(endpoint, formData);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/component/events/widget-events.ts
|
|
51
|
+
var WIDGET_EVENTS = {
|
|
52
|
+
OPEN: "np-hub-open",
|
|
53
|
+
CLOSE: "np-hub-close",
|
|
54
|
+
SUBMIT_SUCCESS: "np-hub-submit-success",
|
|
55
|
+
SUBMIT_ERROR: "np-hub-submit-error"
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/component/assets/np-support-logo.png
|
|
59
|
+
var np_support_logo_default = "data:image/png;base64,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";
|
|
60
|
+
|
|
61
|
+
// src/component/support-widget.styles.css
|
|
62
|
+
var support_widget_styles_default = '@import url("https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap");\n\n:host {\n --np-primary: #003c82;\n --np-primary-dark: #002a5c;\n --np-primary-soft: rgba(0, 60, 130, 0.08);\n --np-border: #e2e8f0;\n --np-text: #0f172a;\n --np-text-muted: #64748b;\n font-family: "Outfit", sans-serif;\n display: block;\n position: fixed;\n right: 20px;\n bottom: 20px;\n z-index: 10000;\n}\n\n.launcher {\n width: var(--np-hub-width, 72px);\n height: var(--np-hub-height, 72px);\n border: none;\n border-radius: 50%;\n cursor: grab;\n box-shadow: 0 8px 28px rgba(0, 60, 130, 0.2);\n background-color: #ffffff;\n background-image: var(--np-hub-icon);\n background-position: center;\n background-repeat: no-repeat;\n background-size: 75%;\n transition:\n transform 0.2s ease,\n box-shadow 0.2s ease;\n}\n\n.launcher:hover {\n transform: scale(1.05);\n box-shadow: 0 12px 32px rgba(0, 60, 130, 0.3);\n}\n\n.launcher:active {\n cursor: grabbing;\n}\n\n.modal {\n position: fixed;\n inset: 0;\n background: rgba(15, 23, 42, 0.55);\n backdrop-filter: blur(6px);\n display: none;\n align-items: center;\n justify-content: center;\n padding: 16px;\n opacity: 0;\n transition: opacity 0.25s ease-out;\n}\n\n.modal.show {\n display: flex;\n opacity: 1;\n}\n\n.dialog {\n width: min(540px, 100%);\n max-height: calc(100vh - 32px);\n overflow-y: auto;\n background: #ffffff;\n border-radius: 20px;\n box-shadow: 0 24px 60px rgba(15, 23, 42, 0.22);\n padding: 28px 32px 32px;\n box-sizing: border-box;\n position: relative;\n transform: translateY(24px) scale(0.98);\n transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.modal.show .dialog {\n transform: translateY(0) scale(1);\n}\n\n.dialog::-webkit-scrollbar {\n width: 8px;\n}\n\n.dialog::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 8px;\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: center;\n padding-bottom: 18px;\n margin-bottom: 22px;\n border-bottom: 1px solid var(--np-border);\n position: relative;\n}\n\n.title {\n margin: 0;\n font-size: 22px;\n font-weight: 700;\n color: var(--np-primary);\n text-align: center;\n letter-spacing: -0.01em;\n}\n\n.close-btn {\n border: none;\n background: #f1f5f9;\n color: #64748b;\n font-size: 20px;\n line-height: 1;\n cursor: pointer;\n position: absolute;\n right: 0;\n top: 0;\n bottom: 18px;\n margin: auto 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n transition:\n background 0.15s ease,\n color 0.15s ease,\n transform 0.15s ease;\n}\n\n.close-btn:hover {\n background: #e2e8f0;\n color: #0f172a;\n transform: rotate(90deg);\n}\n\n.form-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 18px;\n}\n\n.field {\n display: flex;\n flex-direction: column;\n gap: 7px;\n}\n\n.field.full {\n grid-column: 1 / -1;\n}\n\nlabel {\n font-size: 13.5px;\n font-weight: 600;\n color: #334155;\n}\n\n.required {\n color: #ef4444;\n margin-right: 3px;\n}\n\ninput,\ntextarea {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid #d5dde7;\n border-radius: 10px;\n font-size: 14px;\n padding: 12px 14px;\n color: var(--np-text);\n outline: none;\n font-family: inherit;\n background: #fbfcfe;\n transition:\n border-color 0.15s ease,\n box-shadow 0.15s ease,\n background 0.15s ease;\n}\n\ntextarea {\n min-height: 120px;\n resize: vertical;\n line-height: 1.5;\n}\n\ninput::placeholder,\ntextarea::placeholder {\n color: #94a3b8;\n}\n\ninput:hover,\ntextarea:hover {\n border-color: #b6c2d1;\n}\n\ninput:focus,\ntextarea:focus {\n border-color: var(--np-primary);\n background: #ffffff;\n box-shadow: 0 0 0 4px var(--np-primary-soft);\n}\n\n.input-wrap {\n position: relative;\n}\n\n.input-wrap input,\n.input-wrap textarea {\n padding-right: 40px;\n}\n\n.btn-clear {\n position: absolute;\n right: 10px;\n top: 50%;\n transform: translateY(-50%);\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 50%;\n background: #e2e8f0;\n color: #64748b;\n font-size: 16px;\n line-height: 1;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n opacity: 0;\n pointer-events: none;\n transition:\n opacity 0.15s ease,\n background 0.15s ease,\n color 0.15s ease;\n}\n\n.input-wrap.has-value:hover .btn-clear,\n.input-wrap.has-value:focus-within .btn-clear {\n opacity: 1;\n pointer-events: auto;\n}\n\n.btn-clear:hover {\n background: #cbd5e1;\n color: #0f172a;\n}\n\n.input-wrap--textarea .btn-clear {\n top: 12px;\n transform: none;\n}\n\n/* File upload styling */\n.upload-zone {\n display: flex;\n align-items: center;\n gap: 16px;\n background: #f8fafc;\n border: 1.5px dashed #cbd5e1;\n padding: 16px 20px;\n border-radius: 12px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n user-select: none;\n outline: none;\n}\n\n.upload-zone:hover {\n background: var(--np-primary-soft);\n border-color: var(--np-primary);\n}\n\n.upload-zone:focus-visible {\n border-color: var(--np-primary);\n box-shadow: 0 0 0 4px var(--np-primary-soft);\n}\n\n.upload-zone.dragover {\n background: rgba(0, 60, 130, 0.08);\n border-color: var(--np-primary);\n transform: scale(1.005);\n}\n\n.upload-icon-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 10px;\n background: #ffffff;\n border: 1px solid #e2e8f0;\n color: #64748b;\n box-shadow: 0 2px 4px rgba(15, 23, 42, 0.04);\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n\n.upload-zone:hover .upload-icon-wrapper,\n.upload-zone.dragover .upload-icon-wrapper {\n color: var(--np-primary);\n border-color: rgba(0, 60, 130, 0.15);\n box-shadow: 0 4px 8px rgba(0, 60, 130, 0.08);\n}\n\n.upload-text-container {\n display: flex;\n flex-direction: column;\n gap: 3px;\n flex: 1;\n}\n\n.upload-main-text {\n font-size: 13px;\n font-weight: 600;\n color: #334155;\n transition: color 0.2s ease;\n}\n\n.upload-zone:hover .upload-main-text {\n color: var(--np-primary);\n}\n\n.upload-sub-text {\n font-size: 11px;\n color: #64748b;\n line-height: 1.4;\n}\n\n.file-list {\n margin-top: 14px;\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n gap: 12px;\n}\n\n.file-item {\n position: relative;\n display: flex;\n flex-direction: column;\n background: #ffffff;\n border: 1px solid #e2e8f0;\n border-radius: 12px;\n font-size: 11px;\n color: #475569;\n box-shadow: 0 2px 5px rgba(15, 23, 42, 0.03);\n animation: file-in 0.2s cubic-bezier(0.16, 1, 0.3, 1);\n transition: all 0.2s ease;\n overflow: hidden;\n}\n\n.file-item:hover {\n border-color: #cbd5e1;\n box-shadow: 0 4px 12px rgba(15, 23, 42, 0.08);\n transform: translateY(-2px);\n}\n\n.file-preview-trigger {\n border: none;\n background: none;\n padding: 0;\n margin: 0;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n width: 100%;\n color: inherit;\n font: inherit;\n}\n\n.file-thumb {\n width: 100%;\n aspect-ratio: 1 / 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f8fafc;\n border-bottom: 1px solid #f1f5f9;\n position: relative;\n overflow: hidden;\n transition: background 0.2s ease;\n}\n\n.file-thumb img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n transition: transform 0.25s ease;\n}\n\n.file-item:hover .file-thumb img {\n transform: scale(1.06);\n}\n\n.file-thumb--icon {\n color: #64748b;\n background: #f1f5f9;\n}\n\n.file-item:hover .file-thumb--icon {\n background: #e2e8f0;\n color: var(--np-primary);\n}\n\n@keyframes file-in {\n from {\n opacity: 0;\n transform: translateY(6px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.file-info-container {\n padding: 8px 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n box-sizing: border-box;\n}\n\n.file-item .file-name {\n width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n line-height: 1.2;\n color: #334155;\n font-size: 11px;\n font-weight: 500;\n text-align: center;\n}\n\n.file-badge {\n position: absolute;\n top: 6px;\n left: 6px;\n z-index: 2;\n padding: 3px 6px;\n border-radius: 6px;\n font-size: 9px;\n font-weight: 600;\n line-height: 1;\n color: #0369a1;\n background: rgba(224, 242, 254, 0.9);\n border: 1px solid rgba(186, 230, 253, 0.8);\n backdrop-filter: blur(4px);\n box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);\n}\n\n.file-item .btn-remove {\n position: absolute;\n top: 6px;\n right: 6px;\n z-index: 2;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.9);\n border: 1px solid #e2e8f0;\n border-radius: 50%;\n color: #64748b;\n cursor: pointer;\n padding: 0;\n box-shadow: 0 2px 4px rgba(15, 23, 42, 0.06);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n backdrop-filter: blur(4px);\n}\n\n.file-item .btn-remove svg {\n width: 8px;\n height: 8px;\n stroke-width: 3px;\n transition: transform 0.2s ease;\n}\n\n.file-item .btn-remove:hover {\n color: #ffffff;\n background: #ef4444;\n border-color: #ef4444;\n transform: scale(1.1);\n box-shadow: 0 3px 8px rgba(239, 68, 68, 0.25);\n}\n\n.file-item .btn-remove:hover svg {\n transform: rotate(90deg);\n}\n\n/* File preview popup */\n.preview-overlay {\n position: fixed;\n inset: 0;\n z-index: 20;\n display: none;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: rgba(15, 23, 42, 0.72);\n backdrop-filter: blur(4px);\n opacity: 0;\n transition: opacity 0.2s ease-out;\n}\n\n.preview-overlay.show {\n display: flex;\n opacity: 1;\n}\n\n.preview-box {\n position: relative;\n max-width: min(720px, 100%);\n max-height: calc(100vh - 96px);\n background: #ffffff;\n border-radius: 16px;\n padding: 16px;\n box-shadow: 0 24px 60px rgba(15, 23, 42, 0.35);\n display: flex;\n flex-direction: column;\n}\n\n.preview-close {\n position: absolute;\n top: -14px;\n right: -14px;\n width: 34px;\n height: 34px;\n border-radius: 50%;\n border: none;\n background: #ffffff;\n color: #334155;\n font-size: 22px;\n line-height: 1;\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(15, 23, 42, 0.25);\n transition:\n color 0.15s ease,\n transform 0.15s ease;\n}\n\n.preview-close:hover {\n color: #ef4444;\n transform: scale(1.05);\n}\n\n.preview-body {\n overflow: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.preview-body img {\n max-width: 100%;\n max-height: calc(100vh - 140px);\n object-fit: contain;\n border-radius: 8px;\n display: block;\n}\n\n.preview-file {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 32px 40px;\n text-align: center;\n color: var(--np-text);\n}\n\n.preview-file svg {\n color: var(--np-primary);\n}\n\n.preview-file .preview-file-name {\n font-size: 14px;\n font-weight: 600;\n word-break: break-all;\n}\n\n.preview-file a {\n color: var(--np-primary);\n font-size: 13px;\n font-weight: 600;\n text-decoration: none;\n}\n\n.preview-file a:hover {\n text-decoration: underline;\n}\n\n.actions {\n margin-top: 28px;\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n}\n\n.btn {\n border-radius: 10px;\n padding: 12px 26px;\n font-size: 15px;\n font-weight: 600;\n font-family: inherit;\n cursor: pointer;\n transition: all 0.18s ease;\n min-width: 120px;\n}\n\n.btn:active {\n transform: translateY(1px);\n}\n\n.btn-secondary {\n background: #ffffff;\n border: 1px solid #d5dde7;\n color: #334155;\n}\n\n.btn-secondary:hover {\n background: #f1f5f9;\n border-color: #b6c2d1;\n}\n\n.btn-primary {\n background: linear-gradient(\n 135deg,\n var(--np-primary),\n var(--np-primary-dark)\n );\n border: 1px solid var(--np-primary-dark);\n color: #ffffff;\n box-shadow: 0 6px 16px rgba(0, 60, 130, 0.28);\n}\n\n.btn-primary:hover {\n box-shadow: 0 8px 22px rgba(0, 60, 130, 0.38);\n filter: brightness(1.06);\n}\n\n@media (max-width: 480px) {\n .dialog {\n padding: 24px 20px 24px;\n border-radius: 16px;\n }\n\n .form-grid {\n grid-template-columns: 1fr;\n }\n\n .actions {\n justify-content: stretch;\n }\n\n .actions .btn {\n flex: 1;\n }\n}\n';
|
|
63
|
+
|
|
64
|
+
// src/component/support-widget.template.html
|
|
65
|
+
var support_widget_template_default = '<button\n id="open-btn"\n class="launcher"\n type="button"\n aria-label="Open support form"\n></button>\n\n<div id="modal" class="modal">\n <div\n class="dialog"\n role="dialog"\n aria-modal="true"\n aria-label="Support request form"\n >\n <div class="header">\n <h3 class="title">T\u1EA1o y\xEAu c\u1EA7u</h3>\n <button id="close-btn" class="close-btn" type="button" aria-label="Close">\n \xD7\n </button>\n </div>\n\n <div class="form-grid">\n <div class="field">\n <label for="requester"><span class="required">*</span> H\u1ECD v\xE0 t\xEAn</label>\n <div class="input-wrap">\n <input id="requester" type="text" placeholder="H\u1ECD v\xE0 t\xEAn" />\n <button type="button" class="btn-clear" aria-label="X\xF3a">\xD7</button>\n </div>\n </div>\n\n <div class="field">\n <label for="phone-number"\n ><span class="required">*</span> S\u1ED1 \u0111i\u1EC7n tho\u1EA1i</label\n >\n <div class="input-wrap">\n <input id="phone-number" type="text" placeholder="S\u1ED1 \u0111i\u1EC7n tho\u1EA1i" />\n <button type="button" class="btn-clear" aria-label="X\xF3a">\xD7</button>\n </div>\n </div>\n\n <div class="field full">\n <label for="email"><span class="required">*</span> Email</label>\n <div class="input-wrap">\n <input id="email" type="email" placeholder="Email" />\n <button type="button" class="btn-clear" aria-label="X\xF3a">\xD7</button>\n </div>\n </div>\n\n <div class="field full">\n <label for="content"><span class="required">*</span> N\u1ED9i dung</label>\n <div class="input-wrap input-wrap--textarea">\n <textarea\n id="content"\n placeholder="Anh/Ch\u1ECB vui l\xF2ng nh\u1EADp th\xF4ng tin c\u1EA7n h\u1ED7 tr\u1EE3"\n ></textarea>\n <button type="button" class="btn-clear" aria-label="X\xF3a">\xD7</button>\n </div>\n </div>\n\n <div class="field full">\n <label>File \u0111\xEDnh k\xE8m</label>\n <div id="upload-trigger" class="upload-zone" role="button" tabindex="0" aria-label="T\u1EA3i l\xEAn t\u1EC7p">\n <input id="file-input" type="file" multiple style="display: none" />\n <div class="upload-icon-wrapper">\n <svg\n class="upload-icon"\n xmlns="http://www.w3.org/2000/svg"\n width="20"\n height="20"\n viewBox="0 0 24 24"\n fill="none"\n stroke="currentColor"\n stroke-width="2.2"\n stroke-linecap="round"\n stroke-linejoin="round"\n >\n <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>\n <polyline points="17 8 12 3 7 8"></polyline>\n <line x1="12" y1="3" x2="12" y2="15"></line>\n </svg>\n </div>\n <div class="upload-text-container">\n <span class="upload-main-text">Ch\u1ECDn t\u1EC7p t\u1EA3i l\xEAn ho\u1EB7c k\xE9o th\u1EA3 v\xE0o \u0111\xE2y</span>\n <span class="upload-sub-text">H\u1ED7 tr\u1EE3 d\xE1n \u1EA3nh ho\u1EB7c t\u1EC7p (Ctrl+V / Cmd+V) \u0111\u1EC3 \u0111\xEDnh k\xE8m nhanh</span>\n </div>\n </div>\n <div id="file-list" class="file-list"></div>\n </div>\n </div>\n\n <div id="preview-overlay" class="preview-overlay">\n <div\n class="preview-box"\n role="dialog"\n aria-modal="true"\n aria-label="Xem tr\u01B0\u1EDBc t\u1EC7p"\n >\n <button\n id="preview-close"\n class="preview-close"\n type="button"\n aria-label="\u0110\xF3ng"\n >\n \xD7\n </button>\n <div id="preview-body" class="preview-body"></div>\n </div>\n </div>\n\n <div class="actions">\n <button id="cancel-btn" class="btn btn-secondary" type="button">\n H\u1EE7y\n </button>\n <button id="submit-btn" class="btn btn-primary" type="button">\n T\u1EA1o y\xEAu c\u1EA7u\n </button>\n </div>\n </div>\n</div>\n';
|
|
66
|
+
|
|
67
|
+
// src/component/support-widget.element.ts
|
|
68
|
+
var sharedTemplate = null;
|
|
69
|
+
function getTemplate() {
|
|
70
|
+
if (!sharedTemplate) {
|
|
71
|
+
sharedTemplate = document.createElement("template");
|
|
72
|
+
sharedTemplate.innerHTML = `<style>${support_widget_styles_default}</style>${support_widget_template_default}`;
|
|
73
|
+
}
|
|
74
|
+
return sharedTemplate;
|
|
75
|
+
}
|
|
76
|
+
async function urlToFile(url) {
|
|
77
|
+
try {
|
|
78
|
+
const response = await fetch(url);
|
|
79
|
+
if (!response.ok) return null;
|
|
80
|
+
const blob = await response.blob();
|
|
81
|
+
const name = url.substring(url.lastIndexOf("/") + 1) || "attachment";
|
|
82
|
+
return new File([blob], name, { type: blob.type });
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.warn("Failed to fetch prefilled attachment", url, e);
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
var SupportWidgetElement = class extends HTMLElement {
|
|
89
|
+
constructor() {
|
|
90
|
+
super();
|
|
91
|
+
this.config = {
|
|
92
|
+
projectId: ""
|
|
93
|
+
};
|
|
94
|
+
this.dragOccurred = false;
|
|
95
|
+
// Internal states for fields mapped behind the scenes
|
|
96
|
+
this.selectedFiles = [];
|
|
97
|
+
this.prefilledAttachments = [];
|
|
98
|
+
this.previewUrls = [];
|
|
99
|
+
this.priority = 0;
|
|
100
|
+
this.coordinators = [];
|
|
101
|
+
this.emailContacts = [];
|
|
102
|
+
this.handleResize = () => {
|
|
103
|
+
if (this.style.left && this.style.top) {
|
|
104
|
+
const leftVal = parseFloat(this.style.left);
|
|
105
|
+
const topVal = parseFloat(this.style.top);
|
|
106
|
+
this.adjustPosition(leftVal, topVal);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const root = this.attachShadow({ mode: "open" });
|
|
110
|
+
root.appendChild(getTemplate().content.cloneNode(true));
|
|
111
|
+
this.bindActions();
|
|
112
|
+
}
|
|
113
|
+
connectedCallback() {
|
|
114
|
+
this.syncConfigFromAttributes();
|
|
115
|
+
this.prefillFromState();
|
|
116
|
+
this.applyLauncherStyle();
|
|
117
|
+
this.restorePosition();
|
|
118
|
+
window.addEventListener("resize", this.handleResize);
|
|
119
|
+
}
|
|
120
|
+
disconnectedCallback() {
|
|
121
|
+
window.removeEventListener("resize", this.handleResize);
|
|
122
|
+
}
|
|
123
|
+
attributeChangedCallback() {
|
|
124
|
+
this.syncConfigFromAttributes();
|
|
125
|
+
this.prefillFromState();
|
|
126
|
+
this.applyLauncherStyle();
|
|
127
|
+
}
|
|
128
|
+
setUser(user) {
|
|
129
|
+
this.user = user;
|
|
130
|
+
this.prefillFromState();
|
|
131
|
+
}
|
|
132
|
+
setFormPrefill(data) {
|
|
133
|
+
this.setInputValue("content", data.content ?? "");
|
|
134
|
+
this.prefilledAttachments = data.attachments ?? [];
|
|
135
|
+
this.priority = data.priority ?? 0;
|
|
136
|
+
this.coordinators = data.coordinators ?? [];
|
|
137
|
+
this.emailContacts = data.emailContacts ?? [];
|
|
138
|
+
this.renderFileList();
|
|
139
|
+
}
|
|
140
|
+
open() {
|
|
141
|
+
this.shadowRoot?.getElementById("modal")?.classList.add("show");
|
|
142
|
+
this.dispatchEvent(new CustomEvent(WIDGET_EVENTS.OPEN, { bubbles: true }));
|
|
143
|
+
}
|
|
144
|
+
close() {
|
|
145
|
+
this.shadowRoot?.getElementById("modal")?.classList.remove("show");
|
|
146
|
+
this.dispatchEvent(new CustomEvent(WIDGET_EVENTS.CLOSE, { bubbles: true }));
|
|
147
|
+
}
|
|
148
|
+
syncConfigFromAttributes() {
|
|
149
|
+
this.config = {
|
|
150
|
+
projectId: this.getAttribute("project-id") ?? "",
|
|
151
|
+
isDev: this.hasAttribute("is-dev")
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
bindActions() {
|
|
155
|
+
const root = this.shadowRoot;
|
|
156
|
+
if (!root) return;
|
|
157
|
+
const launcher = root.getElementById("open-btn");
|
|
158
|
+
if (launcher) {
|
|
159
|
+
launcher.addEventListener("click", () => {
|
|
160
|
+
if (this.dragOccurred) {
|
|
161
|
+
this.dragOccurred = false;
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
this.open();
|
|
165
|
+
});
|
|
166
|
+
this.setupDrag(launcher);
|
|
167
|
+
}
|
|
168
|
+
root.getElementById("close-btn")?.addEventListener("click", () => this.close());
|
|
169
|
+
root.getElementById("cancel-btn")?.addEventListener("click", () => this.close());
|
|
170
|
+
root.getElementById("submit-btn")?.addEventListener("click", () => void this.submit());
|
|
171
|
+
this.setupClearableInputs();
|
|
172
|
+
const uploadTrigger = root.getElementById("upload-trigger");
|
|
173
|
+
const fileInput = root.getElementById(
|
|
174
|
+
"file-input"
|
|
175
|
+
);
|
|
176
|
+
if (uploadTrigger && fileInput) {
|
|
177
|
+
uploadTrigger.addEventListener("click", () => {
|
|
178
|
+
fileInput.click();
|
|
179
|
+
});
|
|
180
|
+
uploadTrigger.addEventListener("keydown", (e) => {
|
|
181
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
182
|
+
e.preventDefault();
|
|
183
|
+
fileInput.click();
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
uploadTrigger.addEventListener("dragover", (e) => {
|
|
187
|
+
e.preventDefault();
|
|
188
|
+
if (e.dataTransfer) {
|
|
189
|
+
e.dataTransfer.dropEffect = "copy";
|
|
190
|
+
}
|
|
191
|
+
uploadTrigger.classList.add("dragover");
|
|
192
|
+
});
|
|
193
|
+
uploadTrigger.addEventListener("dragleave", () => {
|
|
194
|
+
uploadTrigger.classList.remove("dragover");
|
|
195
|
+
});
|
|
196
|
+
uploadTrigger.addEventListener("drop", (e) => {
|
|
197
|
+
e.preventDefault();
|
|
198
|
+
uploadTrigger.classList.remove("dragover");
|
|
199
|
+
if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {
|
|
200
|
+
this.addSelectedFiles(Array.from(e.dataTransfer.files));
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
fileInput.addEventListener("change", () => {
|
|
204
|
+
if (fileInput.files) {
|
|
205
|
+
this.addSelectedFiles(Array.from(fileInput.files));
|
|
206
|
+
fileInput.value = "";
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
this.setupClipboardPaste();
|
|
211
|
+
this.setupPreviewControls();
|
|
212
|
+
}
|
|
213
|
+
setupPreviewControls() {
|
|
214
|
+
const root = this.shadowRoot;
|
|
215
|
+
if (!root) return;
|
|
216
|
+
const overlay = root.getElementById("preview-overlay");
|
|
217
|
+
root.getElementById("preview-close")?.addEventListener("click", () => this.closePreview());
|
|
218
|
+
overlay?.addEventListener("click", (event) => {
|
|
219
|
+
if (event.target === overlay) this.closePreview();
|
|
220
|
+
});
|
|
221
|
+
root.addEventListener("keydown", (event) => {
|
|
222
|
+
if (event.key === "Escape") this.closePreview();
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
setupClipboardPaste() {
|
|
226
|
+
const dialog = this.shadowRoot?.querySelector(".dialog");
|
|
227
|
+
if (!dialog) return;
|
|
228
|
+
dialog.addEventListener("paste", (event) => {
|
|
229
|
+
const clipboard = event.clipboardData;
|
|
230
|
+
if (!clipboard) return;
|
|
231
|
+
const files = Array.from(clipboard.items).filter((item) => item.kind === "file").map((item) => item.getAsFile()).filter((file) => file !== null);
|
|
232
|
+
if (files.length === 0) return;
|
|
233
|
+
event.preventDefault();
|
|
234
|
+
this.addSelectedFiles(files);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
addSelectedFiles(files) {
|
|
238
|
+
if (files.length === 0) return;
|
|
239
|
+
this.selectedFiles.push(...files);
|
|
240
|
+
this.renderFileList();
|
|
241
|
+
}
|
|
242
|
+
renderFileList() {
|
|
243
|
+
const fileListEl = this.shadowRoot?.getElementById("file-list");
|
|
244
|
+
if (!fileListEl) return;
|
|
245
|
+
fileListEl.innerHTML = "";
|
|
246
|
+
this.previewUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
247
|
+
this.previewUrls = [];
|
|
248
|
+
this.prefilledAttachments.forEach((url, index) => {
|
|
249
|
+
const name = url.substring(url.lastIndexOf("/") + 1) || url;
|
|
250
|
+
const isImage = this.isImageName(name);
|
|
251
|
+
const previewUrl = isImage ? url : null;
|
|
252
|
+
fileListEl.appendChild(
|
|
253
|
+
this.buildFileItem({
|
|
254
|
+
name,
|
|
255
|
+
title: url,
|
|
256
|
+
previewUrl,
|
|
257
|
+
type: "prefilled",
|
|
258
|
+
index,
|
|
259
|
+
isImage,
|
|
260
|
+
openUrl: url,
|
|
261
|
+
badge: "\u0110\xE3 g\xE1n"
|
|
262
|
+
})
|
|
263
|
+
);
|
|
264
|
+
});
|
|
265
|
+
this.selectedFiles.forEach((file, index) => {
|
|
266
|
+
let previewUrl = null;
|
|
267
|
+
const isImage = file.type.startsWith("image/");
|
|
268
|
+
if (isImage) {
|
|
269
|
+
previewUrl = URL.createObjectURL(file);
|
|
270
|
+
this.previewUrls.push(previewUrl);
|
|
271
|
+
}
|
|
272
|
+
fileListEl.appendChild(
|
|
273
|
+
this.buildFileItem({
|
|
274
|
+
name: file.name,
|
|
275
|
+
title: file.name,
|
|
276
|
+
previewUrl,
|
|
277
|
+
type: "selected",
|
|
278
|
+
index,
|
|
279
|
+
isImage,
|
|
280
|
+
openUrl: null,
|
|
281
|
+
badge: null
|
|
282
|
+
})
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
fileListEl.querySelectorAll(".btn-remove").forEach((btn) => {
|
|
286
|
+
btn.addEventListener("click", (e) => {
|
|
287
|
+
const target = e.currentTarget;
|
|
288
|
+
const type = target.getAttribute("data-type");
|
|
289
|
+
const index = parseInt(target.getAttribute("data-index") || "0", 10);
|
|
290
|
+
if (type === "prefilled") {
|
|
291
|
+
this.prefilledAttachments.splice(index, 1);
|
|
292
|
+
} else {
|
|
293
|
+
this.selectedFiles.splice(index, 1);
|
|
294
|
+
}
|
|
295
|
+
this.renderFileList();
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
buildFileItem(opts) {
|
|
300
|
+
const item = document.createElement("div");
|
|
301
|
+
item.className = "file-item";
|
|
302
|
+
const trigger = document.createElement("button");
|
|
303
|
+
trigger.type = "button";
|
|
304
|
+
trigger.className = "file-preview-trigger";
|
|
305
|
+
trigger.title = "Nh\u1EA5n \u0111\u1EC3 xem tr\u01B0\u1EDBc";
|
|
306
|
+
trigger.addEventListener("click", () => {
|
|
307
|
+
this.openPreview({
|
|
308
|
+
name: opts.title,
|
|
309
|
+
previewUrl: opts.previewUrl,
|
|
310
|
+
isImage: opts.isImage,
|
|
311
|
+
openUrl: opts.openUrl
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
const thumb = document.createElement("div");
|
|
315
|
+
thumb.className = "file-thumb";
|
|
316
|
+
if (opts.previewUrl) {
|
|
317
|
+
const img = document.createElement("img");
|
|
318
|
+
img.src = opts.previewUrl;
|
|
319
|
+
img.alt = opts.name;
|
|
320
|
+
img.addEventListener("error", () => this.fillWithFileIcon(thumb));
|
|
321
|
+
thumb.appendChild(img);
|
|
322
|
+
} else {
|
|
323
|
+
this.fillWithFileIcon(thumb);
|
|
324
|
+
}
|
|
325
|
+
const infoContainer = document.createElement("div");
|
|
326
|
+
infoContainer.className = "file-info-container";
|
|
327
|
+
const name = document.createElement("span");
|
|
328
|
+
name.className = "file-name";
|
|
329
|
+
name.title = opts.title;
|
|
330
|
+
name.textContent = opts.name;
|
|
331
|
+
infoContainer.appendChild(name);
|
|
332
|
+
trigger.append(thumb, infoContainer);
|
|
333
|
+
const removeBtn = document.createElement("button");
|
|
334
|
+
removeBtn.type = "button";
|
|
335
|
+
removeBtn.className = "btn-remove";
|
|
336
|
+
removeBtn.setAttribute("aria-label", "X\xF3a t\u1EC7p");
|
|
337
|
+
removeBtn.setAttribute("data-type", opts.type);
|
|
338
|
+
removeBtn.setAttribute("data-index", String(opts.index));
|
|
339
|
+
removeBtn.innerHTML = `
|
|
340
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
|
341
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
342
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
343
|
+
</svg>
|
|
344
|
+
`;
|
|
345
|
+
item.append(trigger, removeBtn);
|
|
346
|
+
if (opts.badge) {
|
|
347
|
+
const badge = document.createElement("span");
|
|
348
|
+
badge.className = "file-badge";
|
|
349
|
+
badge.textContent = opts.badge;
|
|
350
|
+
item.appendChild(badge);
|
|
351
|
+
}
|
|
352
|
+
return item;
|
|
353
|
+
}
|
|
354
|
+
fillWithFileIcon(thumb) {
|
|
355
|
+
thumb.innerHTML = "";
|
|
356
|
+
thumb.classList.add("file-thumb--icon");
|
|
357
|
+
thumb.innerHTML = `
|
|
358
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
359
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
|
360
|
+
<polyline points="14 2 14 8 20 8"></polyline>
|
|
361
|
+
</svg>`;
|
|
362
|
+
}
|
|
363
|
+
openPreview(opts) {
|
|
364
|
+
const overlay = this.shadowRoot?.getElementById("preview-overlay");
|
|
365
|
+
const body = this.shadowRoot?.getElementById("preview-body");
|
|
366
|
+
if (!overlay || !body) return;
|
|
367
|
+
body.innerHTML = "";
|
|
368
|
+
if (opts.isImage && opts.previewUrl) {
|
|
369
|
+
const img = document.createElement("img");
|
|
370
|
+
img.src = opts.previewUrl;
|
|
371
|
+
img.alt = opts.name;
|
|
372
|
+
body.appendChild(img);
|
|
373
|
+
} else {
|
|
374
|
+
const info = document.createElement("div");
|
|
375
|
+
info.className = "preview-file";
|
|
376
|
+
const openLink = opts.openUrl ? `<a href="${opts.openUrl}" target="_blank" rel="noopener noreferrer">M\u1EDF trong tab m\u1EDBi</a>` : `<span>Kh\xF4ng c\xF3 b\u1EA3n xem tr\u01B0\u1EDBc cho t\u1EC7p n\xE0y</span>`;
|
|
377
|
+
info.innerHTML = `
|
|
378
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="56" height="56" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
379
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
|
380
|
+
<polyline points="14 2 14 8 20 8"></polyline>
|
|
381
|
+
</svg>
|
|
382
|
+
<span class="preview-file-name"></span>
|
|
383
|
+
${openLink}`;
|
|
384
|
+
const nameEl = info.querySelector(".preview-file-name");
|
|
385
|
+
if (nameEl) nameEl.textContent = opts.name;
|
|
386
|
+
body.appendChild(info);
|
|
387
|
+
}
|
|
388
|
+
overlay.classList.add("show");
|
|
389
|
+
}
|
|
390
|
+
closePreview() {
|
|
391
|
+
const overlay = this.shadowRoot?.getElementById("preview-overlay");
|
|
392
|
+
if (!overlay) return;
|
|
393
|
+
overlay.classList.remove("show");
|
|
394
|
+
const body = this.shadowRoot?.getElementById("preview-body");
|
|
395
|
+
if (body) body.innerHTML = "";
|
|
396
|
+
}
|
|
397
|
+
isImageName(name) {
|
|
398
|
+
return /\.(png|jpe?g|gif|webp|bmp|svg|avif)$/i.test(name);
|
|
399
|
+
}
|
|
400
|
+
prefillFromState() {
|
|
401
|
+
this.setInputValue("requester", this.user?.name ?? "");
|
|
402
|
+
this.setInputValue("email", this.user?.email ?? "");
|
|
403
|
+
this.setInputValue("phone-number", this.user?.phoneNumber ?? "");
|
|
404
|
+
}
|
|
405
|
+
applyLauncherStyle() {
|
|
406
|
+
const launcher = this.shadowRoot?.getElementById("open-btn");
|
|
407
|
+
if (!launcher) return;
|
|
408
|
+
const launcherStyles = [`--np-hub-icon: url("${np_support_logo_default}")`];
|
|
409
|
+
const width = this.normalizeSize(this.getAttribute("width"));
|
|
410
|
+
const height = this.normalizeSize(this.getAttribute("height"));
|
|
411
|
+
if (width) launcherStyles.push(`--np-hub-width: ${width}`);
|
|
412
|
+
if (height) launcherStyles.push(`--np-hub-height: ${height}`);
|
|
413
|
+
launcher.setAttribute("style", `${launcherStyles.join("; ")};`);
|
|
414
|
+
}
|
|
415
|
+
normalizeSize(value) {
|
|
416
|
+
const trimmed = value?.trim();
|
|
417
|
+
if (!trimmed) return null;
|
|
418
|
+
return /^\d+(\.\d+)?$/.test(trimmed) ? `${trimmed}px` : trimmed;
|
|
419
|
+
}
|
|
420
|
+
setupClearableInputs() {
|
|
421
|
+
const root = this.shadowRoot;
|
|
422
|
+
if (!root) return;
|
|
423
|
+
root.querySelectorAll(".input-wrap").forEach((wrap) => {
|
|
424
|
+
const input = wrap.querySelector("input, textarea");
|
|
425
|
+
const clearBtn = wrap.querySelector(
|
|
426
|
+
".btn-clear"
|
|
427
|
+
);
|
|
428
|
+
if (!input || !clearBtn) return;
|
|
429
|
+
const updateVisibility = () => this.updateClearButton(input);
|
|
430
|
+
input.addEventListener("input", updateVisibility);
|
|
431
|
+
clearBtn.addEventListener("click", () => {
|
|
432
|
+
input.value = "";
|
|
433
|
+
input.focus();
|
|
434
|
+
updateVisibility();
|
|
435
|
+
});
|
|
436
|
+
updateVisibility();
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
updateClearButton(input) {
|
|
440
|
+
const wrap = input.parentElement;
|
|
441
|
+
if (wrap?.classList.contains("input-wrap")) {
|
|
442
|
+
wrap.classList.toggle("has-value", input.value.length > 0);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
setInputValue(id, value) {
|
|
446
|
+
const el = this.shadowRoot?.getElementById(id);
|
|
447
|
+
if (!el) return;
|
|
448
|
+
el.value = value;
|
|
449
|
+
this.updateClearButton(el);
|
|
450
|
+
}
|
|
451
|
+
getInputValue(id) {
|
|
452
|
+
const el = this.shadowRoot?.getElementById(id);
|
|
453
|
+
return el?.value?.trim() ?? "";
|
|
454
|
+
}
|
|
455
|
+
async submit() {
|
|
456
|
+
try {
|
|
457
|
+
const user = {
|
|
458
|
+
name: this.getInputValue("requester"),
|
|
459
|
+
email: this.getInputValue("email"),
|
|
460
|
+
phoneNumber: this.getInputValue("phone-number")
|
|
461
|
+
};
|
|
462
|
+
this.user = user;
|
|
463
|
+
validateWidgetConfig(this.config);
|
|
464
|
+
validateUser(user);
|
|
465
|
+
const content = this.getInputValue("content");
|
|
466
|
+
const submission = {
|
|
467
|
+
content,
|
|
468
|
+
attachments: [],
|
|
469
|
+
// dummy value for local validation of required content field
|
|
470
|
+
priority: this.priority,
|
|
471
|
+
coordinators: this.coordinators,
|
|
472
|
+
emailContacts: this.emailContacts
|
|
473
|
+
};
|
|
474
|
+
validateSubmission(submission);
|
|
475
|
+
const formData = new FormData();
|
|
476
|
+
formData.append("Requester", user.name);
|
|
477
|
+
formData.append("PhoneNumber", user.phoneNumber);
|
|
478
|
+
formData.append("Email", user.email);
|
|
479
|
+
formData.append("Content", content);
|
|
480
|
+
formData.append("ProjectId", this.config.projectId);
|
|
481
|
+
formData.append("Priority", String(this.priority));
|
|
482
|
+
for (const url of this.prefilledAttachments) {
|
|
483
|
+
const file = await urlToFile(url);
|
|
484
|
+
if (file) {
|
|
485
|
+
formData.append("Attachments", file);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
for (const file of this.selectedFiles) {
|
|
489
|
+
formData.append("Attachments", file);
|
|
490
|
+
}
|
|
491
|
+
this.coordinators.forEach(
|
|
492
|
+
(coord) => formData.append("Coordinators", coord)
|
|
493
|
+
);
|
|
494
|
+
this.emailContacts.forEach(
|
|
495
|
+
(contact) => formData.append("EmailContacts", contact)
|
|
496
|
+
);
|
|
497
|
+
const baseUrl = resolveBaseUrl(this.config);
|
|
498
|
+
const result = await createSupportRequest(baseUrl, formData);
|
|
499
|
+
this.dispatchEvent(
|
|
500
|
+
new CustomEvent(WIDGET_EVENTS.SUBMIT_SUCCESS, {
|
|
501
|
+
bubbles: true,
|
|
502
|
+
detail: result
|
|
503
|
+
})
|
|
504
|
+
);
|
|
505
|
+
this.close();
|
|
506
|
+
} catch (error) {
|
|
507
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
508
|
+
this.dispatchEvent(
|
|
509
|
+
new CustomEvent(WIDGET_EVENTS.SUBMIT_ERROR, {
|
|
510
|
+
bubbles: true,
|
|
511
|
+
detail: { message }
|
|
512
|
+
})
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
setupDrag(launcher) {
|
|
517
|
+
launcher.addEventListener("pointerdown", (e) => {
|
|
518
|
+
if (e.button !== 0) return;
|
|
519
|
+
this.dragOccurred = false;
|
|
520
|
+
const rect = this.getBoundingClientRect();
|
|
521
|
+
const startX = e.clientX;
|
|
522
|
+
const startY = e.clientY;
|
|
523
|
+
const initialLeft = rect.left;
|
|
524
|
+
const initialTop = rect.top;
|
|
525
|
+
try {
|
|
526
|
+
launcher.setPointerCapture(e.pointerId);
|
|
527
|
+
} catch {
|
|
528
|
+
}
|
|
529
|
+
const onPointerMove = (moveEvent) => {
|
|
530
|
+
const dx = moveEvent.clientX - startX;
|
|
531
|
+
const dy = moveEvent.clientY - startY;
|
|
532
|
+
if (!this.dragOccurred && (Math.abs(dx) > 4 || Math.abs(dy) > 4)) {
|
|
533
|
+
this.dragOccurred = true;
|
|
534
|
+
launcher.style.cursor = "grabbing";
|
|
535
|
+
}
|
|
536
|
+
if (this.dragOccurred) {
|
|
537
|
+
const leftVal = initialLeft + dx;
|
|
538
|
+
const topVal = initialTop + dy;
|
|
539
|
+
this.adjustPosition(leftVal, topVal);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
const onPointerUp = (upEvent) => {
|
|
543
|
+
try {
|
|
544
|
+
launcher.releasePointerCapture(upEvent.pointerId);
|
|
545
|
+
} catch {
|
|
546
|
+
}
|
|
547
|
+
launcher.removeEventListener("pointermove", onPointerMove);
|
|
548
|
+
launcher.removeEventListener("pointerup", onPointerUp);
|
|
549
|
+
launcher.removeEventListener("pointercancel", onPointerUp);
|
|
550
|
+
launcher.style.cursor = "";
|
|
551
|
+
if (this.dragOccurred) {
|
|
552
|
+
localStorage.setItem(
|
|
553
|
+
"np-hub-widget-position",
|
|
554
|
+
JSON.stringify({
|
|
555
|
+
left: this.style.left,
|
|
556
|
+
top: this.style.top
|
|
557
|
+
})
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
launcher.addEventListener("pointermove", onPointerMove);
|
|
562
|
+
launcher.addEventListener("pointerup", onPointerUp);
|
|
563
|
+
launcher.addEventListener("pointercancel", onPointerUp);
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
adjustPosition(leftVal, topVal) {
|
|
567
|
+
const rect = this.getBoundingClientRect();
|
|
568
|
+
const width = rect.width || 72;
|
|
569
|
+
const height = rect.height || 72;
|
|
570
|
+
const minLeft = 0;
|
|
571
|
+
const maxLeft = window.innerWidth - width;
|
|
572
|
+
const minTop = 0;
|
|
573
|
+
const maxTop = window.innerHeight - height;
|
|
574
|
+
const clampedLeft = Math.max(minLeft, Math.min(maxLeft, leftVal));
|
|
575
|
+
const clampedTop = Math.max(minTop, Math.min(maxTop, topVal));
|
|
576
|
+
this.style.right = "auto";
|
|
577
|
+
this.style.bottom = "auto";
|
|
578
|
+
this.style.left = `${clampedLeft}px`;
|
|
579
|
+
this.style.top = `${clampedTop}px`;
|
|
580
|
+
}
|
|
581
|
+
restorePosition() {
|
|
582
|
+
const savedPosition = localStorage.getItem("np-hub-widget-position");
|
|
583
|
+
if (savedPosition) {
|
|
584
|
+
try {
|
|
585
|
+
const { left, top } = JSON.parse(savedPosition);
|
|
586
|
+
if (left && top) {
|
|
587
|
+
const leftVal = parseFloat(left);
|
|
588
|
+
const topVal = parseFloat(top);
|
|
589
|
+
this.adjustPosition(leftVal, topVal);
|
|
590
|
+
}
|
|
591
|
+
} catch {
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
SupportWidgetElement.observedAttributes = ["project-id", "is-dev", "width", "height"];
|
|
597
|
+
|
|
598
|
+
// src/register.ts
|
|
599
|
+
var TAG_NAME = "np-hub";
|
|
600
|
+
function registerSupportWidget() {
|
|
601
|
+
if (!customElements.get(TAG_NAME)) {
|
|
602
|
+
customElements.define(TAG_NAME, SupportWidgetElement);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
registerSupportWidget();
|
|
606
|
+
|
|
607
|
+
export {
|
|
608
|
+
WIDGET_EVENTS,
|
|
609
|
+
SupportWidgetElement,
|
|
610
|
+
registerSupportWidget
|
|
611
|
+
};
|
|
612
|
+
//# sourceMappingURL=chunk-ZZ63ZHC7.js.map
|