diff --git a/packages/quantic/README.md b/packages/quantic/README.md index d1c92b7246d..224702de007 100644 --- a/packages/quantic/README.md +++ b/packages/quantic/README.md @@ -109,6 +109,20 @@ To get the [detailed report](./docs/detailed-reporting.md), run: npm run e2e:detailed ``` +### Run LWC unit tests for Quantic Components + +To run LWC unit tests directly in your console, run: + +```bash +npm run test:unit +``` + +To run specific file/components LWC unit tests directly in your console, run: + +```bash +npm run test:unit -p force-app/main/default/lwc/nameOfComponent/ +``` + ## Use Quantic From Source After you have cloned the repository and have run `npm install`, run the following commands: diff --git a/packages/quantic/cypress/e2e/default-2/standalone-search-box/standalone-search-box-expectations.ts b/packages/quantic/cypress/e2e/default-2/standalone-search-box/standalone-search-box-expectations.ts index a465c94e665..70f9980ffca 100644 --- a/packages/quantic/cypress/e2e/default-2/standalone-search-box/standalone-search-box-expectations.ts +++ b/packages/quantic/cypress/e2e/default-2/standalone-search-box/standalone-search-box-expectations.ts @@ -17,9 +17,9 @@ function standaloneSearchBoxExpectations( .should(display ? 'exist' : 'not.exist') .logDetail(`${should(display)} display the input search box`); }, - inputInitialized: (textarea = false) => { + inputInitialized: () => { selector - .input(textarea) + .quanticSearchBoxInput() .invoke('attr', 'is-initialized') .should('eq', 'true'); }, diff --git a/packages/quantic/cypress/e2e/default-2/standalone-search-box/standalone-search-box-selectors.ts b/packages/quantic/cypress/e2e/default-2/standalone-search-box/standalone-search-box-selectors.ts index b8a741a593b..3dce712f2bc 100644 --- a/packages/quantic/cypress/e2e/default-2/standalone-search-box/standalone-search-box-selectors.ts +++ b/packages/quantic/cypress/e2e/default-2/standalone-search-box/standalone-search-box-selectors.ts @@ -4,6 +4,7 @@ export const standaloneSearchBoxComponent = 'c-quantic-standalone-search-box'; export interface StandaloneSearchBoxSelector extends ComponentSelector { input: (textarea?: boolean) => CypressSelector; + quanticSearchBoxInput: () => CypressSelector; suggestionList: () => CypressSelector; clearButton: () => CypressSelector; searchIcon: () => CypressSelector; @@ -12,18 +13,30 @@ export interface StandaloneSearchBoxSelector extends ComponentSelector { export const StandaloneSearchBoxSelectors: StandaloneSearchBoxSelector = { get: () => cy.get(standaloneSearchBoxComponent), + quanticSearchBoxInput: () => + StandaloneSearchBoxSelectors.get().find( + '[data-cy="quantic-search-box-input"]' + ), input: (textarea = false) => StandaloneSearchBoxSelectors.get().find( - textarea ? 'textarea[type="search"]' : 'input[type="search"]' + textarea + ? 'c-quantic-search-box-input [data-cy="search-box-textarea"]' + : 'c-quantic-search-box-input [data-cy="search-box-input"]' ), suggestionList: () => StandaloneSearchBoxSelectors.get().find( - 'c-quantic-search-box-suggestions-list li' + 'c-quantic-search-box-input c-quantic-search-box-suggestions-list li' ), clearButton: () => - StandaloneSearchBoxSelectors.get().find('.searchbox__clear-button'), + StandaloneSearchBoxSelectors.get().find( + 'c-quantic-search-box-input [data-cy="search-box-clear-button"]' + ), searchIcon: () => - StandaloneSearchBoxSelectors.get().find('.searchbox__search-icon'), + StandaloneSearchBoxSelectors.get().find( + 'c-quantic-search-box-input [data-cy="search-box-search-icon"]' + ), searchButton: () => - StandaloneSearchBoxSelectors.get().find('.searchbox__submit-button'), + StandaloneSearchBoxSelectors.get().find( + 'c-quantic-search-box-input [data-cy="search-box-submit-button"]' + ), }; diff --git a/packages/quantic/force-app/main/default/lwc/jsconfig.json b/packages/quantic/force-app/main/default/lwc/jsconfig.json index ec94bfa6038..ea4731bac1a 100644 --- a/packages/quantic/force-app/main/default/lwc/jsconfig.json +++ b/packages/quantic/force-app/main/default/lwc/jsconfig.json @@ -57,6 +57,9 @@ "quanticResultsPerPage/quanticResultsPerPage.js" ], "c/quanticSearchBox": ["quanticSearchBox/quanticSearchBox.js"], + "c/quanticSearchBoxInput": [ + "quanticSearchBoxInput/quanticSearchBoxInput.js" + ], "c/quanticSearchBoxSuggestionsList": [ "quanticSearchBoxSuggestionsList/quanticSearchBoxSuggestionsList.js" ], diff --git a/packages/quantic/force-app/main/default/lwc/quanticSearchBox/quanticSearchBox.js b/packages/quantic/force-app/main/default/lwc/quanticSearchBox/quanticSearchBox.js index fab60fa443f..d4f49baa9c3 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSearchBox/quanticSearchBox.js +++ b/packages/quantic/force-app/main/default/lwc/quanticSearchBox/quanticSearchBox.js @@ -1,28 +1,19 @@ -import clear from '@salesforce/label/c.quantic_Clear'; -import search from '@salesforce/label/c.quantic_Search'; import { registerComponentForInit, initializeWithHeadless, getHeadlessBundle, } from 'c/quanticHeadlessLoader'; -import {keys} from 'c/quanticUtils'; import {LightningElement, api, track} from 'lwc'; // @ts-ignore -import defaultSearchBox from './templates/defaultSearchBox.html'; -// @ts-ignore import errorTemplate from './templates/errorTemplate.html'; // @ts-ignore -import expandableSearchBox from './templates/expandableSearchBox.html'; +import searchBox from './templates/searchBox.html'; /** @typedef {import("coveo").SearchEngine} SearchEngine */ /** @typedef {import("coveo").SearchBoxState} SearchBoxState */ /** @typedef {import("coveo").SearchBox} SearchBox */ /** @typedef {import('c/quanticSearchBoxSuggestionsList').default} quanticSearchBoxSuggestionsList */ - -const CLASS_WITH_SUBMIT = - 'slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right slds-input-has-fixed-addon'; -const CLASS_WITHOUT_SUBMIT = - 'slds-combobox__form-element slds-input-has-icon slds-input-has-icon_left-right'; +/** @typedef {import("c/quanticSearchBoxInput").default} quanticSearchBoxInput */ /** * The `QuanticSearchBox` component creates a search box with built-in support for query suggestions. @@ -32,11 +23,6 @@ const CLASS_WITHOUT_SUBMIT = * */ export default class QuanticSearchBox extends LightningElement { - labels = { - search, - clear, - }; - /** * The ID of the engine instance the component registers to. * @api @@ -47,9 +33,8 @@ export default class QuanticSearchBox extends LightningElement { * The placeholder text to display in the search box input area. * @api * @type {string} - * @defaultValue 'Search...' */ - @api placeholder = `${this.labels.search}`; + @api placeholder = null; /** * Whether not to render a submit button. * @api @@ -109,9 +94,12 @@ export default class QuanticSearchBox extends LightningElement { connectedCallback() { registerComponentForInit(this, this.engineId); this.addEventListener( - 'suggestionlistrender', - this.handleSuggestionListEvent + 'quantic__inputvaluechange', + this.handleInputValueChange ); + this.addEventListener('quantic__submitsearch', this.handleSubmit); + this.addEventListener('quantic__showsuggestions', this.showSuggestion); + this.addEventListener('quantic__selectsuggestion', this.selectSuggestion); } renderedCallback() { @@ -121,16 +109,22 @@ export default class QuanticSearchBox extends LightningElement { disconnectedCallback() { this.unsubscribe?.(); this.removeEventListener( - 'suggestionlistrender', - this.handleSuggestionListEvent + 'quantic__inputvaluechange', + this.handleInputValueChange + ); + this.removeEventListener('quantic__submitsearch', this.handleSubmit); + this.removeEventListener('quantic__showsuggestions', this.showSuggestion); + this.removeEventListener( + 'quantic__selectsuggestion', + this.selectSuggestion ); } updateState() { if (this.state?.value !== this.searchBox.state.value) { - this.input.value = this.searchBox.state.value; + this.quanticSearchBoxInput.inputValue = this.searchBox.state.value; } - this.state = this.searchBox.state; + this.state = this.searchBox?.state; this.suggestions = this.state?.suggestions?.map((s, index) => ({ key: index, @@ -140,188 +134,51 @@ export default class QuanticSearchBox extends LightningElement { } /** - * @returns {quanticSearchBoxSuggestionsList} + * Updates the input value. */ - get suggestionList() { - // @ts-ignore - return this.template.querySelector('c-quantic-search-box-suggestions-list'); - } + handleInputValueChange = (event) => { + const updatedValue = event.detail.newInputValue; + const isSelectionReset = event.detail.resetSelection; + if (this.searchBox?.state?.value !== updatedValue) { + if (isSelectionReset) { + this.quanticSearchBoxInput.resetSelection(); + } + this.searchBox.updateText(updatedValue); + } + }; /** - * @returns {HTMLInputElement|HTMLTextAreaElement} + * Submits a search. + * @returns {void} */ - get input() { - return this.textarea - ? this.template.querySelector('textarea') - : this.template.querySelector('input'); - } + handleSubmit = () => { + this.searchBox?.submit(); + }; /** - * @returns {HTMLElement} + * Shows the suggestions. + * @returns {void} */ - get combobox() { - return this.template.querySelector('.slds-combobox'); - } - - get searchBoxContainerClass() { - if (this.withoutSubmitButton) { - this.input?.setAttribute('aria-labelledby', 'fixed-text-label'); - return CLASS_WITHOUT_SUBMIT; - } - this.input?.setAttribute( - 'aria-labelledby', - 'fixed-text-label fixed-text-addon-post' - ); - return CLASS_WITH_SUBMIT; - } - - get searchBoxInputClass() { - return `slds-input searchbox__input ${ - this.withoutSubmitButton ? '' : 'searchbox__input-with-button' - }`; - } - - get suggestionsOpen() { - return this.combobox.classList.contains('slds-is-open'); - } - - get isQueryEmpty() { - return !this.input?.value?.length; - } - - showSuggestions() { + showSuggestion = () => { this.searchBox?.showSuggestions(); - this.combobox?.classList.add('slds-is-open'); - this.combobox?.setAttribute('aria-expanded', 'true'); - } - - hideSuggestions() { - this.combobox?.classList.remove('slds-is-open'); - this.combobox?.setAttribute('aria-expanded', 'false'); - this.suggestionList?.resetSelection(); - } - - handleHighlightChange(event) { - const suggestion = event.detail; - this.input.value = suggestion.rawValue; - } - - handleEnter() { - const selectedSuggestion = this.suggestionList?.getCurrentSelectedValue(); - if (this.suggestionsOpen && selectedSuggestion) { - this.searchBox.selectSuggestion(selectedSuggestion.rawValue); - this.input.blur(); - } else { - this.searchBox.submit(); - this.input.blur(); - } - } - - handleValueChange() { - if (this.searchBox.state.value !== this.input.value) { - this.searchBox.updateText(this.input.value); - } - } - - onSubmit(event) { - event.stopPropagation(); - if (this.searchBox.state.value !== this.input.value) { - this.searchBox.updateText(this.input.value); - } - this.searchBox.submit(); - this.input.blur(); - } - - handleKeyValues() { - if (this.searchBox?.state?.value !== this.input.value) { - this.suggestionList?.resetSelection(); - this.searchBox.updateText(this.input.value); - } - } + }; /** - * Prevent default behavior of enter key, on textArea, to prevent skipping a line. - * @param {KeyboardEvent} event + * Handles the selection of a suggestion. */ - onKeydown(event) { - if (event.key === keys.ENTER) { - event.preventDefault(); - } - } + selectSuggestion = (event) => { + const selectedSuggestion = event.detail.selectedSuggestion; + this.searchBox?.selectSuggestion(selectedSuggestion); + }; /** - * @param {KeyboardEvent} event + * @return {quanticSearchBoxInput} */ - onKeyup(event) { - switch (event.key) { - case keys.ENTER: - this.handleEnter(); - break; - case keys.ARROWUP: - this.suggestionList?.selectionUp(); - break; - case keys.ARROWDOWN: - this.suggestionList?.selectionDown(); - break; - default: - this.handleKeyValues(); - } - } - - onFocus() { - this.showSuggestions(); - this.adjustTextAreaHeight(); - } - - onBlur() { - this.hideSuggestions(); - this.collapseTextArea(); - } - - onTextAreaInput() { - this.handleValueChange(); - this.adjustTextAreaHeight(); - } - - adjustTextAreaHeight() { - if (!this.textarea) { - return; - } - this.input.value = this.input.value.replace(/\n/g, ''); - this.input.style.height = ''; - this.input.style.whiteSpace = 'pre-wrap'; - this.input.style.height = this.input.scrollHeight + 'px'; - } - - collapseTextArea() { - if (!this.textarea) { - return; - } - this.input.style.height = ''; - this.input.style.whiteSpace = 'nowrap'; - } - - clearInput() { - this.input.value = ''; - this.searchBox.updateText(this.input.value); - this.input.focus(); - if (this.textarea) { - this.adjustTextAreaHeight(); - } - } - - handleSuggestionSelection(event) { - const textValue = event.detail; - this.searchBox.selectSuggestion(textValue); - this.input.blur(); + get quanticSearchBoxInput() { + // @ts-ignore + return this.template.querySelector('c-quantic-search-box-input'); } - handleSuggestionListEvent = (event) => { - event.stopPropagation(); - const id = event.detail; - this.input.setAttribute('aria-controls', id); - }; - /** * Sets the component in the initialization error state. */ @@ -330,9 +187,6 @@ export default class QuanticSearchBox extends LightningElement { } render() { - if (this.hasInitializationError) { - return errorTemplate; - } - return this?.textarea ? expandableSearchBox : defaultSearchBox; + return this.hasInitializationError ? errorTemplate : searchBox; } } diff --git a/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/defaultSearchBox.css b/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/searchBox.css similarity index 100% rename from packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/defaultSearchBox.css rename to packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/searchBox.css diff --git a/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/searchBox.html b/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/searchBox.html new file mode 100644 index 00000000000..98b0517907d --- /dev/null +++ b/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/searchBox.html @@ -0,0 +1,8 @@ + diff --git a/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/__tests__/quanticSearchBoxInput.test.js b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/__tests__/quanticSearchBoxInput.test.js new file mode 100644 index 00000000000..e803943690b --- /dev/null +++ b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/__tests__/quanticSearchBoxInput.test.js @@ -0,0 +1,320 @@ +// @ts-ignore +import {createElement} from 'lwc'; +import QuanticSearchBoxInput from '../quanticSearchBoxInput'; + +const functionsMocks = { + exampleHandleInputValueChange: jest.fn(() => {}), + exampleHandleSubmitSearch: jest.fn(() => {}), + exampleShowSuggestions: jest.fn(() => {}), + exampleSelectSuggestion: jest.fn(() => {}), + exampleHandleKeyup: jest.fn(() => {}), +}; + +const defaultPlaceholder = 'Search...'; +const mockInputValue = 'Test input value'; +const mockSuggestions = [ + {key: '1', value: 'suggestion1', rawValue: 'suggestion1'}, + {key: '2', value: 'suggestion2', rawValue: 'suggestion2'}, + {key: '3', value: 'suggestion3', rawValue: 'suggestion3'}, +]; + +const defaultOptions = { + withoutSubmitButton: false, + textarea: true, + placeholder: defaultPlaceholder, + suggestions: [], +}; + +const selectors = { + searchBoxInput: '.searchbox__input', + searchBoxTextArea: '.searchbox__container textarea', + searchBoxSubmitBtn: '.searchbox__submit-button', + searchBoxClearIcon: '.searchbox__clear-button', + searchBoxSuggestionsList: 'c-quantic-search-box-suggestions-list', + searchBoxContainer: '.searchbox__container', + searchBoxComboBox: '.slds-combobox_container .slds-combobox', + searchBoxSearchIcon: '.searchbox__search-icon', +}; + +function setupEventListeners(element) { + element.addEventListener( + 'quantic__inputvaluechange', + functionsMocks.exampleHandleInputValueChange + ); + element.addEventListener( + 'quantic__submitsearch', + functionsMocks.exampleHandleSubmitSearch + ); + element.addEventListener( + 'quantic__showsuggestions', + functionsMocks.exampleShowSuggestions + ); + element.addEventListener( + 'quantic__selectsuggestion', + functionsMocks.exampleSelectSuggestion + ); + element.addEventListener('keyup', functionsMocks.exampleHandleKeyup); +} + +function createTestComponent(options = defaultOptions) { + const element = createElement('c-quantic-search-box-input', { + is: QuanticSearchBoxInput, + }); + + for (const [key, value] of Object.entries(options)) { + element[key] = value; + } + document.body.appendChild(element); + return element; +} + +// Helper function to wait until the microtask queue is empty. +function flushPromises() { + return new Promise((resolve) => setTimeout(resolve, 0)); +} + +describe('c-quantic-search-box-input', () => { + function cleanup() { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + } + + afterEach(() => { + cleanup(); + jest.clearAllMocks(); + }); + + describe('when the textarea property is set to false', () => { + it('should display the search input properly', async () => { + const element = createTestComponent(); + await flushPromises(); + + const input = element.shadowRoot.querySelector(selectors.searchBoxInput); + const submitButton = element.shadowRoot.querySelector( + selectors.searchBoxSubmitBtn + ); + const clearIcon = element.shadowRoot.querySelector( + selectors.searchBoxClearIcon + ); + + expect(input).not.toBeNull(); + expect(input.placeholder).toEqual(defaultOptions.placeholder); + expect(submitButton).not.toBeNull(); + expect(clearIcon).toBeNull(); + }); + }); + + describe('when the textarea property is set to true', () => { + it('should display the search textarea properly', async () => { + const element = createTestComponent({...defaultOptions, textarea: true}); + await flushPromises(); + + const submitButton = element.shadowRoot.querySelector( + selectors.searchBoxSubmitBtn + ); + const clearIcon = element.shadowRoot.querySelector( + selectors.searchBoxClearIcon + ); + const textarea = element.shadowRoot.querySelector( + selectors.searchBoxTextArea + ); + + expect(textarea).not.toBeNull(); + expect(textarea.placeholder).toEqual(defaultOptions.placeholder); + expect(submitButton).not.toBeNull(); + expect(clearIcon).toBeNull(); + }); + }); + + describe('when the withoutSubmitButton is set to false', () => { + it('should display the submit button correctly to the right only', async () => { + const element = createTestComponent({ + ...defaultOptions, + withoutSubmitButton: false, + }); + await flushPromises(); + + const submitButton = element.shadowRoot.querySelector( + selectors.searchBoxSubmitBtn + ); + + const searchIcon = element.shadowRoot.querySelector( + selectors.searchBoxSearchIcon + ); + + expect(submitButton).not.toBeNull(); + expect(searchIcon).toBeNull(); + }); + }); + + describe('when the withoutSubmitButton is set to true', () => { + it('should not display the submit button to the right of the searchbox', async () => { + const element = createTestComponent({ + ...defaultOptions, + withoutSubmitButton: true, + }); + await flushPromises(); + + const searchIcon = element.shadowRoot.querySelector( + selectors.searchBoxSearchIcon + ); + const submitButton = element.shadowRoot.querySelector( + selectors.searchBoxSubmitBtn + ); + + expect(submitButton).toBeNull(); + expect(searchIcon).not.toBeNull(); + expect(searchIcon.classList.contains('slds-input__icon_left')).toBe(true); + }); + }); + + describe('when the placeholder property receives a custom placeholder value', () => { + it('should display the custom value as the searchbox placeholder', async () => { + const customPlaceholder = 'Custom placeholder'; + const element = createTestComponent({ + ...defaultOptions, + placeholder: customPlaceholder, + }); + await flushPromises(); + + const input = element.shadowRoot.querySelector(selectors.searchBoxInput); + + expect(input.placeholder).toEqual(customPlaceholder); + }); + }); + + describe('when suggestions are found', () => { + it('should display the suggestions in the suggestions list', async () => { + const element = createTestComponent({ + ...defaultOptions, + suggestions: mockSuggestions, + }); + await flushPromises(); + + const suggestionsList = element.shadowRoot.querySelector( + selectors.searchBoxSuggestionsList + ); + expect(suggestionsList).not.toBeNull(); + + const suggestionsListItems = + suggestionsList.shadowRoot.querySelectorAll('li'); + expect(suggestionsListItems).not.toBeNull(); + + expect(suggestionsListItems.length).toEqual(mockSuggestions.length); + }); + }); + + describe('when focusing on the input', () => { + it('should dispatch a #quantic__showsuggestions custom event', async () => { + const element = createTestComponent(); + setupEventListeners(element); + await flushPromises(); + + const input = element.shadowRoot.querySelector(selectors.searchBoxInput); + expect(input).not.toBeNull(); + + await input.focus(); + + expect(functionsMocks.exampleShowSuggestions).toHaveBeenCalledTimes(1); + }); + + describe('when selecting a suggestion from the suggestions list', () => { + it('should dispatch a #quantic__selectsuggestion event with the selected suggestion as payload', async () => { + const element = createTestComponent({ + ...defaultOptions, + suggestions: mockSuggestions, + }); + setupEventListeners(element); + await flushPromises(); + + const suggestionsList = element.shadowRoot.querySelector( + selectors.searchBoxSuggestionsList + ); + expect(suggestionsList).not.toBeNull(); + + const firstSuggestion = + suggestionsList.shadowRoot.querySelectorAll('li')[0]; + expect(firstSuggestion).not.toBeNull(); + + firstSuggestion.click(); + + expect(functionsMocks.exampleSelectSuggestion).toHaveBeenCalledTimes(1); + + const eventData = + functionsMocks.exampleSelectSuggestion.mock.calls[0][0] && + functionsMocks.exampleSelectSuggestion.mock.calls[0][0]; + const expectedFirstSuggestionSelected = mockSuggestions[0].rawValue; + + // @ts-ignore + expect(eventData.detail.selectedSuggestion).toEqual( + expectedFirstSuggestionSelected + ); + }); + }); + }); + + describe('when typing something in the input', () => { + it('should dispatch a #quantic__inputvaluechange custom event with the input value as payload', async () => { + const element = createTestComponent(); + setupEventListeners(element); + await flushPromises(); + + element.inputValue = mockInputValue; + + const input = element.shadowRoot.querySelector(selectors.searchBoxInput); + expect(input).not.toBeNull(); + + input.dispatchEvent(new KeyboardEvent('keyup', {key: 'a'})); + expect( + functionsMocks.exampleHandleInputValueChange + ).toHaveBeenCalledTimes(1); + + // @ts-ignore + const eventData = + functionsMocks.exampleHandleInputValueChange.mock.calls[0][0]; + // @ts-ignore + expect(eventData.detail.newInputValue).toEqual(mockInputValue); + }); + + describe('when clicking on the submit button', () => { + it('should dispatch a #quantic__submitsearch custom event', async () => { + const element = createTestComponent(); + setupEventListeners(element); + await flushPromises(); + + const submitButton = element.shadowRoot.querySelector( + selectors.searchBoxSubmitBtn + ); + expect(submitButton).not.toBeNull(); + + submitButton.click(); + + expect(functionsMocks.exampleHandleSubmitSearch).toHaveBeenCalledTimes( + 1 + ); + }); + }); + + describe('when pressing the ENTER key', () => { + it('should dispatch a #quantic__submitsearch custom event', async () => { + const element = createTestComponent(); + setupEventListeners(element); + await flushPromises(); + + const input = element.shadowRoot.querySelector( + selectors.searchBoxInput + ); + expect(input).not.toBeNull(); + + await input.focus(); + input.dispatchEvent(new KeyboardEvent('keyup', {key: 'Enter'})); + + expect(functionsMocks.exampleHandleSubmitSearch).toHaveBeenCalledTimes( + 1 + ); + }); + }); + }); +}); diff --git a/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/quanticSearchBoxInput.js b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/quanticSearchBoxInput.js new file mode 100644 index 00000000000..d87ebdd9827 --- /dev/null +++ b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/quanticSearchBoxInput.js @@ -0,0 +1,340 @@ +import clear from '@salesforce/label/c.quantic_Clear'; +import search from '@salesforce/label/c.quantic_Search'; +import {keys} from 'c/quanticUtils'; +import {LightningElement, api} from 'lwc'; +// @ts-ignore +import defaultSearchBoxInput from './templates/defaultSearchBoxInput.html'; +// @ts-ignore +import expandableSearchBoxInput from './templates/expandableSearchBoxInput.html'; + +/** @typedef {import("c/quanticSearchBoxSuggestionsList").default} quanticSearchBoxSuggestionsList */ + +/** + * @typedef Suggestion + * @property {number} key + * @property {string} value + * @property {string} rawValue + */ + +/** + * The `QuanticSearchBoxInput` component renders the searchBox input. + * @fires CustomEvent#quantic__inputvaluechange + * @fires CustomEvent#quantic__submitsearch + * @fires CustomEvent#quantic__showsuggestions + * @fires CustomEvent#quantic__selectsuggestion + * @category Internal + * @example + * + * + */ +export default class QuanticSearchBoxInput extends LightningElement { + labels = { + search, + clear, + }; + /** + * Indicates whether or not to display a submit button. + * @api + * @type {boolean} + * @defaultValue 'false' + */ + @api withoutSubmitButton = false; + /** + * Indicates whether to render the search box using a [textarea](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea) element. + * The resulting component will expand to support multi-line queries. + * @api + * @type {boolean} + * @defaultValue false + */ + @api textarea = false; + /** + * The placeholder text to display in the search box input area. + * @api + * @type {string} + * @defaultValue 'Search...' + */ + @api placeholder = this.labels.search; + /** + * The query suggestions to display. + * @api + * @type {Suggestion[]} + */ + @api suggestions = []; + /** + * Returns and set the input value. + * @api + * @type {string} + */ + @api + get inputValue() { + return this.input.value; + } + set inputValue(newValue) { + this.input.value = newValue; + } + /** + * The blur function. + * @api + * @type {VoidFunction} + */ + @api blur() { + this.input.blur(); + } + /** + * The reset selection function. + * @api + * @type {VoidFunction} + */ + @api resetSelection() { + this.suggestionListElement?.resetSelection(); + } + + connectedCallback() { + this.addEventListener( + 'suggestionlistrender', + this.handleSuggestionListEvent + ); + } + disconnectedCallback() { + this.removeEventListener( + 'suggestionlistrender', + this.handleSuggestionListEvent + ); + } + + /** + * @returns {quanticSearchBoxSuggestionsList} + */ + get suggestionListElement() { + // @ts-ignore + return this.template.querySelector('c-quantic-search-box-suggestions-list'); + } + + /** + * @returns {HTMLInputElement|HTMLTextAreaElement} + */ + get input() { + return this.textarea + ? this.template.querySelector('textarea') + : this.template.querySelector('input'); + } + + /** + * Sends the "quantic__inputValueChange" event. + * @param {string} newInputValue + * @param {boolean} resetSelection + */ + sendInputValueChangeEvent(newInputValue, resetSelection) { + const inputValueChangeEvent = new CustomEvent('quantic__inputvaluechange', { + detail: { + newInputValue, + resetSelection, + }, + bubbles: true, + composed: true, + }); + this.dispatchEvent(inputValueChangeEvent); + } + + /** + * Sends the "quantic__submitSearch" event. + */ + sendSubmitSearchEvent() { + this.dispatchEvent( + new CustomEvent('quantic__submitsearch', { + bubbles: true, + composed: true, + }) + ); + } + + /** + * Sends the "quantic__showSuggestions" event. + */ + sendShowSuggestionsEvent() { + this.dispatchEvent( + new CustomEvent('quantic__showsuggestions', { + bubbles: true, + composed: true, + }) + ); + } + + /** + * Sends the "quantic__selectSuggestion" event. + * @param {string} selectedSuggestion + */ + sendSelectSuggestionEvent(selectedSuggestion) { + const selectSuggestionEvent = new CustomEvent('quantic__selectsuggestion', { + detail: { + selectedSuggestion, + }, + bubbles: true, + composed: true, + }); + this.dispatchEvent(selectSuggestionEvent); + } + + handleEnter() { + const selectedSuggestion = + this.suggestionListElement?.getCurrentSelectedValue(); + if (this.areSuggestionsOpen && selectedSuggestion) { + this.sendSelectSuggestionEvent(selectedSuggestion.rawValue); + } else { + this.sendSubmitSearchEvent(); + } + this.input.blur(); + } + + handleValueChange() { + this.sendInputValueChangeEvent(this.input.value, false); + } + + handleKeyValues() { + // Reset selection set to true for key pressed other than ARROW keys and ENTER. + this.sendInputValueChangeEvent(this.input.value, true); + } + + onSubmit(event) { + event.stopPropagation(); + this.sendInputValueChangeEvent(this.input.value, false); + this.sendSubmitSearchEvent(); + this.input.blur(); + } + + /** + * Prevent default behavior of enter key, on textArea, to prevent skipping a line. + * @param {KeyboardEvent} event + */ + onKeydown(event) { + if (event.key === keys.ENTER) { + event.preventDefault(); + } + } + + /** + * @param {KeyboardEvent} event + */ + onKeyup(event) { + switch (event.key) { + case keys.ENTER: + this.handleEnter(); + break; + case keys.ARROWUP: + this.suggestionListElement?.selectionUp(); + break; + case keys.ARROWDOWN: + this.suggestionListElement?.selectionDown(); + break; + default: + this.handleKeyValues(); + } + } + + onFocus() { + this.showSuggestions(); + this.adjustTextAreaHeight(); + } + + onBlur() { + this.hideSuggestions(); + this.collapseTextArea(); + } + + onTextAreaInput() { + this.handleValueChange(); + this.adjustTextAreaHeight(); + } + + adjustTextAreaHeight() { + if (!this.textarea) { + return; + } + this.input.value = this.input.value.replace(/\n/g, ''); + this.input.style.height = ''; + this.input.style.whiteSpace = 'pre-wrap'; + this.input.style.height = this.input.scrollHeight + 'px'; + } + + collapseTextArea() { + if (!this.textarea) { + return; + } + this.input.style.height = ''; + this.input.style.whiteSpace = 'nowrap'; + } + + clearInput() { + this.input.value = ''; + this.sendInputValueChangeEvent(this.input.value, false); + this.input.focus(); + if (this.textarea) { + this.adjustTextAreaHeight(); + } + } + + showSuggestions() { + this.sendShowSuggestionsEvent(); + this.combobox?.classList.add('slds-is-open'); + this.combobox?.setAttribute('aria-expanded', 'true'); + } + + hideSuggestions() { + this.combobox?.classList.remove('slds-is-open'); + this.combobox?.setAttribute('aria-expanded', 'false'); + this.suggestionListElement?.resetSelection(); + } + + handleHighlightChange(event) { + this.input.value = event.detail?.rawValue; + } + + handleSuggestionSelection(event) { + const textValue = event.detail; + this.sendSelectSuggestionEvent(textValue); + this.blur(); + } + + handleSuggestionListEvent = (event) => { + event.stopPropagation(); + const id = event.detail; + this.input.setAttribute('aria-controls', id); + }; + + get searchBoxContainerClass() { + return `slds-combobox__form-element slds-input-has-icon slds-grid ${ + this.withoutSubmitButton + ? 'slds-input-has-icon_left-right' + : 'slds-input-has-icon_right slds-input-has-fixed-addon' + }`; + } + + get searchBoxInputClass() { + return `slds-input searchbox__input ${ + this.withoutSubmitButton ? '' : 'searchbox__input-with-button' + }`; + } + + get areSuggestionsOpen() { + return this.combobox?.classList.contains('slds-is-open'); + } + + get isQueryEmpty() { + return !this.input?.value?.length; + } + + /** + * @returns {HTMLElement} + */ + get combobox() { + return this.template.querySelector('.slds-combobox'); + } + + render() { + return this?.textarea ? expandableSearchBoxInput : defaultSearchBoxInput; + } +} diff --git a/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/quanticSearchBoxInput.js-meta.xml b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/quanticSearchBoxInput.js-meta.xml new file mode 100644 index 00000000000..cc0d4bff0ef --- /dev/null +++ b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/quanticSearchBoxInput.js-meta.xml @@ -0,0 +1,5 @@ + + + 58.0 + false + \ No newline at end of file diff --git a/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/defaultSearchBoxInput.css b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/defaultSearchBoxInput.css new file mode 100644 index 00000000000..f823a7a6ffb --- /dev/null +++ b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/defaultSearchBoxInput.css @@ -0,0 +1,9 @@ +@import 'c/searchBoxStyle'; + +.searchbox__input-container { + display: flex; +} + +input { + border: var(--lwc-borderWidthThin, 1px) solid var(--lwc-brandAccessible, #0176d3); +} \ No newline at end of file diff --git a/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/defaultSearchBox.html b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/defaultSearchBoxInput.html similarity index 74% rename from packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/defaultSearchBox.html rename to packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/defaultSearchBoxInput.html index c0f5aba2555..c0839a66a7c 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/defaultSearchBox.html +++ b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/defaultSearchBoxInput.html @@ -1,4 +1,3 @@ - \ No newline at end of file + diff --git a/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/expandableSearchBox.css b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/expandableSearchBoxInput.css similarity index 68% rename from packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/expandableSearchBox.css rename to packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/expandableSearchBoxInput.css index edea567ebb7..18533166d37 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/expandableSearchBox.css +++ b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/expandableSearchBoxInput.css @@ -1,5 +1,24 @@ @import 'c/searchBoxStyle'; +.searchbox__icon-container { + margin: inherit; +} + +.searchbox__icon-container-left { + margin-left: 0.5rem; +} + +.searchbox__icon-container-right { + margin-right: 0.5rem; +} + +/* This is to override some style from the slds-has-input and prevent */ +/* the search icon from sliding down as the searchbox expands */ +.searchbox__search-icon { + margin-top: 0; + top: auto; +} + .searchbox__container { overflow: visible; border: var(--lwc-borderWidthThin, 1px) solid var(--lwc-brandAccessible, #0176d3); diff --git a/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/expandableSearchBox.html b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/expandableSearchBoxInput.html similarity index 64% rename from packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/expandableSearchBox.html rename to packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/expandableSearchBoxInput.html index f451183e253..7d805e895de 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticSearchBox/templates/expandableSearchBox.html +++ b/packages/quantic/force-app/main/default/lwc/quanticSearchBoxInput/templates/expandableSearchBoxInput.html @@ -1,4 +1,3 @@ - \ No newline at end of file + diff --git a/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/quanticStandaloneSearchBox.js b/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/quanticStandaloneSearchBox.js index 0fce8fa2db1..855117dc628 100644 --- a/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/quanticStandaloneSearchBox.js +++ b/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/quanticStandaloneSearchBox.js @@ -1,30 +1,22 @@ -import clear from '@salesforce/label/c.quantic_Clear'; -import search from '@salesforce/label/c.quantic_Search'; import { registerComponentForInit, initializeWithHeadless, getHeadlessBindings, destroyEngine, } from 'c/quanticHeadlessLoader'; -import {STANDALONE_SEARCH_BOX_STORAGE_KEY, keys} from 'c/quanticUtils'; +import {STANDALONE_SEARCH_BOX_STORAGE_KEY} from 'c/quanticUtils'; import {CurrentPageReference, NavigationMixin} from 'lightning/navigation'; import {LightningElement, api, track, wire} from 'lwc'; // @ts-ignore -import defaultStandaloneSearchBox from './templates/defaultStandaloneSearchBox.html'; -// @ts-ignore import errorTemplate from './templates/errorTemplate.html'; // @ts-ignore -import expandableStandaloneSearchBox from './templates/expandableStandaloneSearchBox.html'; - -const CLASS_WITH_SUBMIT = - 'slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right slds-input-has-fixed-addon'; -const CLASS_WITHOUT_SUBMIT = - 'slds-combobox__form-element slds-input-has-icon slds-input-has-icon_left-right'; +import standaloneSearchBox from './templates/standaloneSearchBox.html'; /** @typedef {import("coveo").SearchEngine} SearchEngine */ /** @typedef {import("coveo").StandaloneSearchBoxState} StandaloneSearchBoxState */ /** @typedef {import("coveo").StandaloneSearchBox} StandaloneSearchBox */ /** @typedef {import("c/quanticSearchBoxSuggestionsList").default} quanticSearchBoxSuggestionsList */ +/** @typedef {import("c/quanticSearchBoxInput").default} quanticSearchBoxInput */ /** @typedef {{key: number, value: string}} Suggestion */ /** @@ -37,11 +29,6 @@ const CLASS_WITHOUT_SUBMIT = export default class QuanticStandaloneSearchBox extends NavigationMixin( LightningElement ) { - labels = { - search, - clear, - }; - /** * The ID of the engine instance the component registers to. * @api @@ -52,9 +39,8 @@ export default class QuanticStandaloneSearchBox extends NavigationMixin( * The placeholder text to display in the search box input area. * @api * @type {string} - * @defaultValue 'Search...' */ - @api placeholder = `${this.labels.search}`; + @api placeholder = null; /** * Whether not to render a submit button. * @api @@ -124,7 +110,7 @@ export default class QuanticStandaloneSearchBox extends NavigationMixin( /** @type {Function} */ unsubscribe; /** @type {boolean} */ - isInitialized; + isInitialized = false; /** @type {Suggestion[]} */ suggestions = []; /** @type {boolean} */ @@ -137,16 +123,25 @@ export default class QuanticStandaloneSearchBox extends NavigationMixin( connectedCallback() { registerComponentForInit(this, this.standaloneEngineId); + this.addEventListener( - 'suggestionlistrender', - this.handleSuggestionListEvent + 'quantic__inputvaluechange', + this.handleInputValueChange ); + this.addEventListener('quantic__submitsearch', this.handleSubmit); + this.addEventListener('quantic__showsuggestions', this.showSuggestions); + this.addEventListener('quantic__selectsuggestion', this.selectSuggestion); } renderedCallback() { initializeWithHeadless(this, this.standaloneEngineId, this.initialize); - if (!this.isInitialized && !!this.standaloneSearchBox && !!this.input) { - this.input.setAttribute('is-initialized', 'true'); + if ( + !this.isInitialized && + !!this.standaloneSearchBox && + !!this.quanticSearchBoxInput + ) { + // The is-initialized attribute is set to true for E2E tests + this.quanticSearchBoxInput.setAttribute('is-initialized', 'true'); this.isInitialized = true; } } @@ -186,17 +181,26 @@ export default class QuanticStandaloneSearchBox extends NavigationMixin( disconnectedCallback() { this.unsubscribe?.(); + + this.removeEventListener( + 'quantic__inputvaluechange', + this.handleInputValueChange + ); + this.removeEventListener('quantic__submitsearch', this.handleSubmit); + this.removeEventListener('quantic__showsuggestions', this.showSuggestions); this.removeEventListener( - 'suggestionlistrender', - this.handleSuggestionListEvent + 'quantic__selectsuggestion', + this.selectSuggestion ); } updateStandaloneState() { - if (this.state.value !== this.standaloneSearchBox.state.value) { - this.input.value = this.standaloneSearchBox.state.value; + if (this.state?.value !== this.standaloneSearchBox.state.value) { + // @ts-ignore + this.quanticSearchBoxInput.inputValue = + this.standaloneSearchBox.state.value; } - this.state = this.standaloneSearchBox.state; + this.state = this.standaloneSearchBox?.state; this.suggestions = this.state?.suggestions?.map((s, index) => ({ key: index, @@ -220,148 +224,6 @@ export default class QuanticStandaloneSearchBox extends NavigationMixin( this.navigateToSearchPage(); } - get searchBoxContainerClass() { - if (this.withoutSubmitButton) { - this.input?.setAttribute('aria-labelledby', 'fixed-text-label'); - return CLASS_WITHOUT_SUBMIT; - } - this.input?.setAttribute( - 'aria-labelledby', - 'fixed-text-label fixed-text-addon-post' - ); - return CLASS_WITH_SUBMIT; - } - - get searchBoxInputClass() { - return `slds-input searchbox__input ${ - this.withoutSubmitButton ? '' : 'searchbox__input-with-button' - }`; - } - - showSuggestions() { - this.standaloneSearchBox?.showSuggestions(); - this.combobox?.classList.add('slds-is-open'); - this.combobox?.setAttribute('aria-expanded', 'true'); - } - - hideSuggestions() { - this.combobox?.classList.remove('slds-is-open'); - this.combobox?.setAttribute('aria-expanded', 'false'); - this.suggestionList?.resetSelection(); - } - - handleHighlightChange(event) { - this.input.value = event.detail?.rawValue; - } - - handleEnter() { - const selectedSuggestion = this.suggestionList?.getCurrentSelectedValue(); - if (this.suggestionsOpen && selectedSuggestion) { - this.standaloneSearchBox.selectSuggestion(selectedSuggestion.rawValue); - } else { - this.standaloneSearchBox.submit(); - } - this.input.blur(); - } - - handleValueChange() { - if (this.standaloneSearchBox.state.value !== this.input.value) { - this.standaloneSearchBox.updateText(this.input.value); - } - } - - onSubmit(event) { - event.stopPropagation(); - if (this.standaloneSearchBox?.state?.value !== this.input.value) { - this.standaloneSearchBox.updateText(this.input.value); - } - this.standaloneSearchBox.submit(); - this.input.blur(); - } - - handleKeyValues() { - if (this.standaloneSearchBox?.state?.value !== this.input.value) { - this.suggestionList?.resetSelection(); - this.standaloneSearchBox?.updateText(this.input.value); - } - } - - /** - * Prevent default behavior of enter key, on textArea, to prevent skipping a line. - * @param {KeyboardEvent} event - */ - onKeydown(event) { - if (event.key === keys.ENTER) { - event.preventDefault(); - } - } - - /** - * @param {KeyboardEvent} event - */ - onKeyup(event) { - switch (event.key) { - case keys.ENTER: - this.handleEnter(); - break; - case keys.ARROWUP: - this.suggestionList.selectionUp(); - break; - case keys.ARROWDOWN: - this.suggestionList.selectionDown(); - break; - default: - this.handleKeyValues(); - } - } - - onFocus() { - this.showSuggestions(); - this.adjustTextAreaHeight(); - } - - onBlur() { - this.hideSuggestions(); - this.collapseTextArea(); - } - - onTextAreaInput() { - this.handleValueChange(); - this.adjustTextAreaHeight(); - } - - adjustTextAreaHeight() { - if (!this.textarea) { - return; - } - this.input.value = this.input.value.replace(/\n/g, ''); - this.input.style.height = ''; - this.input.style.whiteSpace = 'pre-wrap'; - this.input.style.height = this.input.scrollHeight + 'px'; - } - - collapseTextArea() { - if (!this.textarea) { - return; - } - this.input.style.height = ''; - this.input.style.whiteSpace = 'nowrap'; - } - - clearInput() { - this.input.value = ''; - this.standaloneSearchBox.updateText(this.input.value); - this.input.focus(); - if (this.textarea) { - this.adjustTextAreaHeight(); - } - } - - handleSuggestionSelection(event) { - const textValue = event.detail; - this.standaloneSearchBox.selectSuggestion(textValue); - } - resetStandaloneSearchboxState() { const engine = getHeadlessBindings(this.standaloneEngineId)?.engine; if (!engine) { @@ -374,7 +236,6 @@ export default class QuanticStandaloneSearchBox extends NavigationMixin( navigateToSearchPage() { const value = this.standaloneSearchBox.state.value; - this.resetStandaloneSearchboxState(); this[NavigationMixin.Navigate]( { @@ -388,49 +249,51 @@ export default class QuanticStandaloneSearchBox extends NavigationMixin( } /** - * @returns {HTMLInputElement|HTMLTextAreaElement} + * Updates the input value. */ - get input() { - return this.textarea - ? this.template.querySelector('textarea') - : this.template.querySelector('input'); - } + handleInputValueChange = (event) => { + const updatedValue = event.detail.newInputValue; + const isSelectionReset = event.detail.resetSelection; + if (this.standaloneSearchBox?.state?.value !== updatedValue) { + if (isSelectionReset) { + this.quanticSearchBoxInput.resetSelection(); + } + this.standaloneSearchBox.updateText(updatedValue); + } + }; /** - * @returns {HTMLElement} + * Submits a search. + * @returns {void} */ - get combobox() { - return this.template.querySelector('.slds-combobox'); - } + handleSubmit = () => { + this.standaloneSearchBox?.submit(); + }; /** - * @returns {quanticSearchBoxSuggestionsList} + * Shows the suggestions. + * @returns {void} */ - get suggestionList() { - // @ts-ignore - return this.template.querySelector('c-quantic-search-box-suggestions-list'); - } + showSuggestions = () => { + this.standaloneSearchBox?.showSuggestions(); + }; /** - * @returns {boolean} + * Handles the selection of a suggestion. */ - get isQueryEmpty() { - return !this.input?.value?.length; - } + selectSuggestion = (event) => { + const selectedSuggestion = event.detail.selectedSuggestion; + this.standaloneSearchBox?.selectSuggestion(selectedSuggestion); + }; /** - * @returns {boolean} + * @return {quanticSearchBoxInput} */ - get suggestionsOpen() { - return this.combobox?.classList.contains('slds-is-open'); + get quanticSearchBoxInput() { + // @ts-ignore + return this.template.querySelector('c-quantic-search-box-input'); } - handleSuggestionListEvent = (event) => { - event.stopPropagation(); - const id = event.detail; - this.input.setAttribute('aria-controls', id); - }; - /** * Sets the component in the initialization error state. */ @@ -439,11 +302,6 @@ export default class QuanticStandaloneSearchBox extends NavigationMixin( } render() { - if (this.hasInitializationError) { - return errorTemplate; - } - return this?.textarea - ? expandableStandaloneSearchBox - : defaultStandaloneSearchBox; + return this.hasInitializationError ? errorTemplate : standaloneSearchBox; } } diff --git a/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/defaultStandaloneSearchBox.html b/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/defaultStandaloneSearchBox.html deleted file mode 100644 index e2a63c050a5..00000000000 --- a/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/defaultStandaloneSearchBox.html +++ /dev/null @@ -1,78 +0,0 @@ - - diff --git a/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/expandableStandaloneSearchBox.css b/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/expandableStandaloneSearchBox.css deleted file mode 100644 index ad5401389db..00000000000 --- a/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/expandableStandaloneSearchBox.css +++ /dev/null @@ -1,37 +0,0 @@ -@import 'c/searchBoxStyle'; - -.searchbox__container { - overflow: visible; - border: var(--lwc-borderWidthThin, 1px) solid var(--lwc-brandAccessible, #0176d3); -} - -.z-index-high { - z-index: 20; -} - -textarea.searchbox__input { - padding-top: 0.8rem; - padding-bottom: 0.8rem; - line-height: 20px; - max-height: 8.5rem; - resize: none; - border: none; - box-shadow: none; - overflow-x: clip; -} - -.searchbox__submit-button { - border: none; - border-radius: 0 var(--lwc-borderRadiusMedium, 0.25rem) var(--lwc-borderRadiusMedium, 0.25rem) 0; -} - -.searchbox__container-wrapper { - min-height: 3.125rem; -} - -.searchbox_floating-container { - position: absolute; - width: 100%; - background-color: var(--lwc-colorBackgroundAlt, rgb(255, 255, 255)); - border-radius: 0.25rem; -} \ No newline at end of file diff --git a/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/expandableStandaloneSearchBox.html b/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/expandableStandaloneSearchBox.html deleted file mode 100644 index 1aa58178242..00000000000 --- a/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/expandableStandaloneSearchBox.html +++ /dev/null @@ -1,85 +0,0 @@ - - \ No newline at end of file diff --git a/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/defaultStandaloneSearchBox.css b/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/standaloneSearchBox.css similarity index 100% rename from packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/defaultStandaloneSearchBox.css rename to packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/standaloneSearchBox.css diff --git a/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/standaloneSearchBox.html b/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/standaloneSearchBox.html new file mode 100644 index 00000000000..87fc96eda58 --- /dev/null +++ b/packages/quantic/force-app/main/default/lwc/quanticStandaloneSearchBox/templates/standaloneSearchBox.html @@ -0,0 +1,28 @@ + diff --git a/packages/quantic/force-app/main/default/lwc/searchBoxStyle/searchBoxStyle.css b/packages/quantic/force-app/main/default/lwc/searchBoxStyle/searchBoxStyle.css index 7c881ffd196..a8cc6617b0f 100644 --- a/packages/quantic/force-app/main/default/lwc/searchBoxStyle/searchBoxStyle.css +++ b/packages/quantic/force-app/main/default/lwc/searchBoxStyle/searchBoxStyle.css @@ -37,9 +37,8 @@ border-bottom-right-radius: 0.25rem; } -.searchbox__clear-button-container { +.searchbox__icon-container { height: 48px; - margin: inherit; } .searchbox__clear-button { diff --git a/packages/quantic/tsconfig.json b/packages/quantic/tsconfig.json index 8675294426f..379e78d0ffe 100644 --- a/packages/quantic/tsconfig.json +++ b/packages/quantic/tsconfig.json @@ -64,6 +64,9 @@ "c/quanticSearchBoxSuggestionsList": [ "quanticSearchBoxSuggestionsList/quanticSearchBoxSuggestionsList.js" ], + "c/quanticSearchBoxInput": [ + "quanticSearchBoxInput/quanticSearchBoxInput.js" + ], "c/quanticSearchInterface": [ "quanticSearchInterface/quanticSearchInterface.js" ],