{"id":15067470,"url":"https://github.com/invisiburu/vue-picker","last_synced_at":"2025-09-11T05:34:15.385Z","repository":{"id":38287943,"uuid":"284347792","full_name":"invisiburu/vue-picker","owner":"invisiburu","description":"A native-like select field, but better","archived":false,"fork":false,"pushed_at":"2023-03-05T10:08:07.000Z","size":5001,"stargazers_count":17,"open_issues_count":23,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-18T03:46:36.630Z","etag":null,"topics":["picker","vue","vuejs2","vuejs3"],"latest_commit_sha":null,"homepage":"","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/invisiburu.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-01T22:16:51.000Z","updated_at":"2025-01-25T18:00:44.000Z","dependencies_parsed_at":"2024-06-19T16:02:31.332Z","dependency_job_id":null,"html_url":"https://github.com/invisiburu/vue-picker","commit_stats":{"total_commits":91,"total_committers":2,"mean_commits":45.5,"dds":0.01098901098901095,"last_synced_commit":"ef2c4fd787ea473d1ea3b0102421864d0064caab"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invisiburu%2Fvue-picker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invisiburu%2Fvue-picker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invisiburu%2Fvue-picker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invisiburu%2Fvue-picker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/invisiburu","download_url":"https://codeload.github.com/invisiburu/vue-picker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248233936,"owners_count":21069493,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["picker","vue","vuejs2","vuejs3"],"created_at":"2024-09-25T01:24:19.591Z","updated_at":"2025-04-10T14:22:39.218Z","avatar_url":"https://github.com/invisiburu.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vue-picker\n\nA native-like select field, but better.\n\n![version](https://badgen.net/github/tag/invisiburu/vue-picker)\n![min size](https://badgen.net/bundlephobia/min/@invisiburu/vue-picker)\n![minzip size](https://badgen.net/bundlephobia/minzip/@invisiburu/vue-picker)\n![deps count](https://badgen.net/bundlephobia/dependency-count/@invisiburu/vue-picker)\n![tree shaking](https://badgen.net/bundlephobia/tree-shaking/@invisiburu/vue-picker)\n\nMostly behaves like native `\u003cselect\u003e` but accepts custom markup for the options\nand the opener button.\n\nThe options are navigatable from the keyboard. The opener text is easily\ncustomizable.\n\nThe package versions of 2 and higher work with Vue3. For Vue2, use prior\nversions of the package.\n\n## Demo\nSee the demo: https://invisiburu.github.io/vue-picker/\n\nSee the demo sources in [demo/](demo/)\n\n## The Problem\nWhen you think about a custom selector, you usually come to provide the\noptions as an array. For sure, it resolves some reactivity issues by default\nbut also has some pitfalls.\n\nOne such pitfall that in most cases, you need to map your data list to an\narray of something like `{ label, value }` thus spending extra resources.\nAdditionally, you write dummy code to display an options selector.\n\nThe second pitfall is that default `\u003cselect\u003e` provides a more natural way\nto render lists - just by giving the elements by themselves, not the arrays.\n\nThe third pitfall is the poor customization capabilities of the options.\nWhich mostly looks similar to the problem of default `\u003cselect\u003e`\nbut a bit milder.\n\n`VuePicker` resolves all of these issues.\n\n## TypeScript\nCurrently, `VuePicker` comes with no TS declarations because of the poor TS\nsupport within Vue infrastructure. Please contact me or craft an issue if you\nthink the times have changed or you have any other arguments of introducing\nTypeScript to the package. Also, you're welcome to contribute.\n\n## Installation\n### Using unpkg:\n```html\n\u003chead\u003e\n  \u003cscript src=\"https://unpkg.com/vue@3\"\u003e\u003c/script\u003e\n  \u003cscript src=\"https://unpkg.com/@invisiburu/vue-picker\"\u003e\u003c/script\u003e\n  \u003c!-- optional css --\u003e\n  \u003clink rel=\"stylesheet\" href=\"https://unpkg.com/@invisiburu/vue-picker/dist/vue-picker.min.css\"\u003e\n\u003c/head\u003e\n\n\u003cbody\u003e\n  \u003cdiv id=\"app\"\u003e\u003c/div\u003e\n  \u003cscript\u003e\n    const App = {\n      template:\n        '\u003cdiv\u003e' +\n          '\u003ch3\u003eHello world\u003c/h3\u003e' +\n          '\u003cVuePicker v-model=\"mv\"\u003e' +\n            '\u003cVuePickerOption value=\"opt0\"\u003eOption 0\u003c/VuePickerOption\u003e' +\n            '\u003cVuePickerOption value=\"opt1\"\u003eOption 1\u003c/VuePickerOption\u003e' +\n          '\u003c/VuePicker\u003e' +\n        '\u003c/div\u003e',\n      data: function () { return { mv: 'opt1' } },\n    }\n    const app = Vue.createApp(App)\n    app.use(window.VuePicker)\n    app.mount('#app')\n  \u003c/script\u003e\n\u003c/body\u003e\n```\n\n### Using npm:\n```bash\nnpm i --save @invisiburu/vue-picker\n```\n\nImport in your project:\n```js\nimport { VuePicker, VuePickerOption } from '@invisiburu/vue-picker'\n// optional css\nimport '@invisiburu/vue-picker/dist/vue-picker.min.css'\n\nconst app = createApp(/* ... */)\napp.component('VuePicker', VuePicker)\napp.component('VuePickerOption', VuePickerOption)\n```\n\n## Usage\n### Basic:\n```html\n\u003cVuePicker v-model=\"color\" :isAutofocus=\"true\"\u003e\n  \u003cVuePickerOption value=\"\"\u003eEmpty\u003c/VuePickerOption\u003e\n  \u003cVuePickerOption value=\"red\"\u003eRed\u003c/VuePickerOption\u003e\n  \u003cVuePickerOption value=\"green\"\u003eGreen\u003c/VuePickerOption\u003e\n  \u003cVuePickerOption value=\"blue\"\u003eBlue\u003c/VuePickerOption\u003e\n  \u003cVuePickerOption value=\"yellow\" :isDisabled=\"true\"\u003eYellow\u003c/VuePickerOption\u003e\n  \u003cVuePickerOption value=\"teal\" text=\"Teal\"\u003e\n    How about teal (Teal will be shown instead)\n  \u003c/VuePickerOption\u003e\n\u003c/VuePicker\u003e\n```\n\n### Custom options:\n```html\n\u003ctemplate\u003e\n  \u003cVuePicker v-model=\"variant\"\u003e\n    \u003cVuePickerOption value=\"italic-bold\"\u003e\n      Some \u003ci\u003eitalics\u003c/i\u003e or \u003cb\u003ebold\u003c/b\u003e?\n    \u003c/VuePickerOption\u003e\n\n    \u003cVuePickerOption value=\"special\" text=\"Special! Yes!\"\u003e\n      \u003cdiv class=\"grid\"\u003e\n        \u003cspan class=\"title\"\u003eOr something more special?\u003c/span\u003e\n        \u003cspan class=\"subtitle\"\u003eI am a subheading!\u003c/span\u003e\n      \u003c/div\u003e\n    \u003c/VuePickerOption\u003e\n  \u003c/VuePicker\u003e\n\u003c/template\u003e\n\n\u003cstyle scoped\u003e\n.grid {\n  display: grid;\n  grid: auto-flow auto / auto;\n  gap: 4px;\n}\n\n.title {\n  font-size: 1.05em;\n  font-weight: bold;\n}\n\n.subtitle {\n  font-size: 0.9em;\n  color: lightgray;\n}\n\u003c/style\u003e\n```\n\n### Custom opener:\n```html\n\u003ctemplate\u003e\n  \u003cVuePicker v-model=\"custom\"\u003e\n    \u003ctemplate #opener=\"{ opener }\"\u003e\n      \u003cspan\u003e\n        \u003ci\u003e{{ opener.value }}\u003c/i\u003e\n        \u003cb\u003e{{ opener.text }}\u003c/b\u003e\n      \u003c/span\u003e\n    \u003c/template\u003e\n\n    \u003cVuePickerOption value=\"value-1\"\u003eValue 1\u003c/VuePickerOption\u003e\n    \u003cVuePickerOption value=\"value-2\"\u003eValue 2\u003c/VuePickerOption\u003e\n  \u003c/VuePicker\u003e\n\u003c/template\u003e\n```\n\n## Api\n### `VuePicker`\n#### Props:\n- `modelValue` - the value, should be a string. The behaviour is not defined for\n  values that do not exist within provided options.\n- `placeholder` - a text to show when `value` is null, undefined or an\n  empty string.\n- `isAutofocus` - focus the opener on mount.\n- `isDisabled` - disable the component.\n- `onKeyDown` - accepts a function to run before the default key-down listener.\n  Please see the [onKeyDown()](#onkeydown-prop) section for more details\n#### Emitted events:\n- `input` - an option selected. Carries the new value to assign.\n- `open` - dropdown open.\n- `close` - dropdown closed. Carries `true` if closed by the outer click.\n#### Slots:\n- `default` - a picker option. Should be a `\u003cVuePickerOption\u003e`.\n- `opener` - override the displayed opener text.\n  Provides the `opener` scope var with `{ value, text, opt }`, where:\n    - `value` - the selected value.\n    - `text` - the text that was intended to display by the opener\n      (HTML stripped). Content of the `placeholder` attribute prevails over\n      empty option values.\n    - `opt` - context of the current option.\n- `openerIco` - override the default expand arrow\n- `dropdownInner` - use if you want a custom dropdown inner container\n\n### `VuePickerOption`\n#### Props:\n- `isDisabled` - disable the option. Disabled options cannot be picked or\n  navigated.\n- `value` - value to set on when the option selected.\n- `text` - text to be displayed instead of the content of the `default` slot.\n  Also overrides the `optHtml` and `optTxt` computed properties of the\n  component.\n#### Slots:\n- `default` - content to be displayed in the options list and in the opener\n  when the option is selected. Can contain any markup, the opener will\n  display it as is. Please consider using the `text` prop if you plan complex\n  things in here.\n#### Computed\nYou can use these computed properties within the `opt` param of the `opener`\nslot.\n- `optHtml` - returns the HTML from the `default` slot of the component.\n- `optTxt` - returns the HTML from the `default` slot of the component.\n  Mostly the same as `text` param of the `opener` slot but does not respect\n  `placeholder` attr of the picker.\n\n### `onKeyDown prop`\nAccepts a function like the following:\n```ts\nfunction onKeyDown (event: KeyboardEvent, dropdown: any, options: any) =\u003e boolean\n```\n\nThe listener is fired in two cases:\n1. When the dropdown in open\n2. When the dropdown is closed but the opener is focused\n\nReturn `false` from your `onKeyDown()` function to prevent the default\nkey-down handler.\n\n## Issues\nIn case of a bug or a suggestion, please report on the [Issues page](https://github.com/invisiburu/vue-picker/issues)\nor contact me by email.\n\n## Changelog\nCheck the changes in [CHANGELOG.md](CHANGELOG.md)\n\n## TODO\n- TS definitions\n- Better onKeyDown description\n- Unit tests\n- Search\n- Handle keys: Page down, Page up\n- Animation support\n- Dropdown position switch if does not fit the screen\n- Outer label[for=\"\"] support\n- Readonly attr - ?\n- iOS, Android full screen style - ?\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finvisiburu%2Fvue-picker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finvisiburu%2Fvue-picker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finvisiburu%2Fvue-picker/lists"}