1.0.6 • Published 5 years ago

vue-search-panel v1.0.6

Weekly downloads
6
License
MIT
Repository
github
Last release
5 years ago

vue-search-panel

English | 简体中文

vue-search-panel is a search component with suggestions

Contents

Features

  • Filter suggestions based on input word, support for custom rules
  • Customize suggestion's element by slot
  • Support for custom UI
  • Support configuration panel position (top/bottom/left/right/static)
  • Extended to multifunctional panel, like VsCode

Example

Live demo

Link: https://theoxiong.github.io/vue-search-panel/

Default UI

DefaultUI

Custom UI

CustomizeUI

Install

$   npm install vue-search-panel --save

Usage

Import module

import VueSearchPanel from 'vue-search-panel'

Registration

Global registration

Vue.use(VueSearchPanel)

Local registration

<script>
export default {
  components: { VueSearchPanel }
}
</script>

Basic usage

  • Calling the show method to open panel.
  • Click outside or Press ESC to close panel.

Sample code:

<template>
  <div class="demo-comp">
    <button @click="onOpen">Open Panel</button>
    <div>Selected: {{ selected }}</div>
    <vue-search-panel
      v-model="value"
      :fetch-suggestions="getSuggestions"
      @select="onSelect"
      ref="searchPanel"
    >
    </vue-search-panel>
  </div>
</template>

<script>
import VueSearchPanel from 'vue-search-panel'
const testData = [
  { key: 'test-data-1', value: 'test data 1' },
  { key: 'test-data-2', value: 'test data 2' },
  { key: 'test-data-3', value: 'test data 3' }
]

export default {
  name: 'DemoComp',
  data () {
    return {
      value: '',
      selected: ''
    }
  },
  methods: {
    onOpen () {
      this.$refs.searchPanel.show()
    },
    onSelect (item) {
      this.selected = item.value
    },
    getSuggestions (query, cb) {
      cb(query ? testData.filter(item => { return item.value.includes(query) }) : testData)
    }
  },
  components: { VueSearchPanel }
}
</script>

Custom suggestions

Customize suggestion's element by scoped slot, access the suggestion object via the item key.

Sample code:

<template>
  <div class="demo-comp">
    <button @click="onOpen">Open Panel</button>
    <div>Selected: {{ selected }}</div>
    <vue-search-panel
      v-model="value"
      :fetch-suggestions="getSuggestions"
      @select="onSelect"
      ref="searchPanel"
    >
      <div class="demo-search-item" slot-scope="{ item }">
        <span class="search-item-value">{{ item.value }}</span>
        <span class="search-item-time">{{ item.time }}</span>
      </div>
    </vue-search-panel>
  </div>
</template>

<script>
import VueSearchPanel from 'vue-search-panel'

export default {
  name: 'DemoComp',
  data () {
    return {
      value: '',
      selected: '',
      testData: []
    }
  },
  mounted () {
    for (let i = 0; i < 20; i++) {
      this.testData.push({
        key: `data-${i}`,
        value: `Test data ${i + 1}`,
        time: new Date(Math.random() * 1000000000000).toLocaleDateString()
      })
    }
  },
  methods: {
    onOpen () {
      this.$refs.searchPanel.show()
    },
    onSelect (item) {
      this.selected = item.value
    },
    getSuggestions (query, cb) {
      cb(query ? this.testData.filter(item => { return item.value.includes(query) }) : this.testData)
    }
  },
  components: { VueSearchPanel }
}
</script>

<style scoped>
.demo-search-item{
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 32px;
  padding: 0 20px;
}
.search-item-value{
  font-size: 14px;
  color: #555;
}
.search-item-time{
  font-size: 12px;
  color: #aaa;
  width: 80px;
}

</style>

Custom UI

Customize UI by props.
The color/borderColor/backgroundColor/width/height can be configured.
For more details, see the API.

Sample code:

<template>
  <div class="demo-comp">
    <button @click="onOpen">Open Panel</button>
    <div>Selected: {{ selected }}</div>
    <vue-search-panel
      v-model="value"
      width="640px"
      height="400px"
      scrollBarColor="#aaaaaa"
      inputColor="#cccccc"
      inputBackground="#555555"
      inputBorderColor="#666666"
      inputBorderColorHovering="#999999"
      inputBorderColorFocused="#bbbbbb"
      placeholderEffect="dark"
      panelBackground="#333333"
      panelBoxShadow="rgba(0, 0, 0, 0.6)"
      highlightedColor="#444444"
      hoveredColor="#666666"
      :fetch-suggestions="getSuggestions"
      @select="onSelect"
      ref="searchPanel"
    >
      <div class="demo-search-item" slot-scope="{ item }">
        <span class="search-item-value">{{ item.value }}</span>
        <span class="search-item-time">{{ item.time }}</span>
      </div>
    </vue-search-panel>
  </div>
</template>

<script>
import VueSearchPanel from 'vue-search-panel'

export default {
  name: 'DemoComp',
  data () {
    return {
      value: '',
      selected: '',
      testData: []
    }
  },
  mounted () {
    for (let i = 0; i < 20; i++) {
      this.testData.push({
        key: `data-${i}`,
        value: `Test data ${i + 1}`,
        time: new Date(Math.random() * 1000000000000).toLocaleDateString()
      })
    }
  },
  methods: {
    onOpen () {
      this.$refs.searchPanel.show()
    },
    onSelect (item) {
      this.selected = item.value
    },
    getSuggestions (query, cb) {
      cb(query ? this.testData.filter(item => { return item.value.includes(query) }) : this.testData)
    }
  },
  components: { VueSearchPanel }
}
</script>

<style scoped>
.demo-search-item{
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 32px;
  padding: 0 20px;
}
.search-item-value{
  font-size: 14px;
  color: #999;
}
.search-item-time{
  font-size: 12px;
  color: #777;
  width: 80px;
}

</style>

config panel position

  • The prop of fixed is used for position of panel, the panel is positioned relative to the viewport when the value is true, and the panel is positioned according to the normal flow of the document when the value is false.
  • The prop of placement is used for specifying the placement of panel relative to the viewport, the optional vlaue is top/bottom/left/right

    The placement prop is ignored when the fiexd value is false

         

Sample code:

<template>
  <div class="demo-comp">
    <button @click="onOpen('top')" :disabled="disabled" :class="{'is-disabled': disabled}">Open at top</button>
    <button @click="onOpen('bottom')" :disabled="disabled" :class="{'is-disabled': disabled}">Open at bottom</button>
    <button @click="onOpen('left')" :disabled="disabled" :class="{'is-disabled': disabled}">Open at left</button>
    <button @click="onOpen('right')" :disabled="disabled" :class="{'is-disabled': disabled}">Open at right</button>
    <button @click="onOpen('inner')" :disabled="disabled" :class="{'is-disabled': disabled}">Open at inner</button>
    <div>Selected: {{ selected }}</div>
    <vue-search-panel
      v-model="value"
      :placement="placement"
      :fixed="fixed"
      :fetch-suggestions="getSuggestions"
      @open="onPanelOpen"
      @closed="onPanelClosed"
      @select="onSelect"
      ref="searchPanel"
    >
    </vue-search-panel>
  </div>
</template>

<script>
import VueSearchPanel from 'vue-search-panel'
const testData = [
  { key: 'test-data-1', value: 'test data 1' },
  { key: 'test-data-2', value: 'test data 2' },
  { key: 'test-data-3', value: 'test data 3' }
]

export default {
  name: 'DemoComp',
  data () {
    return {
      value: '',
      selected: '',
      placement: 'top',
      fixed: true,
      disabled: false
    }
  },
  methods: {
    onOpen (position) {
      if (position === 'inner') {
        this.fixed = false
      } else {
        this.fixed = true
        this.placement = position
      }
      this.$refs.searchPanel.show()
    },
    onPanelOpen () {
      this.disabled = true
    },
    onPanelClosed () {
      this.disabled = false
    },
    onSelect (item) {
      this.selected = item.value
    },
    getSuggestions (query, cb) {
      cb(query ? testData.filter(item => { return item.value.includes(query) }) : testData)
    }
  },
  components: { VueSearchPanel }
}
</script>

<style scoped>
.demo-comp{
  margin: 20px;
  width: 600px;
}
.is-disabled,
.is-disabled:active,
.is-disabled:focus,
.is-disabled:hover{
  cursor:not-allowed;
  background-color:#e4e4ee;
}
</style>

Extension

It could be extended to multifunctional panel, such as search/recently/command, like VsCode
Live dome:https://theoxiong.github.io/vue-search-panel/

For dev:

npm install
npm run dev

API

Attributes

parameterdescriptiontypeoptional valuedefault value
value / v-modeltwo-way binding valueString
placeholderthe placeholder of inputString
widththe width of panelString50%
heightthe height of panelString300px
topthe marginTop of panelString0px
bottomthe marginBottom of panelString0px
leftthe marginLeft of panelString0px
rightthe marginRight of panelString0px
fixedwhether positioned relative to the viewportBooleantrue
placementspecifying the placement of panel relative to the viewport (ignored when the fiexd value is false)Stringtop/bottom/left/righttop
fetchSuggestionsa method to fetch input suggestions. when suggestions are ready, invoke callback(data:[]) to return themFunction(queryString, cb)
closeOnPressEscapewhether close panel on press ESCBooleantrue
closeOnSelectwhether close panel on selectBooleantrue
clearOnClosewhether clear input value when the panel closedBooleantrue
selectWhenUnmatchedwhether to emit a select event on enter when there is no matchBooleanfalse
triggerOnFocuswhether show suggestions when input focusBooleantrue
highlightFirstItemwhether to highlight first itemBooleantrue
valueColorthe color of suggestion item (when there is no scoped slot)String#606266
scrollBarColorthe color of scroll barString#DFDFDF
scrollBarOpacitythe opacity of scroll barNumber0.8
panelBackgroundthe background color of panelString#FFFFFF
panelBorderRadiusthe border radius of panelString0px
panelBoxShadowthe boxShadow color of panelStringrgba(0, 0, 0, 0.3)
highlightedColorthe color of suggestion item when highlightedString#F5F7FA
hoveredColorthe color of suggestion item when hoveredString#C5C7CA
placeholderEffectthe color of placeholder textStringlight/darklight
inputColorthe color of input textString#606266
inputBackgroundthe background color of input fieldString#FFFFFF
inputBorderColorthe border color of input fieldString#DCDFE6
inputBorderColorHoveringthe border color of input field when hoveredString#B0B3BB
inputBorderColorFocusedthe border color of input field when focusedString#575F96

Methods

method namedescriptionparameters
showopen the panel
closeclose the panel
focusInputfocus the input element
getInputElementget the input element

Events

event namedescriptionparameters
opentriggers when the panel opens
openedtriggers when the panel opening animation ends
closetriggers when the panel closes
closedtriggers when the panel closing animation ends
focustriggers when the input element focused
blurtriggers when the input element blurred
selecttriggers when a suggestion is clickedsuggestion being clicked

Slots

Scoped slot

Custom content for input suggestions, the scope parameter is { item }

Named slot

namedescription
upon-itemcontent on the top of suggestions

Reference

  • VS Code
  • Element UI