Skip to content

Commit

Permalink
feat(css): configurable prefix (#184)
Browse files Browse the repository at this point in the history
Fixes #97
  • Loading branch information
darrenjennings authored Apr 3, 2020
1 parent c18c67b commit 77b5bca
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 20 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ vue-autosuggest does not have an opinion about how you render the items in your
| `component-attr-id-autosuggest` | String | | `id` of entire component |
| `component-attr-class-autosuggest-results-container` | String | | `class` of container of results container |
| `component-attr-class-autosuggest-results` | String | | `class` of results container |
| `component-attr-prefix` | String | | prefix to be used for results item classes/ids. default: `autosuggest` |

<a name="inputPropsTable"></a>

Expand Down
64 changes: 64 additions & 0 deletions __tests__/__snapshots__/autosuggest.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,70 @@ exports[`Autosuggest can click outside document to trigger close 1`] = `
</div>
`;
exports[`Autosuggest can customize css prefix 1`] = `
<div id="the-whole-thing" class="containerz"><input type="text" autocomplete="off" role="combobox" aria-autocomplete="list" aria-owns="v__results" aria-activedescendant="" aria-haspopup="true" aria-expanded="true" id="the-input-thing" placeholder="Type 'G'" value="G" class="v__input--open">
<div class="the-results-container">
<div aria-labelledby="the-whole-thing" class="the-results">
<ul role="listbox" aria-labelledby="autosuggest">
<li role="option" data-suggestion-index="0" data-section-name="default" id="v__results-item--0" class="v__results-item">
clifford kits
</li>
<li role="option" data-suggestion-index="1" data-section-name="default" id="v__results-item--1" class="v__results-item">
friendly chemistry
</li>
<li role="option" data-suggestion-index="2" data-section-name="default" id="v__results-item--2" class="v__results-item">
phonics
</li>
<li role="option" data-suggestion-index="3" data-section-name="default" id="v__results-item--3" class="v__results-item">
life of fred
</li>
<li role="option" data-suggestion-index="4" data-section-name="default" id="v__results-item--4" class="v__results-item">
life of fred math
</li>
</ul>
<ul role="listbox" aria-labelledby="autosuggest">
<li role="option" data-suggestion-index="5" data-section-name="dogs" id="v__results-item--5" class="v__results-item">
spike
</li>
<li role="option" data-suggestion-index="6" data-section-name="dogs" id="v__results-item--6" class="v__results-item">
bud
</li>
<li role="option" data-suggestion-index="7" data-section-name="dogs" id="v__results-item--7" class="v__results-item">
rover
</li>
</ul>
<ul role="listbox" aria-labelledby="autosuggest">
<li role="option" data-suggestion-index="8" data-section-name="cats" id="v__results-item--8" class="v__results-item">
sassy
</li>
<li role="option" data-suggestion-index="9" data-section-name="cats" id="v__results-item--9" class="v__results-item">
tuesday
</li>
<li role="option" data-suggestion-index="10" data-section-name="cats" id="v__results-item--10" class="v__results-item">
church
</li>
</ul>
<ul role="listbox" aria-labelledby="autosuggest">
<li role="option" data-suggestion-index="11" data-section-name="zeu" id="v__results-item--11" class="v__results-item">
elephant
</li>
<li role="option" data-suggestion-index="12" data-section-name="zeu" id="v__results-item--12" class="v__results-item">
lion
</li>
</ul>
<ul role="listbox" aria-labelledby="autosuggest">
<li role="option" data-suggestion-index="13" data-section-name="Uhh" id="v__results-item--13" class="v__results-item">
something
</li>
<li role="option" data-suggestion-index="14" data-section-name="Uhh" id="v__results-item--14" class="v__results-item">
something2
</li>
</ul>
</div>
</div>
</div>
`;
exports[`Autosuggest can customize ids and classes for container divs 1`] = `
<div id="automatischsuchen" class="containerz"><input type="text" autocomplete="off" role="combobox" aria-autocomplete="list" aria-owns="autosuggest__results" aria-activedescendant="" aria-haspopup="true" aria-expanded="true" id="autosuggest__input" placeholder="Type 'G'" value="G" class="autosuggest__input--open">
<div class="resultz-containerz">
Expand Down
40 changes: 40 additions & 0 deletions __tests__/autosuggest.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,46 @@ describe("Autosuggest", () => {
expect(str).toMatchSnapshot();
});
});

it("can customize css prefix", async () => {
const wrapper = mount(Autosuggest, {
propsData: {
...defaultProps,
class: "containerz",
'component-attr-prefix': 'v',
'component-attr-id-autosuggest': "the-whole-thing",
'component-attr-class-autosuggest-results-container': 'the-results-container',
'component-attr-class-autosuggest-results': 'the-results',
inputProps: {
...defaultProps.inputProps,
id: 'the-input-thing',
}
},
attachToDocument: true
});

const input = wrapper.find("input");
input.trigger("click");
input.setValue("G");

// Make sure the prefixes still allow for custom css/id's
expect(wrapper.find('#the-whole-thing').is('div')).toBe(true);
expect(wrapper.find('#the-input-thing').is('input')).toBe(true);
expect(wrapper.find('.the-results-container').is('div')).toBe(true);
expect(wrapper.find('.the-results').is('div')).toBe(true);

// Prefix checks
expect(wrapper.find('#v__results-item--0').is('li')).toBeTruthy()
expect(wrapper.find('.v__results-item').is('li')).toBeTruthy()

const renderer = createRenderer();
renderer.renderToString(wrapper.vm, (err, str) => {
if (err) {
return false;
}
expect(str).toMatchSnapshot();
});
});

it("@click and @selected listener events works as expected", async () => {
let props = Object.assign({}, defaultProps);
Expand Down
39 changes: 26 additions & 13 deletions src/Autosuggest.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@
:value="internalValue"
:autocomplete="internal_inputProps.autocomplete"
role="combobox"
:class="[isOpen ? 'autosuggest__input--open' : '', internal_inputProps['class']]"
:class="[isOpen ? `${componentAttrPrefix}__input--open` : '', internal_inputProps['class']]"
v-bind="internal_inputProps"
aria-autocomplete="list"
aria-owns="autosuggest__results"
:aria-activedescendant="isOpen && currentIndex !== null ? `autosuggest__results-item--${currentIndex}` : ''"
:aria-owns="`${componentAttrPrefix}__results`"
:aria-activedescendant="isOpen && currentIndex !== null ? `${componentAttrPrefix}__results-item--${currentIndex}` : ''"
:aria-haspopup="isOpen ? 'true' : 'false'"
:aria-expanded="isOpen ? 'true' : 'false'"
@input="inputHandler"
@keydown="handleKeyStroke"
v-on="listeners"
><slot name="after-input" />
<div :class="componentAttrClassAutosuggestResultsContainer">
<div :class="_componentAttrClassAutosuggestResultsContainer">
<div
v-if="isOpen"
:class="componentAttrClassAutosuggestResults"
:class="_componentAttrClassAutosuggestResults"
:aria-labelledby="componentAttrIdAutosuggest"
>
<slot name="before-suggestions" />
Expand All @@ -32,6 +32,7 @@
:normalize-item-function="normalizeItem"
:render-suggestion="renderSuggestion"
:section="cs"
:component-attr-prefix="componentAttrPrefix"
@updateCurrentIndex="updateCurrentIndex"
>
<template
Expand Down Expand Up @@ -184,13 +185,18 @@ export default {
componentAttrClassAutosuggestResultsContainer: {
type: String,
required: false,
default: "autosuggest__results-container"
default: null // `${componentAttrPrefix}__results-container`
},
componentAttrClassAutosuggestResults: {
type: String,
required: false,
default: "autosuggest__results"
default: null // `${componentAttrPrefix}__results`
},
componentAttrPrefix: {
type: String,
required: false,
default: "autosuggest"
}
},
data() {
return {
Expand Down Expand Up @@ -326,7 +332,14 @@ export default {
const { limit, data } = section
return acc + (data.length >= limit ? limit : data.length)
}, 0)
}
},
_componentAttrClassAutosuggestResultsContainer () {
return this.componentAttrClassAutosuggestResultsContainer || `${this.componentAttrPrefix}__results-container`
},
_componentAttrClassAutosuggestResults () {
return this.componentAttrClassAutosuggestResults || `${this.componentAttrPrefix}__results`
},
},
watch: {
/**
Expand Down Expand Up @@ -538,14 +551,14 @@ export default {
*/
ensureItemVisible(item, index, selector) {
const resultsScrollElement = this.$el.querySelector(
selector || `.${this.componentAttrClassAutosuggestResults}`
selector || `.${this._componentAttrClassAutosuggestResults}`
);
if (!resultsScrollElement) {
return
}
const itemElement = resultsScrollElement.querySelector(`#autosuggest__results-item--${index}`);
const itemElement = resultsScrollElement.querySelector(`#${this.componentAttrPrefix}__results-item--${index}`);
if (!itemElement) {
return;
}
Expand Down Expand Up @@ -580,7 +593,7 @@ export default {
* results e.g. an offset of clientX
*/
clickedOnScrollbar(e, mouseX){
const results = this.$el.querySelector(`.${this.componentAttrClassAutosuggestResults}`);
const results = this.$el.querySelector(`.${this._componentAttrClassAutosuggestResults}`);
const mouseIsInsideScrollbar = results && results.clientWidth <= (mouseX + 17) &&
mouseX + 17 <= results.clientWidth + 34
Expand Down Expand Up @@ -645,8 +658,8 @@ export default {
}
this.currentIndex = adjustedValue;
const element = this.$el.querySelector(`#autosuggest__results-item--${this.currentIndex}`);
const hoverClass = "autosuggest__results-item--highlighted";
const element = this.$el.querySelector(`#${this.componentAttrPrefix}__results-item--${this.currentIndex}`);
const hoverClass = `${this.componentAttrPrefix}__results-item--highlighted`;
if (this.$el.querySelector(`.${hoverClass}`)) {
removeClass(this.$el.querySelector(`.${hoverClass}`), hoverClass);
Expand Down
16 changes: 9 additions & 7 deletions src/parts/DefaultSection.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const DefaultSection = {
section: { type: Object, required: true },
currentIndex: { type: [Number, String], required: false, default: Infinity },
renderSuggestion: { type: Function, required: false },
normalizeItemFunction: { type: Function, required: true }
normalizeItemFunction: { type: Function, required: true },
componentAttrPrefix: { type: String, required: true }
},
data: function () {
return {
Expand Down Expand Up @@ -43,13 +44,14 @@ const DefaultSection = {
},
// eslint-disable-next-line no-unused-vars
render (h) {
const componentAttrPrefix = this.componentAttrPrefix
const slots = {
beforeSection: this.$scopedSlots[`before-section-${this.section.name}`],
afterSectionDefault: this.$scopedSlots[`after-section`],
afterSectionNamed: this.$scopedSlots[`after-section-${this.section.name}`]
}

const beforeClassName = `autosuggest__results-before autosuggest__results-before--${this.section.name}`
const beforeClassName = `${componentAttrPrefix}__results-before ${componentAttrPrefix}__results-before--${this.section.name}`
const before = slots.beforeSection && slots.beforeSection({
section: this.section,
className: beforeClassName
Expand All @@ -75,13 +77,13 @@ const DefaultSection = {
role: "option",
"data-suggestion-index": itemIndex,
"data-section-name": item.name,
id: "autosuggest__results-item--" + itemIndex,
id: `${componentAttrPrefix}__results-item--${itemIndex}`,
...item.liAttributes
},
key: itemIndex,
class: {
"autosuggest__results-item--highlighted": isHighlighted,
'autosuggest__results-item': true,
[`${componentAttrPrefix}__results-item--highlighted`]: isHighlighted,
[`${componentAttrPrefix}__results-item`]: true,
...item.liClass
},
on: {
Expand All @@ -98,11 +100,11 @@ const DefaultSection = {
}),
slots.afterSectionDefault && slots.afterSectionDefault({
section: this.section,
className: `autosuggest__results-after autosuggest__results-after--${this.section.name}`
className: `${componentAttrPrefix}__results-after ${componentAttrPrefix}__results-after--${this.section.name}`
}),
slots.afterSectionNamed && slots.afterSectionNamed({
section: this.section,
className: `autosuggest__results_after autosuggest__results-after--${this.section.name}`
className: `${componentAttrPrefix}__results_after ${componentAttrPrefix}__results-after--${this.section.name}`
})
]
);
Expand Down

0 comments on commit 77b5bca

Please sign in to comment.