@getlupa/client 1.18.3 → 1.18.5
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/lupaSearch.iife.js +492 -43
- package/dist/lupaSearch.js +492 -43
- package/dist/lupaSearch.mjs +492 -43
- package/dist/lupaSearch.umd.js +492 -43
- package/dist/src/modules/pluginManager/PluginConfigurationMerger.d.ts +1 -0
- package/dist/style.css +1 -1
- package/package.json +2 -2
package/dist/lupaSearch.mjs
CHANGED
|
@@ -12617,6 +12617,11 @@ const getRandomString = (length) => {
|
|
|
12617
12617
|
}
|
|
12618
12618
|
return result2;
|
|
12619
12619
|
};
|
|
12620
|
+
const getSocketClientId = () => {
|
|
12621
|
+
const timestamp = Date.now().toString(36);
|
|
12622
|
+
const randomString = getRandomString(8);
|
|
12623
|
+
return `${timestamp}-${randomString}`;
|
|
12624
|
+
};
|
|
12620
12625
|
const toFixedIfNecessary = (value, precision = 2) => {
|
|
12621
12626
|
return (+parseFloat(value).toFixed(precision)).toString();
|
|
12622
12627
|
};
|
|
@@ -12731,6 +12736,10 @@ const DEFAULT_SEARCH_BOX_OPTIONS$1 = {
|
|
|
12731
12736
|
links: {
|
|
12732
12737
|
searchResults: "/search"
|
|
12733
12738
|
},
|
|
12739
|
+
voiceSearch: {
|
|
12740
|
+
enabled: false,
|
|
12741
|
+
queryKey: ""
|
|
12742
|
+
},
|
|
12734
12743
|
panels: [
|
|
12735
12744
|
{
|
|
12736
12745
|
type: "suggestion",
|
|
@@ -14312,6 +14321,350 @@ const useSearchBoxStore = defineStore("searchBox", () => {
|
|
|
14312
14321
|
resetHighlightIndex
|
|
14313
14322
|
};
|
|
14314
14323
|
});
|
|
14324
|
+
const Env = {
|
|
14325
|
+
production: "https://api.lupasearch.com/v1/",
|
|
14326
|
+
staging: "https://api.staging.lupasearch.com/v1/"
|
|
14327
|
+
};
|
|
14328
|
+
const VoiceServiceEnv = {
|
|
14329
|
+
production: "ws://voice.lupasearch.com:3001",
|
|
14330
|
+
staging: "ws://voice.lupasearch.dev:3001"
|
|
14331
|
+
};
|
|
14332
|
+
const DEFAULT_REQUEST_CONFIG = {
|
|
14333
|
+
method: "POST",
|
|
14334
|
+
headers: { "Content-Type": "application/json" }
|
|
14335
|
+
};
|
|
14336
|
+
const DEFAULT_HEADERS = DEFAULT_REQUEST_CONFIG.headers;
|
|
14337
|
+
const getVoiceServiceApiUrl = (environment, customVoiceServiceUrl) => {
|
|
14338
|
+
if (customVoiceServiceUrl) {
|
|
14339
|
+
return customVoiceServiceUrl;
|
|
14340
|
+
}
|
|
14341
|
+
return VoiceServiceEnv[environment] || VoiceServiceEnv["production"];
|
|
14342
|
+
};
|
|
14343
|
+
const getApiUrl = (environment, customBaseUrl) => {
|
|
14344
|
+
if (customBaseUrl) {
|
|
14345
|
+
return customBaseUrl;
|
|
14346
|
+
}
|
|
14347
|
+
return Env[environment] || Env["production"];
|
|
14348
|
+
};
|
|
14349
|
+
const _sfc_main$1z = /* @__PURE__ */ defineComponent({
|
|
14350
|
+
__name: "VoiceSearchProgressCircle",
|
|
14351
|
+
props: {
|
|
14352
|
+
isRecording: { type: Boolean },
|
|
14353
|
+
timesliceLimit: {},
|
|
14354
|
+
timeSliceLength: {}
|
|
14355
|
+
},
|
|
14356
|
+
setup(__props, { expose: __expose }) {
|
|
14357
|
+
const props = __props;
|
|
14358
|
+
const progressBar = ref(null);
|
|
14359
|
+
const getProgressBarColor = (progressBarStyle) => {
|
|
14360
|
+
if (!progressBarStyle.backgroundImage.startsWith("conic-gradient")) {
|
|
14361
|
+
return progressBarStyle.backgroundColor;
|
|
14362
|
+
}
|
|
14363
|
+
const colorStops = progressBarStyle.backgroundImage.replace(/conic-gradient\(|\)$/g, "").split(")");
|
|
14364
|
+
if (colorStops.length > 1) {
|
|
14365
|
+
return `${colorStops[0]})`;
|
|
14366
|
+
} else {
|
|
14367
|
+
return progressBarStyle.backgroundColor;
|
|
14368
|
+
}
|
|
14369
|
+
};
|
|
14370
|
+
const startProgressBar = () => {
|
|
14371
|
+
if (!progressBar.value || !props.isRecording) {
|
|
14372
|
+
return;
|
|
14373
|
+
}
|
|
14374
|
+
const duration = props.timesliceLimit * props.timeSliceLength;
|
|
14375
|
+
const progressBarStyle = window.getComputedStyle(progressBar.value);
|
|
14376
|
+
const progressBarColor = getProgressBarColor(progressBarStyle);
|
|
14377
|
+
progressBar.value.style.background = `conic-gradient(${progressBarColor} 0%, transparent 0%)`;
|
|
14378
|
+
let startTime = null;
|
|
14379
|
+
function updateProgress(timestamp) {
|
|
14380
|
+
if (!progressBar.value || !props.isRecording) {
|
|
14381
|
+
return;
|
|
14382
|
+
}
|
|
14383
|
+
if (!startTime)
|
|
14384
|
+
startTime = timestamp;
|
|
14385
|
+
const elapsed = timestamp - startTime;
|
|
14386
|
+
const progress = Math.min(elapsed / duration, 1) * 100;
|
|
14387
|
+
progressBar.value.style.background = `conic-gradient(${progressBarColor} ${progress}%, transparent ${progress}%)`;
|
|
14388
|
+
if (elapsed < duration) {
|
|
14389
|
+
requestAnimationFrame(updateProgress);
|
|
14390
|
+
}
|
|
14391
|
+
}
|
|
14392
|
+
requestAnimationFrame(updateProgress);
|
|
14393
|
+
};
|
|
14394
|
+
const stopProgressBar = () => {
|
|
14395
|
+
if (!progressBar.value) {
|
|
14396
|
+
return;
|
|
14397
|
+
}
|
|
14398
|
+
progressBar.value.style.background = "";
|
|
14399
|
+
};
|
|
14400
|
+
__expose({
|
|
14401
|
+
startProgressBar,
|
|
14402
|
+
stopProgressBar
|
|
14403
|
+
});
|
|
14404
|
+
return (_ctx, _cache) => {
|
|
14405
|
+
return openBlock(), createElementBlock("div", {
|
|
14406
|
+
ref_key: "progressBar",
|
|
14407
|
+
ref: progressBar,
|
|
14408
|
+
class: "lupa-progress-circle"
|
|
14409
|
+
}, null, 512);
|
|
14410
|
+
};
|
|
14411
|
+
}
|
|
14412
|
+
});
|
|
14413
|
+
const buildSocketMessageFrameHeader = (event, payloadLength) => {
|
|
14414
|
+
const headerObj = { event, length: payloadLength };
|
|
14415
|
+
const headerJson = JSON.stringify(headerObj);
|
|
14416
|
+
const headerBytes = new TextEncoder().encode(headerJson);
|
|
14417
|
+
const headerLength = new Uint32Array([headerBytes.length]);
|
|
14418
|
+
const headerLengthBytes = new Uint8Array(headerLength.buffer);
|
|
14419
|
+
const result2 = new Uint8Array(4 + headerBytes.length);
|
|
14420
|
+
result2.set(headerLengthBytes, 0);
|
|
14421
|
+
result2.set(headerBytes, 4);
|
|
14422
|
+
return result2;
|
|
14423
|
+
};
|
|
14424
|
+
function useVoiceRecorder(options) {
|
|
14425
|
+
const socket = ref(null);
|
|
14426
|
+
const mediaStream = ref(null);
|
|
14427
|
+
const mediaRecorder = ref(null);
|
|
14428
|
+
const isRecording = ref(false);
|
|
14429
|
+
const errorRef = ref(null);
|
|
14430
|
+
const transcription = ref("");
|
|
14431
|
+
const timeSliceLength = computed(() => {
|
|
14432
|
+
var _a;
|
|
14433
|
+
return (_a = options.timesliceLength) != null ? _a : 1e3;
|
|
14434
|
+
});
|
|
14435
|
+
onBeforeUnmount(() => {
|
|
14436
|
+
closeSocket();
|
|
14437
|
+
stopRecording();
|
|
14438
|
+
});
|
|
14439
|
+
const initSocket = (url, onMessage) => {
|
|
14440
|
+
socket.value = new WebSocket(url);
|
|
14441
|
+
socket.value.onopen = () => __async2(this, null, function* () {
|
|
14442
|
+
var _a;
|
|
14443
|
+
if (((_a = mediaRecorder.value) == null ? void 0 : _a.state) !== "recording") {
|
|
14444
|
+
yield startRecording();
|
|
14445
|
+
}
|
|
14446
|
+
});
|
|
14447
|
+
socket.value.onmessage = (event) => {
|
|
14448
|
+
const msg = JSON.parse(event.data);
|
|
14449
|
+
if (msg.event === "transcription") {
|
|
14450
|
+
transcription.value = msg.transcription;
|
|
14451
|
+
onMessage == null ? void 0 : onMessage(msg.transcription);
|
|
14452
|
+
stopSocketConnection();
|
|
14453
|
+
} else if (msg.event === "error") {
|
|
14454
|
+
errorRef.value = "Server error during transcription";
|
|
14455
|
+
stopRecording();
|
|
14456
|
+
}
|
|
14457
|
+
};
|
|
14458
|
+
socket.value.onclose = () => {
|
|
14459
|
+
stopRecording();
|
|
14460
|
+
};
|
|
14461
|
+
socket.value.onerror = () => {
|
|
14462
|
+
stopRecording();
|
|
14463
|
+
errorRef.value = "Service connection error";
|
|
14464
|
+
};
|
|
14465
|
+
};
|
|
14466
|
+
const onMediaRecorderDataAvailable = (event) => __async2(this, null, function* () {
|
|
14467
|
+
var _a, _b;
|
|
14468
|
+
if (((_a = mediaRecorder.value) == null ? void 0 : _a.state) !== "recording")
|
|
14469
|
+
return;
|
|
14470
|
+
const audioBuffer = yield event.data.arrayBuffer();
|
|
14471
|
+
const header = buildSocketMessageFrameHeader("audio-chunk", audioBuffer.byteLength);
|
|
14472
|
+
const buffer = new Uint8Array(header.length + audioBuffer.byteLength);
|
|
14473
|
+
buffer.set(header, 0);
|
|
14474
|
+
buffer.set(new Uint8Array(audioBuffer), header.length);
|
|
14475
|
+
(_b = socket.value) == null ? void 0 : _b.send(buffer);
|
|
14476
|
+
});
|
|
14477
|
+
const startRecording = () => __async2(this, null, function* () {
|
|
14478
|
+
mediaStream.value = yield navigator.mediaDevices.getUserMedia({
|
|
14479
|
+
video: false,
|
|
14480
|
+
audio: {
|
|
14481
|
+
channelCount: 1,
|
|
14482
|
+
echoCancellation: true,
|
|
14483
|
+
sampleRate: 16e3
|
|
14484
|
+
}
|
|
14485
|
+
});
|
|
14486
|
+
mediaRecorder.value = new MediaRecorder(mediaStream.value, {
|
|
14487
|
+
mimeType: "audio/webm; codecs=opus"
|
|
14488
|
+
});
|
|
14489
|
+
mediaRecorder.value.ondataavailable = onMediaRecorderDataAvailable;
|
|
14490
|
+
mediaRecorder.value.start(timeSliceLength.value);
|
|
14491
|
+
isRecording.value = true;
|
|
14492
|
+
});
|
|
14493
|
+
const stopRecording = () => {
|
|
14494
|
+
var _a, _b;
|
|
14495
|
+
(_a = mediaRecorder.value) == null ? void 0 : _a.stop();
|
|
14496
|
+
(_b = mediaStream.value) == null ? void 0 : _b.getTracks().forEach((track2) => {
|
|
14497
|
+
track2.stop();
|
|
14498
|
+
});
|
|
14499
|
+
isRecording.value = false;
|
|
14500
|
+
};
|
|
14501
|
+
const stopSocketConnection = () => {
|
|
14502
|
+
if (socket.value && socket.value.readyState === WebSocket.OPEN) {
|
|
14503
|
+
const endHeader = buildSocketMessageFrameHeader("audio-chunk-end", 0);
|
|
14504
|
+
socket.value.send(endHeader);
|
|
14505
|
+
setTimeout(() => {
|
|
14506
|
+
closeSocket();
|
|
14507
|
+
}, 1e3);
|
|
14508
|
+
}
|
|
14509
|
+
};
|
|
14510
|
+
const closeSocket = () => {
|
|
14511
|
+
var _a;
|
|
14512
|
+
(_a = socket.value) == null ? void 0 : _a.close();
|
|
14513
|
+
socket.value = null;
|
|
14514
|
+
};
|
|
14515
|
+
const reset = () => {
|
|
14516
|
+
stopRecording();
|
|
14517
|
+
closeSocket();
|
|
14518
|
+
transcription.value = "";
|
|
14519
|
+
errorRef.value = null;
|
|
14520
|
+
isRecording.value = false;
|
|
14521
|
+
};
|
|
14522
|
+
return {
|
|
14523
|
+
isRecording,
|
|
14524
|
+
transcription,
|
|
14525
|
+
errorRef,
|
|
14526
|
+
initSocket,
|
|
14527
|
+
startRecording,
|
|
14528
|
+
stopRecording,
|
|
14529
|
+
stopSocketConnection,
|
|
14530
|
+
reset,
|
|
14531
|
+
closeSocket
|
|
14532
|
+
};
|
|
14533
|
+
}
|
|
14534
|
+
const _hoisted_1$1l = {
|
|
14535
|
+
key: 0,
|
|
14536
|
+
class: "lupa-dialog-overlay"
|
|
14537
|
+
};
|
|
14538
|
+
const _hoisted_2$W = { class: "lupa-dialog-content" };
|
|
14539
|
+
const _hoisted_3$F = { class: "lupa-listening-text" };
|
|
14540
|
+
const _hoisted_4$v = { class: "lupa-mic-button-wrapper" };
|
|
14541
|
+
const _sfc_main$1y = /* @__PURE__ */ defineComponent({
|
|
14542
|
+
__name: "VoiceSearchDialog",
|
|
14543
|
+
props: {
|
|
14544
|
+
isOpen: { type: Boolean },
|
|
14545
|
+
options: {}
|
|
14546
|
+
},
|
|
14547
|
+
emits: [
|
|
14548
|
+
"close",
|
|
14549
|
+
"transcript-update",
|
|
14550
|
+
"stop-recognize"
|
|
14551
|
+
],
|
|
14552
|
+
setup(__props, { expose: __expose, emit: emit2 }) {
|
|
14553
|
+
const props = __props;
|
|
14554
|
+
const optionsStore = useOptionsStore();
|
|
14555
|
+
const {
|
|
14556
|
+
isRecording,
|
|
14557
|
+
transcription,
|
|
14558
|
+
errorRef,
|
|
14559
|
+
initSocket,
|
|
14560
|
+
stopSocketConnection,
|
|
14561
|
+
reset
|
|
14562
|
+
} = useVoiceRecorder(props.options);
|
|
14563
|
+
const clientId = ref(null);
|
|
14564
|
+
const voiceSearchProgressBar = ref(null);
|
|
14565
|
+
const timesliceLimit = computed(() => {
|
|
14566
|
+
var _a;
|
|
14567
|
+
return (_a = props.options.timesliceLimit) != null ? _a : 4;
|
|
14568
|
+
});
|
|
14569
|
+
const timeSliceLength = computed(() => {
|
|
14570
|
+
var _a;
|
|
14571
|
+
return (_a = props.options.timesliceLength) != null ? _a : 1e3;
|
|
14572
|
+
});
|
|
14573
|
+
const stopDelay = computed(() => {
|
|
14574
|
+
var _a;
|
|
14575
|
+
return (_a = props.options.stopDelay) != null ? _a : 700;
|
|
14576
|
+
});
|
|
14577
|
+
const labels = computed(() => {
|
|
14578
|
+
var _a;
|
|
14579
|
+
return (_a = props.options.labels) != null ? _a : {};
|
|
14580
|
+
});
|
|
14581
|
+
const description = computed(() => {
|
|
14582
|
+
var _a, _b, _c;
|
|
14583
|
+
if (errorRef.value) {
|
|
14584
|
+
return (_a = labels.value.serviceError) != null ? _a : errorRef.value;
|
|
14585
|
+
}
|
|
14586
|
+
if (!isRecording.value) {
|
|
14587
|
+
return (_b = labels.value.microphoneOff) != null ? _b : "Microphone is off. Try again.";
|
|
14588
|
+
}
|
|
14589
|
+
return (_c = labels.value.listening) != null ? _c : "Listening...";
|
|
14590
|
+
});
|
|
14591
|
+
watch(transcription, (newValue) => {
|
|
14592
|
+
emit2("transcript-update", newValue);
|
|
14593
|
+
});
|
|
14594
|
+
const handleRecordingButtonClick = () => {
|
|
14595
|
+
var _a, _b;
|
|
14596
|
+
if (isRecording.value) {
|
|
14597
|
+
setTimeout(() => {
|
|
14598
|
+
stopSocketConnection();
|
|
14599
|
+
handleOnStopEvent();
|
|
14600
|
+
}, stopDelay.value);
|
|
14601
|
+
return;
|
|
14602
|
+
}
|
|
14603
|
+
const voiceServiceUrl = getVoiceServiceApiUrl(
|
|
14604
|
+
optionsStore.envOptions.environment,
|
|
14605
|
+
props.options.customVoiceServiceUrl
|
|
14606
|
+
);
|
|
14607
|
+
const socketUrl = `${voiceServiceUrl}?clientId=${clientId.value}&queryKey=${props.options.queryKey}&languageCode=${(_a = props.options.language) != null ? _a : "en-US"}&connectionType=write-first`;
|
|
14608
|
+
initSocket(socketUrl);
|
|
14609
|
+
(_b = voiceSearchProgressBar.value) == null ? void 0 : _b.startProgressBar();
|
|
14610
|
+
setTimeout(() => {
|
|
14611
|
+
stopSocketConnection();
|
|
14612
|
+
handleOnStopEvent();
|
|
14613
|
+
}, timesliceLimit.value * timeSliceLength.value);
|
|
14614
|
+
};
|
|
14615
|
+
const handleOnStopEvent = () => {
|
|
14616
|
+
var _a;
|
|
14617
|
+
setTimeout(() => {
|
|
14618
|
+
if (errorRef.value)
|
|
14619
|
+
return;
|
|
14620
|
+
emit2("stop-recognize", transcription.value);
|
|
14621
|
+
}, 1500);
|
|
14622
|
+
(_a = voiceSearchProgressBar.value) == null ? void 0 : _a.stopProgressBar();
|
|
14623
|
+
};
|
|
14624
|
+
onMounted(() => {
|
|
14625
|
+
clientId.value = getSocketClientId();
|
|
14626
|
+
});
|
|
14627
|
+
onBeforeUnmount(() => {
|
|
14628
|
+
clientId.value = null;
|
|
14629
|
+
});
|
|
14630
|
+
const dialogReset = () => {
|
|
14631
|
+
var _a;
|
|
14632
|
+
reset();
|
|
14633
|
+
(_a = voiceSearchProgressBar.value) == null ? void 0 : _a.stopProgressBar();
|
|
14634
|
+
};
|
|
14635
|
+
__expose({
|
|
14636
|
+
handleRecordingButtonClick,
|
|
14637
|
+
reset: dialogReset
|
|
14638
|
+
});
|
|
14639
|
+
return (_ctx, _cache) => {
|
|
14640
|
+
return openBlock(), createElementBlock("div", null, [
|
|
14641
|
+
props.isOpen ? (openBlock(), createElementBlock("div", _hoisted_1$1l, [
|
|
14642
|
+
createBaseVNode("button", {
|
|
14643
|
+
class: "lupa-dialog-box-close-button",
|
|
14644
|
+
onClick: _cache[0] || (_cache[0] = () => emit2("close"))
|
|
14645
|
+
}),
|
|
14646
|
+
createBaseVNode("div", _hoisted_2$W, [
|
|
14647
|
+
createBaseVNode("p", _hoisted_3$F, toDisplayString(description.value), 1),
|
|
14648
|
+
createBaseVNode("div", _hoisted_4$v, [
|
|
14649
|
+
createBaseVNode("button", {
|
|
14650
|
+
class: normalizeClass(["lupa-mic-button", { recording: unref(isRecording) }]),
|
|
14651
|
+
onClick: handleRecordingButtonClick
|
|
14652
|
+
}, null, 2),
|
|
14653
|
+
createVNode(_sfc_main$1z, {
|
|
14654
|
+
ref_key: "voiceSearchProgressBar",
|
|
14655
|
+
ref: voiceSearchProgressBar,
|
|
14656
|
+
class: "lupa-progress-circle",
|
|
14657
|
+
isRecording: unref(isRecording),
|
|
14658
|
+
timesliceLimit: timesliceLimit.value,
|
|
14659
|
+
timeSliceLength: timeSliceLength.value
|
|
14660
|
+
}, null, 8, ["isRecording", "timesliceLimit", "timeSliceLength"])
|
|
14661
|
+
])
|
|
14662
|
+
])
|
|
14663
|
+
])) : createCommentVNode("", true)
|
|
14664
|
+
]);
|
|
14665
|
+
};
|
|
14666
|
+
}
|
|
14667
|
+
});
|
|
14315
14668
|
const _hoisted_1$1k = { id: "lupa-search-box-input-container" };
|
|
14316
14669
|
const _hoisted_2$V = { class: "lupa-input-clear" };
|
|
14317
14670
|
const _hoisted_3$E = { id: "lupa-search-box-input" };
|
|
@@ -14325,6 +14678,7 @@ const _hoisted_8$3 = {
|
|
|
14325
14678
|
key: 0,
|
|
14326
14679
|
class: "lupa-close-label"
|
|
14327
14680
|
};
|
|
14681
|
+
const _hoisted_9$3 = { key: 1 };
|
|
14328
14682
|
const _sfc_main$1x = /* @__PURE__ */ defineComponent({
|
|
14329
14683
|
__name: "SearchBoxInput",
|
|
14330
14684
|
props: {
|
|
@@ -14340,6 +14694,8 @@ const _sfc_main$1x = /* @__PURE__ */ defineComponent({
|
|
|
14340
14694
|
const searchBoxStore = useSearchBoxStore();
|
|
14341
14695
|
const { query } = storeToRefs(paramStore);
|
|
14342
14696
|
const mainInput = ref(null);
|
|
14697
|
+
const voiceDialogOverlay = ref(null);
|
|
14698
|
+
const isVoiceDialogOpen = ref(false);
|
|
14343
14699
|
const emitInputOnFocus = computed(() => {
|
|
14344
14700
|
var _a;
|
|
14345
14701
|
return (_a = props.emitInputOnFocus) != null ? _a : true;
|
|
@@ -14350,6 +14706,10 @@ const _sfc_main$1x = /* @__PURE__ */ defineComponent({
|
|
|
14350
14706
|
return (_a = props.suggestedValue) != null ? _a : { value: "", override: false, item: { suggestion: "" } };
|
|
14351
14707
|
}
|
|
14352
14708
|
);
|
|
14709
|
+
const isVoiceSearchEnabled = computed(() => {
|
|
14710
|
+
var _a, _b;
|
|
14711
|
+
return (_b = (_a = props.options.voiceSearch) == null ? void 0 : _a.enabled) != null ? _b : false;
|
|
14712
|
+
});
|
|
14353
14713
|
const labels = computed(() => props.options.labels);
|
|
14354
14714
|
const input2 = ref("");
|
|
14355
14715
|
const inputValue = computed({
|
|
@@ -14373,6 +14733,12 @@ const _sfc_main$1x = /* @__PURE__ */ defineComponent({
|
|
|
14373
14733
|
var _a;
|
|
14374
14734
|
return (_a = labels.value.searchInputAriaLabel) != null ? _a : "Search input";
|
|
14375
14735
|
});
|
|
14736
|
+
onMounted(() => {
|
|
14737
|
+
document.addEventListener("click", handleClickOutsideVoiceDialogOverlay);
|
|
14738
|
+
});
|
|
14739
|
+
onBeforeUnmount(() => {
|
|
14740
|
+
document.removeEventListener("click", handleClickOutsideVoiceDialogOverlay);
|
|
14741
|
+
});
|
|
14376
14742
|
watch(suggestedValue, () => {
|
|
14377
14743
|
if (suggestedValue.value.override) {
|
|
14378
14744
|
input2.value = suggestedValue.value.item.suggestion;
|
|
@@ -14407,6 +14773,37 @@ const _sfc_main$1x = /* @__PURE__ */ defineComponent({
|
|
|
14407
14773
|
}
|
|
14408
14774
|
(_a = mainInput == null ? void 0 : mainInput.value) == null ? void 0 : _a.focus();
|
|
14409
14775
|
};
|
|
14776
|
+
const openVoiceSearchDialog = () => {
|
|
14777
|
+
var _a;
|
|
14778
|
+
isVoiceDialogOpen.value = true;
|
|
14779
|
+
(_a = voiceDialogOverlay.value) == null ? void 0 : _a.handleRecordingButtonClick();
|
|
14780
|
+
};
|
|
14781
|
+
const closeDialog = () => {
|
|
14782
|
+
var _a;
|
|
14783
|
+
isVoiceDialogOpen.value = false;
|
|
14784
|
+
(_a = voiceDialogOverlay.value) == null ? void 0 : _a.reset();
|
|
14785
|
+
};
|
|
14786
|
+
const handleVoiceSearchOutput = (transcription) => {
|
|
14787
|
+
inputValue.value = transcription;
|
|
14788
|
+
handleSubmit();
|
|
14789
|
+
};
|
|
14790
|
+
const stopRecognition = (trascription) => {
|
|
14791
|
+
setTimeout(() => {
|
|
14792
|
+
isVoiceDialogOpen.value = false;
|
|
14793
|
+
handleVoiceSearchOutput(trascription);
|
|
14794
|
+
}, 500);
|
|
14795
|
+
};
|
|
14796
|
+
const handleClickOutsideVoiceDialogOverlay = (event) => {
|
|
14797
|
+
if (event.target.classList.contains("lupa-voice-search-button")) {
|
|
14798
|
+
return;
|
|
14799
|
+
}
|
|
14800
|
+
if (voiceDialogOverlay.value && voiceDialogOverlay.value.$el.contains(event.target)) {
|
|
14801
|
+
return;
|
|
14802
|
+
}
|
|
14803
|
+
if (isVoiceDialogOpen.value) {
|
|
14804
|
+
closeDialog();
|
|
14805
|
+
}
|
|
14806
|
+
};
|
|
14410
14807
|
__expose({ focus });
|
|
14411
14808
|
return (_ctx, _cache) => {
|
|
14412
14809
|
return openBlock(), createElementBlock("div", _hoisted_1$1k, [
|
|
@@ -14450,7 +14847,23 @@ const _sfc_main$1x = /* @__PURE__ */ defineComponent({
|
|
|
14450
14847
|
onClick: _cache[1] || (_cache[1] = ($event) => _ctx.$emit("close"))
|
|
14451
14848
|
}, [
|
|
14452
14849
|
labels.value.close ? (openBlock(), createElementBlock("span", _hoisted_8$3, toDisplayString(labels.value.close), 1)) : createCommentVNode("", true)
|
|
14453
|
-
])) : createCommentVNode("", true)
|
|
14850
|
+
])) : createCommentVNode("", true),
|
|
14851
|
+
isVoiceSearchEnabled.value ? (openBlock(), createElementBlock("div", _hoisted_9$3, [
|
|
14852
|
+
createBaseVNode("button", {
|
|
14853
|
+
onClick: openVoiceSearchDialog,
|
|
14854
|
+
class: "lupa-voice-search-button"
|
|
14855
|
+
})
|
|
14856
|
+
])) : createCommentVNode("", true),
|
|
14857
|
+
isVoiceSearchEnabled.value ? (openBlock(), createBlock(_sfc_main$1y, {
|
|
14858
|
+
key: 2,
|
|
14859
|
+
ref_key: "voiceDialogOverlay",
|
|
14860
|
+
ref: voiceDialogOverlay,
|
|
14861
|
+
isOpen: isVoiceDialogOpen.value,
|
|
14862
|
+
options: props.options.voiceSearch,
|
|
14863
|
+
onClose: closeDialog,
|
|
14864
|
+
onTranscriptUpdate: handleVoiceSearchOutput,
|
|
14865
|
+
onStopRecognize: stopRecognition
|
|
14866
|
+
}, null, 8, ["isOpen", "options"])) : createCommentVNode("", true)
|
|
14454
14867
|
]);
|
|
14455
14868
|
};
|
|
14456
14869
|
}
|
|
@@ -25989,7 +26402,8 @@ const _sfc_main$12 = /* @__PURE__ */ defineComponent({
|
|
|
25989
26402
|
"labels",
|
|
25990
26403
|
"links",
|
|
25991
26404
|
"inputAttributes",
|
|
25992
|
-
"showSubmitButton"
|
|
26405
|
+
"showSubmitButton",
|
|
26406
|
+
"voiceSearch"
|
|
25993
26407
|
])
|
|
25994
26408
|
);
|
|
25995
26409
|
const panelOptions = computed(
|
|
@@ -26573,22 +26987,42 @@ const _sfc_main$_ = /* @__PURE__ */ defineComponent({
|
|
|
26573
26987
|
emits: ["remove"],
|
|
26574
26988
|
setup(__props, { emit: emit2 }) {
|
|
26575
26989
|
const props = __props;
|
|
26576
|
-
const facetKeyClass = computed(() => {
|
|
26577
|
-
|
|
26990
|
+
const facetKeyClass = computed(() => `lupa-facet-active-filter-${props.filter.key}`);
|
|
26991
|
+
const { searchResultOptions } = storeToRefs(useOptionsStore());
|
|
26992
|
+
const units = computed(() => {
|
|
26993
|
+
var _a, _b, _c, _d, _e;
|
|
26994
|
+
return (_e = (_d = (_c = (_b = (_a = searchResultOptions.value) == null ? void 0 : _a.filters) == null ? void 0 : _b.facets) == null ? void 0 : _c.stats) == null ? void 0 : _d.units) != null ? _e : {};
|
|
26578
26995
|
});
|
|
26579
|
-
|
|
26996
|
+
function handleClick() {
|
|
26580
26997
|
emit2("remove", { filter: props.filter });
|
|
26581
|
-
}
|
|
26998
|
+
}
|
|
26999
|
+
function formatFilterValue(filter2) {
|
|
27000
|
+
const unit = units.value[filter2.key] || "";
|
|
27001
|
+
let min, max;
|
|
27002
|
+
if (Array.isArray(filter2.value)) {
|
|
27003
|
+
[min, max] = filter2.value.map(String);
|
|
27004
|
+
} else if (typeof filter2.value === "string" && filter2.value.includes("-")) {
|
|
27005
|
+
const parts = filter2.value.split("-").map((s) => s.trim());
|
|
27006
|
+
if (parts.length === 2)
|
|
27007
|
+
[min, max] = parts;
|
|
27008
|
+
}
|
|
27009
|
+
if (min != null && max != null) {
|
|
27010
|
+
return `${min} ${unit} – ${max} ${unit}`;
|
|
27011
|
+
}
|
|
27012
|
+
return `${filter2.value} ${unit}`.trim();
|
|
27013
|
+
}
|
|
26582
27014
|
return (_ctx, _cache) => {
|
|
26583
27015
|
return openBlock(), createElementBlock("div", {
|
|
26584
|
-
class: normalizeClass(["lupa-search-result-filter-value",
|
|
27016
|
+
class: normalizeClass(["lupa-search-result-filter-value", [facetKeyClass.value]]),
|
|
27017
|
+
"data-cy": "lupa-current-filter-item"
|
|
26585
27018
|
}, [
|
|
26586
27019
|
createBaseVNode("div", {
|
|
26587
27020
|
class: "lupa-current-filter-action",
|
|
26588
|
-
onClick: handleClick
|
|
26589
|
-
|
|
27021
|
+
onClick: handleClick,
|
|
27022
|
+
"aria-label": "Remove filter"
|
|
27023
|
+
}, " ⨉ "),
|
|
26590
27024
|
createBaseVNode("div", _hoisted_1$U, toDisplayString(_ctx.filter.label) + ": ", 1),
|
|
26591
|
-
createBaseVNode("div", _hoisted_2$F, toDisplayString(
|
|
27025
|
+
createBaseVNode("div", _hoisted_2$F, toDisplayString(formatFilterValue(props.filter)), 1)
|
|
26592
27026
|
], 2);
|
|
26593
27027
|
};
|
|
26594
27028
|
}
|
|
@@ -26610,6 +27044,14 @@ const _sfc_main$Z = /* @__PURE__ */ defineComponent({
|
|
|
26610
27044
|
expandable: { type: Boolean }
|
|
26611
27045
|
},
|
|
26612
27046
|
setup(__props) {
|
|
27047
|
+
const optionsStore = useOptionsStore();
|
|
27048
|
+
const { searchResultOptions } = storeToRefs(optionsStore);
|
|
27049
|
+
const units = computed(
|
|
27050
|
+
() => {
|
|
27051
|
+
var _a, _b, _c, _d, _e;
|
|
27052
|
+
return (_e = (_d = (_c = (_b = (_a = searchResultOptions == null ? void 0 : searchResultOptions.value) == null ? void 0 : _a.filters) == null ? void 0 : _b.facets) == null ? void 0 : _c.stats) == null ? void 0 : _d.units) != null ? _e : {};
|
|
27053
|
+
}
|
|
27054
|
+
);
|
|
26613
27055
|
const isOpen = ref(false);
|
|
26614
27056
|
const paramsStore = useParamsStore();
|
|
26615
27057
|
const optionStore = useOptionsStore();
|
|
@@ -26691,8 +27133,9 @@ const _sfc_main$Z = /* @__PURE__ */ defineComponent({
|
|
|
26691
27133
|
return openBlock(), createBlock(_sfc_main$_, {
|
|
26692
27134
|
key: filter2.key + "_" + filter2.value,
|
|
26693
27135
|
filter: filter2,
|
|
27136
|
+
units: units.value,
|
|
26694
27137
|
onRemove: handleRemove
|
|
26695
|
-
}, null, 8, ["filter"]);
|
|
27138
|
+
}, null, 8, ["filter", "units"]);
|
|
26696
27139
|
}), 128))
|
|
26697
27140
|
]),
|
|
26698
27141
|
createBaseVNode("div", {
|
|
@@ -28016,15 +28459,17 @@ const _hoisted_4$j = {
|
|
|
28016
28459
|
const _hoisted_5$d = { class: "lupa-stats-from" };
|
|
28017
28460
|
const _hoisted_6$7 = ["max", "min", "pattern", "aria-label"];
|
|
28018
28461
|
const _hoisted_7$5 = { key: 0 };
|
|
28019
|
-
const _hoisted_8$1 =
|
|
28020
|
-
const _hoisted_9$1 = {
|
|
28462
|
+
const _hoisted_8$1 = { key: 1 };
|
|
28463
|
+
const _hoisted_9$1 = /* @__PURE__ */ createBaseVNode("div", { class: "lupa-stats-separator" }, null, -1);
|
|
28464
|
+
const _hoisted_10 = {
|
|
28021
28465
|
key: 0,
|
|
28022
28466
|
class: "lupa-stats-range-label"
|
|
28023
28467
|
};
|
|
28024
|
-
const
|
|
28025
|
-
const
|
|
28026
|
-
const
|
|
28027
|
-
const
|
|
28468
|
+
const _hoisted_11 = { class: "lupa-stats-to" };
|
|
28469
|
+
const _hoisted_12 = ["max", "min", "pattern", "aria-label"];
|
|
28470
|
+
const _hoisted_13 = { key: 0 };
|
|
28471
|
+
const _hoisted_14 = { key: 1 };
|
|
28472
|
+
const _hoisted_15 = {
|
|
28028
28473
|
key: 2,
|
|
28029
28474
|
class: "lupa-stats-slider-wrapper"
|
|
28030
28475
|
};
|
|
@@ -28091,7 +28536,7 @@ const _sfc_main$V = /* @__PURE__ */ defineComponent({
|
|
|
28091
28536
|
if (!value || value > facetMax.value) {
|
|
28092
28537
|
return;
|
|
28093
28538
|
}
|
|
28094
|
-
innerSliderRange.value = [
|
|
28539
|
+
innerSliderRange.value = [sliderRange.value[1], value];
|
|
28095
28540
|
handleInputChange();
|
|
28096
28541
|
}
|
|
28097
28542
|
});
|
|
@@ -28147,7 +28592,18 @@ const _sfc_main$V = /* @__PURE__ */ defineComponent({
|
|
|
28147
28592
|
});
|
|
28148
28593
|
const statsSummary = computed(() => {
|
|
28149
28594
|
const [min, max] = sliderRange.value;
|
|
28150
|
-
|
|
28595
|
+
if (isPrice.value) {
|
|
28596
|
+
return formatPriceSummary(
|
|
28597
|
+
[min, max],
|
|
28598
|
+
currency.value,
|
|
28599
|
+
separator.value,
|
|
28600
|
+
currencyTemplate.value
|
|
28601
|
+
);
|
|
28602
|
+
}
|
|
28603
|
+
if (unit.value) {
|
|
28604
|
+
return `${min} ${unit.value} - ${max} ${unit.value}`;
|
|
28605
|
+
}
|
|
28606
|
+
return formatRange({ gte: min, lte: max });
|
|
28151
28607
|
});
|
|
28152
28608
|
const separator = computed(() => {
|
|
28153
28609
|
var _a, _b, _c;
|
|
@@ -28208,6 +28664,12 @@ const _sfc_main$V = /* @__PURE__ */ defineComponent({
|
|
|
28208
28664
|
const handleDragging = (value) => {
|
|
28209
28665
|
innerSliderRange.value = value;
|
|
28210
28666
|
};
|
|
28667
|
+
const unit = computed(
|
|
28668
|
+
() => {
|
|
28669
|
+
var _a, _b, _c, _d, _e;
|
|
28670
|
+
return (_e = (_d = (_a = props.options.stats) == null ? void 0 : _a.units) == null ? void 0 : _d[(_c = (_b = props.facet) == null ? void 0 : _b.key) != null ? _c : ""]) != null ? _e : "";
|
|
28671
|
+
}
|
|
28672
|
+
);
|
|
28211
28673
|
return (_ctx, _cache) => {
|
|
28212
28674
|
return openBlock(), createElementBlock("div", _hoisted_1$P, [
|
|
28213
28675
|
!isInputVisible.value ? (openBlock(), createElementBlock("div", _hoisted_2$B, toDisplayString(statsSummary.value), 1)) : (openBlock(), createElementBlock("div", _hoisted_3$s, [
|
|
@@ -28230,13 +28692,14 @@ const _sfc_main$V = /* @__PURE__ */ defineComponent({
|
|
|
28230
28692
|
{ lazy: true }
|
|
28231
28693
|
]
|
|
28232
28694
|
]),
|
|
28233
|
-
isPrice.value ? (openBlock(), createElementBlock("span", _hoisted_7$5, toDisplayString(currency.value), 1)) : createCommentVNode("", true)
|
|
28695
|
+
isPrice.value ? (openBlock(), createElementBlock("span", _hoisted_7$5, toDisplayString(currency.value), 1)) : createCommentVNode("", true),
|
|
28696
|
+
unit.value ? (openBlock(), createElementBlock("span", _hoisted_8$1, toDisplayString(unit.value), 1)) : createCommentVNode("", true)
|
|
28234
28697
|
])
|
|
28235
28698
|
]),
|
|
28236
|
-
|
|
28699
|
+
_hoisted_9$1,
|
|
28237
28700
|
createBaseVNode("div", null, [
|
|
28238
|
-
rangeLabelTo.value ? (openBlock(), createElementBlock("div",
|
|
28239
|
-
createBaseVNode("div",
|
|
28701
|
+
rangeLabelTo.value ? (openBlock(), createElementBlock("div", _hoisted_10, toDisplayString(rangeLabelTo.value), 1)) : createCommentVNode("", true),
|
|
28702
|
+
createBaseVNode("div", _hoisted_11, [
|
|
28240
28703
|
withDirectives(createBaseVNode("input", {
|
|
28241
28704
|
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => toValue.value = $event),
|
|
28242
28705
|
type: "text",
|
|
@@ -28245,7 +28708,7 @@ const _sfc_main$V = /* @__PURE__ */ defineComponent({
|
|
|
28245
28708
|
min: facetMin.value,
|
|
28246
28709
|
pattern: sliderInputFormat.value,
|
|
28247
28710
|
"aria-label": ariaLabelTo.value
|
|
28248
|
-
}, null, 8,
|
|
28711
|
+
}, null, 8, _hoisted_12), [
|
|
28249
28712
|
[
|
|
28250
28713
|
vModelText,
|
|
28251
28714
|
toValue.value,
|
|
@@ -28253,11 +28716,12 @@ const _sfc_main$V = /* @__PURE__ */ defineComponent({
|
|
|
28253
28716
|
{ lazy: true }
|
|
28254
28717
|
]
|
|
28255
28718
|
]),
|
|
28256
|
-
isPrice.value ? (openBlock(), createElementBlock("span",
|
|
28719
|
+
isPrice.value ? (openBlock(), createElementBlock("span", _hoisted_13, toDisplayString(currency.value), 1)) : createCommentVNode("", true),
|
|
28720
|
+
unit.value ? (openBlock(), createElementBlock("span", _hoisted_14, toDisplayString(unit.value), 1)) : createCommentVNode("", true)
|
|
28257
28721
|
])
|
|
28258
28722
|
])
|
|
28259
28723
|
])),
|
|
28260
|
-
isSliderVisible.value ? (openBlock(), createElementBlock("div",
|
|
28724
|
+
isSliderVisible.value ? (openBlock(), createElementBlock("div", _hoisted_15, [
|
|
28261
28725
|
createVNode(unref(m), {
|
|
28262
28726
|
class: "slider",
|
|
28263
28727
|
tooltips: false,
|
|
@@ -33160,21 +33624,6 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
|
|
|
33160
33624
|
};
|
|
33161
33625
|
}
|
|
33162
33626
|
});
|
|
33163
|
-
const Env = {
|
|
33164
|
-
production: "https://api.lupasearch.com/v1/",
|
|
33165
|
-
staging: "https://api.staging.lupasearch.com/v1/"
|
|
33166
|
-
};
|
|
33167
|
-
const DEFAULT_REQUEST_CONFIG = {
|
|
33168
|
-
method: "POST",
|
|
33169
|
-
headers: { "Content-Type": "application/json" }
|
|
33170
|
-
};
|
|
33171
|
-
const DEFAULT_HEADERS = DEFAULT_REQUEST_CONFIG.headers;
|
|
33172
|
-
const getApiUrl = (environment, customBaseUrl) => {
|
|
33173
|
-
if (customBaseUrl) {
|
|
33174
|
-
return customBaseUrl;
|
|
33175
|
-
}
|
|
33176
|
-
return Env[environment] || Env["production"];
|
|
33177
|
-
};
|
|
33178
33627
|
const suggestSearchChatPhrases = (options, request, chatSettings) => __async2(void 0, null, function* () {
|
|
33179
33628
|
var _a, _b, _c;
|
|
33180
33629
|
const { environment, customBaseUrl } = options;
|
|
@@ -33681,7 +34130,7 @@ const _hoisted_4 = {
|
|
|
33681
34130
|
key: 0,
|
|
33682
34131
|
class: "lupasearch-chat-content"
|
|
33683
34132
|
};
|
|
33684
|
-
const _sfc_main$
|
|
34133
|
+
const _sfc_main$1A = /* @__PURE__ */ defineComponent({
|
|
33685
34134
|
__name: "ChatContainer",
|
|
33686
34135
|
props: {
|
|
33687
34136
|
options: {}
|
|
@@ -40335,7 +40784,7 @@ const chat = (options, mountOptions) => {
|
|
|
40335
40784
|
const instance = createVue(
|
|
40336
40785
|
options.displayOptions.containerSelector,
|
|
40337
40786
|
mountOptions == null ? void 0 : mountOptions.mountingBehavior,
|
|
40338
|
-
_sfc_main$
|
|
40787
|
+
_sfc_main$1A,
|
|
40339
40788
|
{
|
|
40340
40789
|
options
|
|
40341
40790
|
}
|