From b8e20e77ba0dbc5896d608ed1e74d32a07367e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Arenal?= Date: Mon, 20 Jan 2025 18:24:31 +0100 Subject: [PATCH 01/16] refactor(RelatedPrompt): component logic to be reusable --- .../related-prompts.endpoint-adapter.ts | 6 +- packages/x-components/src/directives/index.ts | 1 + .../x-components/src/directives/typing.ts | 84 ++++++ packages/x-components/src/views/home/Home.vue | 6 + .../components/related-prompt.vue | 56 +--- .../components/related-prompts-tag-list.vue | 276 ++++++------------ 6 files changed, 187 insertions(+), 242 deletions(-) create mode 100644 packages/x-components/src/directives/typing.ts diff --git a/packages/x-adapter-platform/src/endpoint-adapters/related-prompts.endpoint-adapter.ts b/packages/x-adapter-platform/src/endpoint-adapters/related-prompts.endpoint-adapter.ts index 65baab1d33..be191f0f08 100644 --- a/packages/x-adapter-platform/src/endpoint-adapters/related-prompts.endpoint-adapter.ts +++ b/packages/x-adapter-platform/src/endpoint-adapters/related-prompts.endpoint-adapter.ts @@ -14,9 +14,9 @@ export const relatedPromptsEndpointAdapter = endpointAdapterFactory< RelatedPromptsRequest, RelatedPromptsResponse >({ - endpoint: from => - interpolate(`${getBeaconServiceUrl(from)}/relatedprompts/{extraParams.instance}`, from), - requestMapper: relatedPromptsRequestMapper, + endpoint: + 'https://api.empathy.co/relatedprompts/mymotivemarketplace?store=Labstore+London&lang=en', + requestMapper: ({ query }) => ({ query }), responseMapper: relatedPromptsResponseMapper, defaultRequestOptions: { id: 'related-prompts', diff --git a/packages/x-components/src/directives/index.ts b/packages/x-components/src/directives/index.ts index 73717bd815..efe3f3a867 100644 --- a/packages/x-components/src/directives/index.ts +++ b/packages/x-components/src/directives/index.ts @@ -1 +1,2 @@ export * from './infinite-scroll'; +export * from './typing'; diff --git a/packages/x-components/src/directives/typing.ts b/packages/x-components/src/directives/typing.ts new file mode 100644 index 0000000000..25ed09355a --- /dev/null +++ b/packages/x-components/src/directives/typing.ts @@ -0,0 +1,84 @@ +import type { Directive } from 'vue'; + +export interface TypingOptions { + /** + * The text (plain or html) that will be typed into the target element. + */ + text: string; + /** + * The typing speed in milliseconds per character. + * + * @default 1 + */ + speed?: number; + /** + * The attribute of the HTML element where the typed text will be placed. + * If not specified, the text will be set as content (innerHTML). + * + * @example 'placeholder' + */ + targetAttr?: string; +} + +interface TypingHTMLElement extends HTMLElement { + __timeoutId?: number; +} + +const typingDirective: Directive = { + mounted(el, binding) { + execute(el, binding.value); + }, + + updated(el, binding) { + if (binding.value.text !== binding.oldValue?.text) { + clearTimeout(el.__timeoutId); + execute(el, binding.value); + } + }, + + unmounted(el) { + clearTimeout(el.__timeoutId); + } +}; + +/** + * Execute a typing animation in an HTML element. + * + * @param el - The HTML element where the typing animation will be displayed + * @param options - Options for the behavior of the animation. + */ +function execute(el: TypingHTMLElement, options: TypingOptions) { + const { text, speed = 1, targetAttr = '' } = options; + + if (!text) { + console.error('v-typing: "text" is required.'); + return; + } + + let index = 0; + el.__timeoutId = el.__timeoutId || undefined; + + const updateContent = (value: string) => { + if (targetAttr) { + el.setAttribute(targetAttr, value); + } else { + el.innerHTML = value; + } + }; + + const type = () => { + if (index < text.length) { + updateContent(text.slice(0, index + 1)); + index++; + el.__timeoutId = setTimeout(type, speed) as unknown as number; + } else { + updateContent(text); + clearTimeout(el.__timeoutId); + el.__timeoutId = undefined; + } + }; + + type(); +} + +export default typingDirective; diff --git a/packages/x-components/src/views/home/Home.vue b/packages/x-components/src/views/home/Home.vue index 7b1fd4b651..60468ef7ad 100644 --- a/packages/x-components/src/views/home/Home.vue +++ b/packages/x-components/src/views/home/Home.vue @@ -391,6 +391,12 @@ diff --git a/packages/x-components/src/x-modules/related-prompts/components/related-prompts-tag-list.vue b/packages/x-components/src/x-modules/related-prompts/components/related-prompts-tag-list.vue index 545e8d0329..d63ee1d387 100644 --- a/packages/x-components/src/x-modules/related-prompts/components/related-prompts-tag-list.vue +++ b/packages/x-components/src/x-modules/related-prompts/components/related-prompts-tag-list.vue @@ -1,65 +1,50 @@