├── .browserslistrc ├── .eslintrc.js ├── .github ├── FUNDING.yml └── workflows │ └── yarn.yml ├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── build └── rollup.config.js ├── css └── tailwind.css ├── jest.config.js ├── package.json ├── postcss.config.js ├── public ├── favicon.ico └── index.html ├── shims-tsx.d.ts ├── shims-vue.d.ts ├── src ├── App.vue ├── base │ ├── Component.ts │ ├── HtmlInput.ts │ ├── InputWithOptions.ts │ ├── MultipleInput.ts │ └── TextInput.ts ├── components.ts ├── components │ ├── TAlert.ts │ ├── TCard.ts │ ├── TCheckboxGroup.ts │ ├── TDatepicker.ts │ ├── TDatepicker │ │ ├── TDatePickerViewsViewCalendarDays.ts │ │ ├── TDatepickerNavigator.ts │ │ ├── TDatepickerNavigatorYearMonthSelector.ts │ │ ├── TDatepickerNavigatorYearMonthSelectorMonth.ts │ │ ├── TDatepickerNavigatorYearMonthSelectorYear.ts │ │ ├── TDatepickerTimeSelector.ts │ │ ├── TDatepickerTrigger.ts │ │ ├── TDatepickerViews.ts │ │ ├── TDatepickerViewsView.ts │ │ ├── TDatepickerViewsViewCalendar.ts │ │ ├── TDatepickerViewsViewCalendarDays.ts │ │ ├── TDatepickerViewsViewCalendarDaysDay.ts │ │ ├── TDatepickerViewsViewCalendarHeaders.ts │ │ ├── TDatepickerViewsViewMonths.ts │ │ ├── TDatepickerViewsViewMonthsMonth.ts │ │ ├── TDatepickerViewsViewYears.ts │ │ └── TDatepickerViewsViewYearsYear.ts │ ├── TDialog.ts │ ├── TDialog │ │ ├── TDialogOverlay.ts │ │ ├── TDialogOverlayWrapper.ts │ │ ├── TDialogOverlayWrapperTransition.ts │ │ ├── TDialogOverlayWrapperTransitionDialog.ts │ │ ├── TDialogOverlayWrapperTransitionDialogButtons.ts │ │ ├── TDialogOverlayWrapperTransitionDialogClose.ts │ │ ├── TDialogOverlayWrapperTransitionDialogContent.ts │ │ ├── TDialogOverlayWrapperTransitionDialogContentInput.ts │ │ ├── TDialogOverlayWrapperTransitionDialogIcon.ts │ │ └── TDialogOverlayWrapperTransitionDialogLoader.ts │ ├── TDropdown.ts │ ├── TInputGroup.ts │ ├── TModal.ts │ ├── TPagination.ts │ ├── TRadioGroup.ts │ ├── TRichSelect.ts │ ├── TTable.ts │ ├── TTag.ts │ └── TToggle.ts ├── configure.ts ├── full.ts ├── index.ts ├── inputs │ ├── TButton.ts │ ├── TCheckbox.ts │ ├── TInput.ts │ ├── TRadio.ts │ ├── TSelect.ts │ └── TTextarea.ts ├── l10n │ ├── ar.ts │ ├── at.ts │ ├── az.ts │ ├── be.ts │ ├── bg.ts │ ├── bn.ts │ ├── bs.ts │ ├── cat.ts │ ├── cs.ts │ ├── cy.ts │ ├── da.ts │ ├── de.ts │ ├── default.ts │ ├── eo.ts │ ├── es.ts │ ├── et.ts │ ├── fa.ts │ ├── fi.ts │ ├── fo.ts │ ├── fr.ts │ ├── ga.ts │ ├── gr.ts │ ├── he.ts │ ├── hi.ts │ ├── hr.ts │ ├── hu.ts │ ├── id.ts │ ├── index.ts │ ├── is.ts │ ├── it.ts │ ├── ja.ts │ ├── ka.ts │ ├── km.ts │ ├── ko.ts │ ├── kz.ts │ ├── lt.ts │ ├── lv.ts │ ├── mk.ts │ ├── mn.ts │ ├── ms.ts │ ├── my.ts │ ├── nl.ts │ ├── no.ts │ ├── pa.ts │ ├── pl.ts │ ├── pt.ts │ ├── ro.ts │ ├── ru.ts │ ├── si.ts │ ├── sk.ts │ ├── sl.ts │ ├── sq.ts │ ├── sr-cyr.ts │ ├── sr.ts │ ├── sv.ts │ ├── th.ts │ ├── tr.ts │ ├── uk.ts │ ├── uz.ts │ ├── uz_latn.ts │ ├── vn.ts │ ├── zh-tw.ts │ └── zh.ts ├── main.ts ├── renderers │ └── TRichSelectRenderer.ts ├── t-alert.ts ├── t-button.ts ├── t-card.ts ├── t-checkbox-group.ts ├── t-checkbox.ts ├── t-datepicker.ts ├── t-dialog.ts ├── t-dropdown.ts ├── t-input-group.ts ├── t-input.ts ├── t-modal.ts ├── t-pagination.ts ├── t-radio-group.ts ├── t-radio.ts ├── t-rich-select.ts ├── t-select.ts ├── t-table.ts ├── t-tag.ts ├── t-textarea.ts ├── t-toggle.ts ├── types │ ├── CheckboxValues.ts │ ├── ComponentName.ts │ ├── ComponentSettings.ts │ ├── ComponentVariants.ts │ ├── CssClass.ts │ ├── CssClasses.ts │ ├── CustomProps.ts │ ├── Dialog.ts │ ├── InputOption.ts │ ├── InputOptions.ts │ ├── Key.ts │ ├── LibrarySettings.ts │ ├── NormalizedOption.ts │ ├── NormalizedOptions.ts │ ├── TRichSelect.ts │ └── locale.ts └── utils │ ├── configureDialogGlobals.ts │ ├── dates.ts │ ├── formatting.ts │ ├── index.ts │ ├── inputOptions.ts │ ├── isNumeric.ts │ └── uniqid.ts ├── tailwind.config.js ├── tests └── unit │ ├── ComponentClasses.spec.js │ ├── TAlert.spec.js │ ├── TButton.spec.js │ ├── TCard.spec.js │ ├── TCheckbox.spec.js │ ├── TCheckboxGroup.spec.js │ ├── TDatepicker.spec.js │ ├── TDatepicker │ └── TDatepickerTimeSelector.spec.js │ ├── TDialog.spec.js │ ├── TDropdown.spec.js │ ├── TInput.spec.js │ ├── TInputGroup.spec.js │ ├── TModal.spec.js │ ├── TPagination.spec.js │ ├── TRadio.spec.js │ ├── TRadioGroup.spec.js │ ├── TRichSelect.spec.js │ ├── TSelect.spec.js │ ├── TTable.spec.js │ ├── TTag.spec.js │ ├── TTextarea.spec.js │ ├── TToggle.spec.js │ └── utils │ └── formatDate.spec.js ├── tsconfig.json ├── vue-tailwind.d.ts ├── vue.config.js └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | }, 6 | extends: [ 7 | 'plugin:vue/recommended', 8 | '@vue/airbnb', 9 | '@vue/typescript/recommended', 10 | ], 11 | parserOptions: { 12 | ecmaVersion: 2020, 13 | }, 14 | rules: { 15 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 16 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 17 | 'no-shadow': 'off', 18 | 'max-len': 'off', 19 | 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], 20 | }, 21 | overrides: [ 22 | { 23 | files: [ 24 | '**/__tests__/*.{j,t}s?(x)', 25 | '**/tests/unit/**/*.spec.{j,t}s?(x)', 26 | ], 27 | env: { 28 | jest: true, 29 | }, 30 | }, 31 | ], 32 | }; 33 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: alfonsobries 4 | open_collective: vue-tailwind 5 | custom: https://www.buymeacoffee.com/alfonsobries 6 | -------------------------------------------------------------------------------- /.github/workflows/yarn.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: push 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | - name: Install modules 9 | run: yarn 10 | - name: Run tests 11 | run: yarn test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | .editorconfig 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Alfonso Bribiesca 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset', 4 | ], 5 | }; 6 | -------------------------------------------------------------------------------- /build/rollup.config.js: -------------------------------------------------------------------------------- 1 | import vue from 'rollup-plugin-vue'; 2 | import typescript from '@rollup/plugin-typescript'; 3 | import del from 'rollup-plugin-delete'; 4 | import multiInput from 'rollup-plugin-multi-input'; 5 | 6 | const globals = { 7 | 'body-scroll-lock': 'bodyScrollLock', 8 | 'lodash.clonedeep': 'cloneDeep', 9 | 'lodash.get': 'get', 10 | 'lodash.intersection': 'intersection', 11 | 'lodash.isequal': 'isEqual', 12 | 'lodash.kebabcase': 'kebabCase', 13 | 'lodash.map': 'map', 14 | 'lodash.mapvalues': 'mapValues', 15 | 'lodash.merge': 'merge', 16 | 'lodash.pick': 'pick', 17 | 'lodash.range': 'range', 18 | vue: 'Vue', 19 | }; 20 | 21 | const config = [ 22 | { 23 | input: 'src/index.ts', // Path relative to package.json 24 | output: { 25 | sourcemap: true, 26 | dir: 'dist', 27 | entryFileNames: 'vue-tailwind.js', 28 | format: 'umd', 29 | name: 'VueTailwind', 30 | exports: 'named', 31 | globals, 32 | }, 33 | external: Object.keys(globals), 34 | plugins: [ 35 | del({ targets: 'dist/*' }), 36 | typescript({ 37 | declaration: true, 38 | declarationDir: 'dist', 39 | rootDir: 'src', 40 | }), 41 | vue(), 42 | ], 43 | }, 44 | { 45 | input: 'src/full.ts', 46 | output: { 47 | sourcemap: true, 48 | dir: 'dist', 49 | entryFileNames: 'full.js', 50 | format: 'umd', 51 | name: 'VueTailwind', 52 | exports: 'named', 53 | globals, 54 | }, 55 | external: Object.keys(globals), 56 | plugins: [ 57 | typescript({ 58 | rootDir: 'src', 59 | }), 60 | vue(), 61 | ], 62 | }, 63 | { 64 | input: 'src/components.ts', 65 | output: { 66 | sourcemap: true, 67 | dir: 'dist', 68 | entryFileNames: 'components.js', 69 | format: 'umd', 70 | name: 'VueTailwind', 71 | exports: 'named', 72 | globals, 73 | }, 74 | external: Object.keys(globals), 75 | plugins: [ 76 | typescript({ 77 | rootDir: 'src', 78 | }), 79 | vue(), 80 | ], 81 | }, 82 | ]; 83 | 84 | const components = { 85 | 't-input': 'TInput', 86 | 't-button': 'TButton', 87 | 't-checkbox': 'TCheckbox', 88 | 't-radio': 'TRadio', 89 | 't-select': 'TSelect', 90 | 't-textarea': 'TTextarea', 91 | 't-rich-select': 'TRichSelect', 92 | 't-input-group': 'TInputGroup', 93 | 't-card': 'TCard', 94 | 't-alert': 'TAlert', 95 | 't-modal': 'TModal', 96 | 't-dropdown': 'TDropdown', 97 | 't-pagination': 'TPagination', 98 | 't-tag': 'TTag', 99 | 't-radio-group': 'TRadioGroup', 100 | 't-checkbox-group': 'TCheckboxGroup', 101 | 't-table': 'TTable', 102 | 't-datepicker': 'TDatepicker', 103 | 't-toggle': 'TToggle', 104 | 't-dialog': 'TDialog', 105 | }; 106 | 107 | const componentsConfig = Object.keys(components).map((component) => { 108 | const componentName = components[component]; 109 | 110 | return { 111 | input: `src/${component}.ts`, // Path relative to package.json 112 | output: { 113 | sourcemap: true, 114 | dir: 'dist', 115 | entryFileNames: `${component}.js`, 116 | format: 'umd', 117 | name: componentName, 118 | exports: 'named', 119 | globals, 120 | }, 121 | external: Object.keys(globals), 122 | plugins: [ 123 | typescript({ 124 | declaration: true, 125 | declarationDir: 'dist', 126 | rootDir: 'src', 127 | }), 128 | vue(), 129 | ], 130 | }; 131 | }).flat(); 132 | 133 | const helpers = [ 134 | { 135 | input: 'src/configure.ts', // Path relative to package.json 136 | output: { 137 | sourcemap: true, 138 | dir: 'dist', 139 | entryFileNames: 'configure.js', 140 | format: 'umd', 141 | name: 'configure', 142 | exports: 'named', 143 | globals, 144 | }, 145 | external: Object.keys(globals), 146 | plugins: [ 147 | typescript({ 148 | declaration: true, 149 | declarationDir: 'dist', 150 | rootDir: 'src', 151 | }), 152 | ], 153 | }, 154 | { 155 | input: 'src/l10n/*.ts', 156 | output: { 157 | sourcemap: true, 158 | format: 'esm', 159 | dir: 'dist', 160 | }, 161 | plugins: [ 162 | multiInput(), 163 | typescript(), 164 | ], 165 | }, 166 | ]; 167 | 168 | // Transpile/polyfill with reasonable browser support 169 | export default config.concat(componentsConfig, helpers); 170 | -------------------------------------------------------------------------------- /css/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | 3 | @tailwind components; 4 | 5 | @tailwind utilities; -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel', 3 | }; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-tailwind", 3 | "version": "2.5.1", 4 | "description": "Vue components styled with TailwindCss with configurable classes", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/alfonsobries/vue-tailwind" 8 | }, 9 | "keywords": [ 10 | "tailwindcss", 11 | "vue", 12 | "vue-tailwind", 13 | "vue components", 14 | "tailwind components" 15 | ], 16 | "author": "Alfonso Bribiesca (https://www.vexilo.com/)", 17 | "license": "MIT", 18 | "private": false, 19 | "scripts": { 20 | "serve": "vue-cli-service serve", 21 | "build": "rollup --config build/rollup.config.js", 22 | "test": "vue-cli-service test:unit", 23 | "test:watch": "vue-cli-service test:unit --watch", 24 | "lint": "vue-cli-service lint", 25 | "release": "release-it" 26 | }, 27 | "dependencies": { 28 | "body-scroll-lock": "^3.1.5", 29 | "lodash.clonedeep": "^4.5.0", 30 | "lodash.get": "^4.4.2", 31 | "lodash.intersection": "^4.4.0", 32 | "lodash.isequal": "^4.5.0", 33 | "lodash.kebabcase": "^4.1.1", 34 | "lodash.map": "^4.6.0", 35 | "lodash.mapvalues": "^4.6.0", 36 | "lodash.merge": "^4.6.2", 37 | "lodash.pick": "^4.4.0", 38 | "lodash.range": "^3.2.0" 39 | }, 40 | "devDependencies": { 41 | "@rollup/plugin-typescript": "^6.1.0", 42 | "@tailwindcss/forms": "^0.2.1", 43 | "@types/body-scroll-lock": "^2.6.1", 44 | "@types/jest": "^26.0.16", 45 | "@types/lodash.clonedeep": "^4.5.6", 46 | "@types/lodash.get": "^4.4.6", 47 | "@types/lodash.intersection": "^4.4.6", 48 | "@types/lodash.isequal": "^4.5.5", 49 | "@types/lodash.kebabcase": "^4.1.6", 50 | "@types/lodash.map": "^4.6.13", 51 | "@types/lodash.mapvalues": "^4.6.6", 52 | "@types/lodash.merge": "^4.6.6", 53 | "@types/lodash.pick": "^4.4.6", 54 | "@types/lodash.range": "^3.2.6", 55 | "@types/vue": "^2.0.0", 56 | "@typescript-eslint/eslint-plugin": "^4.9.0", 57 | "@typescript-eslint/parser": "^4.9.0", 58 | "@vue/cli-plugin-babel": "~4.5.9", 59 | "@vue/cli-plugin-eslint": "~4.5.9", 60 | "@vue/cli-plugin-typescript": "~4.5.9", 61 | "@vue/cli-plugin-unit-jest": "^4.5.9", 62 | "@vue/cli-service": "~4.5.9", 63 | "@vue/compiler-sfc": "^3.0.4", 64 | "@vue/eslint-config-airbnb": "^5.1.0", 65 | "@vue/eslint-config-typescript": "^7.0.0", 66 | "@vue/test-utils": "1.1.1", 67 | "autoprefixer": "^9", 68 | "eslint": "^7.13.0", 69 | "eslint-plugin-import": "^2.22.1", 70 | "eslint-plugin-vue": "^7.2.0", 71 | "postcss": "^7", 72 | "release-it": "^14.2.2", 73 | "rollup": "^2.34.2", 74 | "rollup-plugin-delete": "^2.0.0", 75 | "rollup-plugin-multi-input": "^1.1.1", 76 | "rollup-plugin-vue": "^6.0.0", 77 | "tailwindcss": "npm:@tailwindcss/postcss7-compat", 78 | "tslib": "^2.0.3", 79 | "typescript": "~3.9.7", 80 | "vue-template-compiler": "^2", 81 | "vue": "^2" 82 | }, 83 | "homepage": "https://vue-tailwind.com", 84 | "files": [ 85 | "dist/*" 86 | ], 87 | "typings": "./dist/index.d.ts", 88 | "main": "dist/vue-tailwind.js", 89 | "release-it": { 90 | "hooks": { 91 | "before:init": [ 92 | "yarn test" 93 | ], 94 | "after:bump": "yarn build" 95 | } 96 | }, 97 | "peerDependencies": { 98 | "vue": "^2" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfonsobries/vue-tailwind/7ff9278d66a8b75234fbfedcd6dc1ed1c51f50cf/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /shims-tsx.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, { VNode } from 'vue'; 2 | 3 | declare global { 4 | namespace JSX { 5 | // tslint:disable no-empty-interface 6 | interface Element extends VNode {} 7 | // tslint:disable no-empty-interface 8 | interface ElementClass extends Vue {} 9 | interface IntrinsicElements { 10 | [elem: string]: any; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue'; 3 | 4 | export default Vue; 5 | } 6 | -------------------------------------------------------------------------------- /src/base/Component.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import get from 'lodash.get'; 3 | import CssClass from '../types/CssClass'; 4 | 5 | const mergeClasses = (classesA: CssClass, classesB: CssClass): CssClass => { 6 | let a = classesA; 7 | let b = classesB; 8 | 9 | // Convert array of string classes to a single string 10 | if (Array.isArray(classesA) && classesA.every((className) => typeof className === 'string' || !!className)) { 11 | a = classesA.filter((className) => !!className).join(' '); 12 | } 13 | 14 | // Convert array of string classes to a single string 15 | if (Array.isArray(classesB) && classesB.every((className) => typeof className === 'string' || !!className)) { 16 | b = classesB.filter((className) => !!className).join(' '); 17 | } 18 | 19 | if (typeof a === 'string' && typeof b === 'string') { 20 | return `${a} ${b}`; 21 | } 22 | 23 | if (typeof a === 'string' && Array.isArray(b)) { 24 | return [a].concat(b); 25 | } 26 | 27 | if (typeof b === 'string' && Array.isArray(a)) { 28 | return a.concat([b]); 29 | } 30 | 31 | if (Array.isArray(a) && Array.isArray(b)) { 32 | return a.concat(b); 33 | } 34 | 35 | return [a, b]; 36 | }; 37 | 38 | const Component = Vue.extend({ 39 | props: { 40 | classes: { 41 | type: [String, Array, Object], 42 | default: undefined, 43 | }, 44 | fixedClasses: { 45 | type: [String, Array, Object], 46 | default: undefined, 47 | }, 48 | variants: { 49 | type: Object, 50 | default: undefined, 51 | }, 52 | variant: { 53 | type: [String, Object], 54 | default: undefined, 55 | }, 56 | }, 57 | 58 | computed: { 59 | componentClass(): CssClass { 60 | return this.getElementCssClass(); 61 | }, 62 | activeVariant(): string | undefined { 63 | if (!this.variant) { 64 | return undefined; 65 | } 66 | 67 | if (typeof this.variant === 'object') { 68 | const truthyVariant = Object.keys(this.variant).find((variant) => !!this.variant[variant]); 69 | return truthyVariant || undefined; 70 | } 71 | 72 | return this.variant; 73 | }, 74 | }, 75 | 76 | methods: { 77 | getElementCssClass( 78 | elementName?: string, 79 | defaultClasses: CssClass = '', 80 | ): CssClass { 81 | let classes; 82 | 83 | if (elementName) { 84 | if (this.activeVariant) { 85 | const elementVariant = get(this.variants, `${this.activeVariant}.${elementName}`); 86 | // If the variant exists but not for the element fallback to the default 87 | if (elementVariant === undefined 88 | && get(this.variants, this.activeVariant) !== undefined) { 89 | classes = get(this.classes, elementName, defaultClasses); 90 | } else { 91 | classes = elementVariant === undefined ? defaultClasses : elementVariant; 92 | } 93 | } else { 94 | classes = get(this.classes, elementName, defaultClasses); 95 | } 96 | 97 | const fixedClasses = get(this.fixedClasses, elementName); 98 | 99 | if (fixedClasses) { 100 | return mergeClasses(fixedClasses, classes); 101 | } 102 | 103 | return classes; 104 | } 105 | 106 | if (this.activeVariant) { 107 | classes = get(this.variants, this.activeVariant, defaultClasses); 108 | } else { 109 | classes = this.classes === undefined ? defaultClasses : this.classes; 110 | } 111 | 112 | if (this.fixedClasses) { 113 | return mergeClasses(this.fixedClasses, classes); 114 | } 115 | 116 | return classes; 117 | }, 118 | }, 119 | }); 120 | 121 | export default Component; 122 | -------------------------------------------------------------------------------- /src/base/HtmlInput.ts: -------------------------------------------------------------------------------- 1 | import Component from './Component'; 2 | 3 | type EventListenerOptions = { 4 | // eslint-disable-next-line @typescript-eslint/ban-types 5 | [key: string]: Function | Function[]; 6 | } | undefined 7 | 8 | const HtmlInput = Component.extend({ 9 | props: { 10 | id: { 11 | type: String, 12 | default: undefined, 13 | }, 14 | name: { 15 | type: String, 16 | default: undefined, 17 | }, 18 | disabled: { 19 | type: Boolean, 20 | default: undefined, 21 | }, 22 | readonly: { 23 | type: Boolean, 24 | default: undefined, 25 | }, 26 | autofocus: { 27 | type: Boolean, 28 | default: undefined, 29 | }, 30 | required: { 31 | type: Boolean, 32 | default: undefined, 33 | }, 34 | tabindex: { 35 | type: [String, Number], 36 | default: undefined, 37 | }, 38 | }, 39 | methods: { 40 | getListeners(listeners: EventListenerOptions): EventListenerOptions { 41 | return { 42 | ...this.$listeners, 43 | ...listeners, 44 | }; 45 | }, 46 | }, 47 | }); 48 | 49 | export default HtmlInput; 50 | -------------------------------------------------------------------------------- /src/base/InputWithOptions.ts: -------------------------------------------------------------------------------- 1 | import HtmlInput from './HtmlInput'; 2 | import InputOptions from '../types/InputOptions'; 3 | import NormalizedOptions from '../types/NormalizedOptions'; 4 | import { normalizeOptions } from '../utils/inputOptions'; 5 | 6 | const InputWithOptions = HtmlInput.extend({ 7 | props: { 8 | value: { 9 | type: [String, Object, Number, Boolean], 10 | default: null, 11 | }, 12 | valueAttribute: { 13 | type: String, 14 | default: undefined, 15 | }, 16 | textAttribute: { 17 | type: String, 18 | default: undefined, 19 | }, 20 | options: { 21 | type: [Array, Object], 22 | default: undefined, 23 | }, 24 | }, 25 | data() { 26 | return { 27 | localValue: this.value, 28 | }; 29 | }, 30 | computed: { 31 | normalizedOptions(): NormalizedOptions { 32 | return this.normalizeOptions(this.options); 33 | }, 34 | 35 | flattenedOptions(): NormalizedOptions { 36 | return this.normalizedOptions.map((option) => { 37 | if (option.children) { 38 | return option.children; 39 | } 40 | 41 | return option; 42 | }).flat(); 43 | }, 44 | }, 45 | methods: { 46 | normalizeOptions(options: InputOptions) { 47 | return normalizeOptions(options, this.textAttribute, this.valueAttribute); 48 | }, 49 | }, 50 | }); 51 | 52 | export default InputWithOptions; 53 | -------------------------------------------------------------------------------- /src/base/MultipleInput.ts: -------------------------------------------------------------------------------- 1 | import InputWithOptions from './InputWithOptions'; 2 | 3 | const MultipleInput = InputWithOptions.extend({ 4 | props: { 5 | value: { 6 | type: [Array, String, Number, Boolean, Object], 7 | default: null, 8 | }, 9 | multiple: { 10 | type: Boolean, 11 | default: undefined, 12 | }, 13 | }, 14 | }); 15 | 16 | export default MultipleInput; 17 | -------------------------------------------------------------------------------- /src/base/TextInput.ts: -------------------------------------------------------------------------------- 1 | import HtmlInput from './HtmlInput'; 2 | 3 | const TextInput = HtmlInput.extend({ 4 | props: { 5 | value: { 6 | type: [String, Number], 7 | default: undefined, 8 | }, 9 | autocomplete: { 10 | type: String, 11 | default: undefined, 12 | }, 13 | maxlength: { 14 | type: [String, Number], 15 | default: undefined, 16 | }, 17 | minlength: { 18 | type: [String, Number], 19 | default: undefined, 20 | }, 21 | multiple: { 22 | type: Boolean, 23 | default: undefined, 24 | }, 25 | pattern: { 26 | type: String, 27 | default: undefined, 28 | }, 29 | placeholder: { 30 | type: String, 31 | default: undefined, 32 | }, 33 | classes: { 34 | type: [String, Array, Object], 35 | default: undefined, 36 | }, 37 | }, 38 | 39 | data() { 40 | return { 41 | localValue: this.value as string | number | null, 42 | valueWhenFocus: null as string | number | null, 43 | }; 44 | }, 45 | 46 | watch: { 47 | localValue(localValue: string | null) { 48 | this.$emit('input', localValue); 49 | }, 50 | value(value: string | null) { 51 | this.localValue = value; 52 | }, 53 | }, 54 | 55 | methods: { 56 | blurHandler(e: FocusEvent) { 57 | this.$emit('blur', e); 58 | 59 | if (this.localValue !== this.valueWhenFocus) { 60 | this.$emit('change', this.localValue); 61 | } 62 | }, 63 | 64 | focusHandler(e: FocusEvent) { 65 | this.$emit('focus', e); 66 | 67 | this.valueWhenFocus = this.localValue; 68 | }, 69 | 70 | keyupHandler(e: KeyboardEvent) { 71 | this.$emit('keyup', e); 72 | }, 73 | 74 | keydownHandler(e: KeyboardEvent) { 75 | this.$emit('keydown', e); 76 | }, 77 | 78 | blur() { 79 | (this.$el as HTMLInputElement).blur(); 80 | }, 81 | 82 | click() { 83 | (this.$el as HTMLInputElement).click(); 84 | }, 85 | 86 | focus(options?: FocusOptions | undefined) { 87 | (this.$el as HTMLInputElement).focus(options); 88 | }, 89 | 90 | select() { 91 | (this.$el as HTMLInputElement).select(); 92 | }, 93 | 94 | setSelectionRange(start: number, end: number, direction?: 'forward' | 'backward' | 'none' | undefined) { 95 | (this.$el as HTMLInputElement).setSelectionRange(start, end, direction); 96 | }, 97 | 98 | setRangeText(replacement: string) { 99 | (this.$el as HTMLInputElement).setRangeText(replacement); 100 | }, 101 | }, 102 | }); 103 | 104 | export default TextInput; 105 | -------------------------------------------------------------------------------- /src/components.ts: -------------------------------------------------------------------------------- 1 | import TCheckbox from './inputs/TCheckbox'; 2 | import TRadio from './inputs/TRadio'; 3 | import TTextarea from './inputs/TTextarea'; 4 | import TInput from './inputs/TInput'; 5 | import TSelect from './inputs/TSelect'; 6 | import TButton from './inputs/TButton'; 7 | import TRichSelect from './components/TRichSelect'; 8 | import TInputGroup from './components/TInputGroup'; 9 | import TCard from './components/TCard'; 10 | import TAlert from './components/TAlert'; 11 | import TModal from './components/TModal'; 12 | import TDropdown from './components/TDropdown'; 13 | import TPagination from './components/TPagination'; 14 | import TTag from './components/TTag'; 15 | import TRadioGroup from './components/TRadioGroup'; 16 | import TCheckboxGroup from './components/TCheckboxGroup'; 17 | import TTable from './components/TTable'; 18 | import TDatepicker from './components/TDatepicker'; 19 | import TToggle from './components/TToggle'; 20 | import TDialog from './components/TDialog'; 21 | 22 | export { 23 | TInput, 24 | TTextarea, 25 | TSelect, 26 | TRadio, 27 | TCheckbox, 28 | TButton, 29 | TInputGroup, 30 | TCard, 31 | TAlert, 32 | TModal, 33 | TDropdown, 34 | TRichSelect, 35 | TPagination, 36 | TTag, 37 | TRadioGroup, 38 | TCheckboxGroup, 39 | TTable, 40 | TDatepicker, 41 | TToggle, 42 | TDialog, 43 | }; 44 | -------------------------------------------------------------------------------- /src/components/TAlert.ts: -------------------------------------------------------------------------------- 1 | import { CreateElement, VNode } from 'vue'; 2 | import Component from '../base/Component'; 3 | 4 | const TAlert = Component.extend({ 5 | name: 'TAlert', 6 | 7 | props: { 8 | tagName: { 9 | type: String, 10 | default: 'div', 11 | }, 12 | bodyTagName: { 13 | type: String, 14 | default: 'div', 15 | }, 16 | dismissible: { 17 | type: Boolean, 18 | default: true, 19 | }, 20 | show: { 21 | type: Boolean, 22 | default: false, 23 | }, 24 | timeout: { 25 | type: Number, 26 | default: undefined, 27 | }, 28 | classes: { 29 | type: Object, 30 | default() { 31 | return { 32 | wrapper: 'relative flex items-center p-4 bg-blue-50 border-l-4 border-blue-500 rounded shadow-sm', 33 | body: 'flex-grow', 34 | close: 'absolute relative flex items-center justify-center flex-shrink-0 w-6 h-6 ml-4 text-blue-500 transition duration-100 ease-in-out rounded hover:bg-blue-200 focus:ring-2 focus:ring-blue-500 focus:outline-none focus:ring-opacity-50', 35 | closeIcon: 'fill-current h-4 w-4', 36 | }; 37 | }, 38 | }, 39 | }, 40 | 41 | data() { 42 | return { 43 | localShow: this.show, 44 | }; 45 | }, 46 | 47 | render(createElement) { 48 | const renderFun: (createElement: CreateElement) => VNode = this.render; 49 | return renderFun(createElement); 50 | }, 51 | 52 | watch: { 53 | show(show) { 54 | this.localShow = show; 55 | }, 56 | localShow(localShow) { 57 | this.$emit('update:show', localShow); 58 | if (this.localShow) { 59 | this.$emit('shown'); 60 | if (this.timeout) { 61 | this.initTimeout(); 62 | } 63 | } else { 64 | this.$emit('hidden'); 65 | } 66 | }, 67 | }, 68 | 69 | mounted() { 70 | if (this.localShow && this.timeout) { 71 | this.initTimeout(); 72 | } 73 | }, 74 | 75 | methods: { 76 | render(createElement: CreateElement) { 77 | if (!this.localShow) { 78 | return createElement(); 79 | } 80 | 81 | return createElement( 82 | this.tagName, 83 | { 84 | class: this.getElementCssClass('wrapper'), 85 | }, 86 | !this.dismissible 87 | ? [ 88 | createElement( 89 | this.bodyTagName, 90 | { 91 | ref: 'body', 92 | class: this.getElementCssClass('body'), 93 | }, 94 | this.$slots.default, 95 | ), 96 | ] 97 | : [ 98 | createElement( 99 | this.bodyTagName, 100 | { 101 | ref: 'body', 102 | class: this.getElementCssClass('body'), 103 | }, 104 | this.$slots.default, 105 | ), 106 | createElement( 107 | 'button', 108 | { 109 | ref: 'close', 110 | class: this.getElementCssClass('close'), 111 | attrs: { 112 | type: 'button', 113 | }, 114 | on: { 115 | click: this.hide, 116 | }, 117 | }, 118 | this.$slots.close 119 | || [ 120 | createElement( 121 | 'svg', 122 | { 123 | attrs: { 124 | fill: 'currentColor', 125 | xmlns: 'http://www.w3.org/2000/svg', 126 | viewBox: '0 0 20 20', 127 | }, 128 | class: this.getElementCssClass('closeIcon'), 129 | }, 130 | [ 131 | createElement('path', { 132 | attrs: { 133 | 'clip-rule': 'evenodd', 134 | 'fill-rule': 'evenodd', 135 | d: 'M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z', 136 | }, 137 | }), 138 | ], 139 | ), 140 | ], 141 | ), 142 | ], 143 | ); 144 | }, 145 | initTimeout() { 146 | setTimeout(() => { 147 | this.hide(); 148 | }, this.timeout); 149 | }, 150 | hide() { 151 | this.localShow = false; 152 | }, 153 | }, 154 | }); 155 | 156 | export default TAlert; 157 | -------------------------------------------------------------------------------- /src/components/TCard.ts: -------------------------------------------------------------------------------- 1 | import { CreateElement, VNode } from 'vue'; 2 | import Component from '../base/Component'; 3 | 4 | const TCard = Component.extend({ 5 | name: 'TCard', 6 | 7 | props: { 8 | tagName: { 9 | type: String, 10 | default: 'div', 11 | }, 12 | header: { 13 | type: String, 14 | default: undefined, 15 | }, 16 | footer: { 17 | type: String, 18 | default: undefined, 19 | }, 20 | noBody: { 21 | type: Boolean, 22 | default: false, 23 | }, 24 | classes: { 25 | type: Object, 26 | default: () => ({ 27 | wrapper: 'border rounded shadow-sm bg-white border-gray-100', 28 | body: 'p-3', 29 | header: 'border-b border-gray-100 p-3 rounded-t', 30 | footer: 'border-gray-100 border-t p-3 rounded-b', 31 | }), 32 | }, 33 | }, 34 | 35 | render(createElement) { 36 | const renderFun: (createElement: CreateElement) => VNode = this.render; 37 | return renderFun(createElement); 38 | }, 39 | 40 | methods: { 41 | render(createElement: CreateElement) { 42 | return createElement( 43 | this.tagName, 44 | { 45 | class: this.getElementCssClass('wrapper'), 46 | }, 47 | this.renderChilds(createElement), 48 | ); 49 | }, 50 | renderChilds(createElement: CreateElement) { 51 | if (this.noBody) { 52 | return this.$slots.default; 53 | } 54 | 55 | const childs = []; 56 | 57 | if (!!this.$slots.header || this.header !== undefined) { 58 | childs.push(createElement( 59 | 'div', 60 | { 61 | ref: 'header', 62 | class: this.getElementCssClass('header'), 63 | }, 64 | this.$slots.header || this.header, 65 | )); 66 | } 67 | 68 | childs.push(createElement( 69 | 'div', 70 | { 71 | ref: 'body', 72 | class: this.getElementCssClass('body'), 73 | }, 74 | this.$slots.default, 75 | )); 76 | 77 | if (!!this.$slots.footer || this.footer !== undefined) { 78 | childs.push(createElement( 79 | 'div', 80 | { 81 | ref: 'footer', 82 | class: this.getElementCssClass('footer'), 83 | }, 84 | this.$slots.footer || this.footer, 85 | )); 86 | } 87 | 88 | return childs; 89 | }, 90 | }, 91 | }); 92 | 93 | export default TCard; 94 | -------------------------------------------------------------------------------- /src/components/TCheckboxGroup.ts: -------------------------------------------------------------------------------- 1 | import { CreateElement, VNode } from 'vue'; 2 | import kebabCase from 'lodash.kebabcase'; 3 | import InputWithOptions from '../base/InputWithOptions'; 4 | import TCheckbox from '../inputs/TCheckbox'; 5 | import NormalizedOption from '../types/NormalizedOption'; 6 | import NormalizedOptions from '../types/NormalizedOptions'; 7 | 8 | const TCheckboxGroup = InputWithOptions.extend({ 9 | name: 'TCheckboxGroup', 10 | 11 | props: { 12 | groupWrapperTag: { 13 | type: String, 14 | default: 'div', 15 | }, 16 | wrapperTag: { 17 | type: String, 18 | default: 'label', 19 | }, 20 | inputWrapperTag: { 21 | type: String, 22 | default: 'span', 23 | }, 24 | labelTag: { 25 | type: String, 26 | default: 'span', 27 | }, 28 | value: { 29 | type: Array, 30 | default() { 31 | return []; 32 | }, 33 | }, 34 | fixedClasses: { 35 | type: Object, 36 | default() { 37 | return {}; 38 | }, 39 | }, 40 | classes: { 41 | type: Object, 42 | default() { 43 | return { 44 | groupWrapper: 'flex flex-col', 45 | label: '', 46 | input: 'text-blue-500 transition duration-100 ease-in-out border-gray-300 rounded shadow-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none focus:ring-opacity-50 focus:ring-offset-0 disabled:opacity-50 disabled:cursor-not-allowed', 47 | inputWrapper: 'inline-flex', 48 | wrapper: 'inline-flex items-center space-x-2', 49 | }; 50 | }, 51 | }, 52 | }, 53 | 54 | data() { 55 | return { 56 | localValue: this.value as (string | number | Record)[], 57 | }; 58 | }, 59 | 60 | watch: { 61 | localValue(localValue: (string | number | Record)[]) { 62 | this.$emit('input', localValue); 63 | this.$emit('change', localValue); 64 | }, 65 | value(value) { 66 | this.localValue = value; 67 | }, 68 | }, 69 | 70 | render(createElement) { 71 | const createRadioGroupFunc: (createElement: CreateElement) => VNode = this.createRadioGroup; 72 | return createRadioGroupFunc(createElement); 73 | }, 74 | 75 | methods: { 76 | createRadioGroup(createElement: CreateElement) { 77 | return createElement( 78 | this.groupWrapperTag, 79 | { 80 | ref: 'wrapper', 81 | class: this.getElementCssClass('groupWrapper'), 82 | }, 83 | this.createRadioOptions(createElement), 84 | ); 85 | }, 86 | createRadioOptions(createElement: CreateElement): VNode[] { 87 | const options: NormalizedOptions = this.normalizedOptions; 88 | 89 | return options 90 | .map( 91 | (option: NormalizedOption, index) => this.createRadioOption(createElement, option, index), 92 | ); 93 | }, 94 | createRadioOption( 95 | createElement: CreateElement, 96 | option: NormalizedOption, 97 | index: number, 98 | ): VNode { 99 | return createElement( 100 | TCheckbox, 101 | { 102 | props: { 103 | id: this.buildId(option, index), 104 | name: this.name, 105 | tabindex: this.tabindex, 106 | disabled: this.disabled, 107 | autofocus: this.autofocus, 108 | required: this.required, 109 | model: this.localValue, 110 | label: option.text, 111 | wrapped: true, 112 | value: option.value, 113 | checked: this.value === option.value, 114 | variant: this.variant, 115 | classes: this.classes, 116 | fixedClasses: this.fixedClasses, 117 | variants: this.variants, 118 | wrapperTag: this.wrapperTag, 119 | inputWrapperTag: this.inputWrapperTag, 120 | labelTag: this.labelTag, 121 | }, 122 | scopedSlots: { 123 | default: this.$scopedSlots.default, 124 | }, 125 | on: { 126 | blur: this.blurHandler, 127 | focus: this.focusHandler, 128 | input: this.inputHandler, 129 | }, 130 | }, 131 | ); 132 | }, 133 | 134 | buildId(option: NormalizedOption, index: number) { 135 | const parts = []; 136 | 137 | if (this.id) { 138 | parts.push(this.id); 139 | } else if (this.name) { 140 | parts.push(this.name); 141 | } 142 | 143 | if (['string', 'number'].includes(typeof option.value)) { 144 | parts.push(kebabCase(String(option.value))); 145 | } else { 146 | parts.push(index); 147 | } 148 | 149 | return parts.join('-'); 150 | }, 151 | 152 | inputHandler(value: (string | number| Record)[]) { 153 | (this.localValue as (string | number | Record)[]) = value; 154 | }, 155 | 156 | blurHandler(e: FocusEvent) { 157 | this.$emit('blur', e); 158 | }, 159 | 160 | focusHandler(e: FocusEvent) { 161 | this.$emit('focus', e); 162 | }, 163 | }, 164 | }); 165 | 166 | export default TCheckboxGroup; 167 | -------------------------------------------------------------------------------- /src/components/TDatepicker/TDatepickerNavigatorYearMonthSelector.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | import TDatepickerNavigatorYearMonthSelectorYear from './TDatepickerNavigatorYearMonthSelectorYear'; 3 | import TDatepickerNavigatorYearMonthSelectorMonth from './TDatepickerNavigatorYearMonthSelectorMonth'; 4 | 5 | const TDatepickerNavigatorYearMonthSelector = Vue.extend({ 6 | name: 'TDatepickerNavigatorYearMonthSelector', 7 | 8 | props: { 9 | getElementCssClass: { 10 | type: Function, 11 | required: true, 12 | }, 13 | value: { 14 | type: Date, 15 | default: null, 16 | }, 17 | }, 18 | 19 | data() { 20 | return { 21 | localValue: new Date(this.value.valueOf()), 22 | }; 23 | }, 24 | 25 | watch: { 26 | value(value: Date) { 27 | this.localValue = new Date(value.valueOf()); 28 | }, 29 | }, 30 | 31 | methods: { 32 | inputHandler(newDate: Date): void { 33 | this.$emit('input', newDate); 34 | }, 35 | }, 36 | 37 | render(createElement: CreateElement): VNode { 38 | return createElement( 39 | 'div', 40 | { 41 | class: 'flex', 42 | }, 43 | [ 44 | createElement( 45 | TDatepickerNavigatorYearMonthSelectorMonth, 46 | { 47 | props: { 48 | getElementCssClass: this.getElementCssClass, 49 | value: this.localValue, 50 | }, 51 | on: { 52 | input: this.inputHandler, 53 | }, 54 | }, 55 | ), 56 | createElement( 57 | TDatepickerNavigatorYearMonthSelectorYear, 58 | { 59 | props: { 60 | getElementCssClass: this.getElementCssClass, 61 | value: this.localValue, 62 | }, 63 | on: { 64 | input: this.inputHandler, 65 | }, 66 | }, 67 | ), 68 | ], 69 | ); 70 | }, 71 | 72 | }); 73 | 74 | export default TDatepickerNavigatorYearMonthSelector; 75 | -------------------------------------------------------------------------------- /src/components/TDatepicker/TDatepickerNavigatorYearMonthSelectorMonth.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | 3 | const TDatepickerNavigatorYearMonthSelectorMonth = Vue.extend({ 4 | name: 'TDatepickerNavigatorYearMonthSelectorMonth', 5 | 6 | props: { 7 | getElementCssClass: { 8 | type: Function, 9 | required: true, 10 | }, 11 | value: { 12 | type: Date, 13 | default: null, 14 | }, 15 | formatNative: { 16 | type: Function, 17 | required: true, 18 | }, 19 | }, 20 | 21 | data() { 22 | return { 23 | localValue: new Date(this.value.valueOf()), 24 | }; 25 | }, 26 | 27 | computed: { 28 | months(): Date[] { 29 | const d = new Date(); 30 | return Array 31 | .from({ length: 12 }, (_x, i) => i) 32 | .map((month: number) => new Date(d.setMonth(month))); 33 | }, 34 | }, 35 | 36 | watch: { 37 | value(value: Date) { 38 | this.localValue = new Date(value.valueOf()); 39 | }, 40 | }, 41 | 42 | render(createElement: CreateElement): VNode { 43 | return createElement( 44 | 'select', 45 | { 46 | attrs: { 47 | class: 'pl-3 text-center text-gray-600 hover:bg-gray-200 focus:text-gray-700 focus:text-gray-700 border rounded-sm appearance-none', 48 | }, 49 | on: { 50 | input: (e: InputEvent) => { 51 | const target = (e.target as HTMLSelectElement); 52 | const newDate = new Date(this.localValue.valueOf()); 53 | newDate.setMonth(Number(target.value) - 1); 54 | this.$emit('input', newDate); 55 | }, 56 | }, 57 | }, 58 | this.months.map((month: Date) => createElement( 59 | 'option', 60 | { 61 | attrs: { 62 | selected: month.getMonth() === this.localValue.getMonth() ? 'selected' : undefined, 63 | value: month.getMonth(), 64 | }, 65 | }, 66 | this.formatNative(month, 'F'), 67 | )), 68 | ); 69 | }, 70 | }); 71 | 72 | export default TDatepickerNavigatorYearMonthSelectorMonth; 73 | -------------------------------------------------------------------------------- /src/components/TDatepicker/TDatepickerNavigatorYearMonthSelectorYear.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | 3 | const TDatepickerNavigatorYearMonthSelectorYear = Vue.extend({ 4 | name: 'TDatepickerNavigatorYearMonthSelectorYear', 5 | 6 | props: { 7 | getElementCssClass: { 8 | type: Function, 9 | required: true, 10 | }, 11 | value: { 12 | type: Date, 13 | default: null, 14 | }, 15 | }, 16 | 17 | data() { 18 | return { 19 | localValue: new Date(this.value.valueOf()), 20 | }; 21 | }, 22 | 23 | watch: { 24 | value(value: Date) { 25 | this.localValue = new Date(value.valueOf()); 26 | }, 27 | }, 28 | 29 | methods: { 30 | inputHandler(e: Event) { 31 | const target = (e.target as HTMLInputElement); 32 | 33 | 34 | let numericValue = parseInt(target.value, 10); 35 | 36 | // eslint-disable-next-line no-restricted-globals 37 | if (isNaN(numericValue)) { 38 | numericValue = this.localValue.getFullYear(); 39 | } 40 | 41 | if (target.value !== numericValue.toString()) { 42 | target.value = numericValue.toString(); 43 | } 44 | 45 | const newDate = new Date(this.localValue.valueOf()); 46 | newDate.setFullYear(numericValue); 47 | this.$emit('input', newDate); 48 | }, 49 | }, 50 | 51 | render(createElement: CreateElement): VNode { 52 | return createElement( 53 | 'input', 54 | { 55 | attrs: { 56 | inputmode: 'numeric', 57 | type: 'number', 58 | step: 1, 59 | maxlength: '4', 60 | size: '4', 61 | class: 'p-0 pl-2 text-gray-600 w-16 focus:text-gray-200 focus:text-gray-700 rounded-sm border', 62 | value: this.localValue.getFullYear(), 63 | }, 64 | on: { 65 | blur: (e: FocusEvent) => { 66 | this.inputHandler(e); 67 | }, 68 | input: (e: InputEvent) => { 69 | // When the data is not undefined means it was update trough 70 | // the keyboard, in those case we only change in blur 71 | if (typeof e.data !== 'undefined') { 72 | return; 73 | } 74 | 75 | this.inputHandler(e); 76 | }, 77 | }, 78 | }, 79 | 'zzzz', 80 | ); 81 | }, 82 | 83 | }); 84 | 85 | export default TDatepickerNavigatorYearMonthSelectorYear; 86 | -------------------------------------------------------------------------------- /src/components/TDatepicker/TDatepickerViewsViewCalendar.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | 3 | import TDatepickerViewsViewCalendarDays from './TDatepickerViewsViewCalendarDays'; 4 | import TDatepickerViewsViewCalendarHeaders from './TDatepickerViewsViewCalendarHeaders'; 5 | 6 | const TDatepickerViewsViewCalendar = Vue.extend({ 7 | name: 'TDatepickerViewsViewCalendar', 8 | 9 | props: { 10 | value: { 11 | type: [Date, Array], 12 | default: null, 13 | }, 14 | activeDate: { 15 | type: Date, 16 | required: true, 17 | }, 18 | activeMonth: { 19 | type: Date, 20 | required: true, 21 | }, 22 | weekStart: { 23 | type: Number, 24 | required: true, 25 | }, 26 | getElementCssClass: { 27 | type: Function, 28 | required: true, 29 | }, 30 | parse: { 31 | type: Function, 32 | required: true, 33 | }, 34 | format: { 35 | type: Function, 36 | required: true, 37 | }, 38 | formatNative: { 39 | type: Function, 40 | required: true, 41 | }, 42 | dateFormat: { 43 | type: String, 44 | required: true, 45 | }, 46 | userFormat: { 47 | type: String, 48 | required: true, 49 | }, 50 | monthsPerView: { 51 | type: Number, 52 | required: true, 53 | }, 54 | showActiveDate: { 55 | type: Boolean, 56 | required: true, 57 | }, 58 | disabledDates: { 59 | type: [Date, Array, Function, String], 60 | default: undefined, 61 | }, 62 | highlightDates: { 63 | type: [Date, Array, Function, String], 64 | default: undefined, 65 | }, 66 | maxDate: { 67 | type: [Date, String], 68 | default: undefined, 69 | }, 70 | minDate: { 71 | type: [Date, String], 72 | default: undefined, 73 | }, 74 | range: { 75 | type: Boolean, 76 | required: true, 77 | }, 78 | showDaysForOtherMonth: { 79 | type: Boolean, 80 | required: true, 81 | }, 82 | timepicker: { 83 | type: Boolean, 84 | required: true, 85 | }, 86 | dateWithoutTime: { 87 | type: Date, 88 | default: null, 89 | }, 90 | }, 91 | 92 | data() { 93 | return { 94 | localActiveDate: new Date(this.activeDate.valueOf()), 95 | localActiveMonth: new Date(this.activeMonth.valueOf()), 96 | }; 97 | }, 98 | 99 | watch: { 100 | activeDate(activeDate: Date) { 101 | this.localActiveDate = new Date(activeDate.valueOf()); 102 | }, 103 | activeMonth(activeMonth: Date) { 104 | this.localActiveMonth = new Date(activeMonth.valueOf()); 105 | }, 106 | }, 107 | 108 | render(createElement: CreateElement): VNode { 109 | return createElement( 110 | 'div', 111 | { 112 | class: this.getElementCssClass('calendarWrapper'), 113 | }, 114 | [ 115 | createElement( 116 | TDatepickerViewsViewCalendarHeaders, 117 | { 118 | props: { 119 | weekStart: this.weekStart, 120 | getElementCssClass: this.getElementCssClass, 121 | formatNative: this.formatNative, 122 | }, 123 | }, 124 | ), 125 | createElement( 126 | TDatepickerViewsViewCalendarDays, 127 | { 128 | ref: 'days', 129 | props: { 130 | value: this.value, 131 | activeDate: this.localActiveDate, 132 | activeMonth: this.localActiveMonth, 133 | weekStart: this.weekStart, 134 | getElementCssClass: this.getElementCssClass, 135 | parse: this.parse, 136 | format: this.format, 137 | formatNative: this.formatNative, 138 | userFormat: this.userFormat, 139 | dateFormat: this.dateFormat, 140 | showDaysForOtherMonth: this.monthsPerView > 1 ? false : this.showDaysForOtherMonth, 141 | showActiveDate: this.showActiveDate, 142 | disabledDates: this.disabledDates, 143 | highlightDates: this.highlightDates, 144 | minDate: this.minDate, 145 | maxDate: this.maxDate, 146 | range: this.range, 147 | timepicker: this.timepicker, 148 | dateWithoutTime: this.dateWithoutTime, 149 | }, 150 | scopedSlots: this.$scopedSlots, 151 | on: { 152 | input: (date: Date) => this.$emit('input', date), 153 | 'input-date': (date: Date) => this.$emit('input-date', date), 154 | }, 155 | }, 156 | ), 157 | ], 158 | ); 159 | }, 160 | }); 161 | 162 | export default TDatepickerViewsViewCalendar; 163 | -------------------------------------------------------------------------------- /src/components/TDatepicker/TDatepickerViewsViewCalendarHeaders.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | 3 | const TDatepickerViewsViewCalendarHeaders = Vue.extend({ 4 | name: 'TDatepickerViewsViewCalendarHeaders', 5 | 6 | props: { 7 | weekStart: { 8 | type: Number, 9 | required: true, 10 | }, 11 | getElementCssClass: { 12 | type: Function, 13 | required: true, 14 | }, 15 | formatNative: { 16 | type: Function, 17 | required: true, 18 | }, 19 | }, 20 | 21 | computed: { 22 | weekDays(): string[] { 23 | return Array.from({ length: 7 }, (_x, i) => { 24 | const weekDay = this.weekStart + i; 25 | if (weekDay >= 7) { 26 | return weekDay - 7; 27 | } 28 | 29 | return weekDay; 30 | }).map(this.getWeekDayName); 31 | }, 32 | 33 | }, 34 | 35 | methods: { 36 | getWeekDayName(weekDay: number): string { 37 | const date = new Date(); 38 | date.setDate((date.getDate() + (7 + weekDay - date.getDay())) % 7); 39 | return this.formatNative(date, 'D'); 40 | }, 41 | }, 42 | 43 | render(createElement: CreateElement): VNode { 44 | return createElement( 45 | 'div', 46 | { 47 | class: this.getElementCssClass('calendarHeaderWrapper'), 48 | }, 49 | this.weekDays.map((weekDayName: string) => createElement( 50 | 'span', 51 | { 52 | class: this.getElementCssClass('calendarHeaderWeekDay'), 53 | }, 54 | weekDayName, 55 | )), 56 | ); 57 | }, 58 | 59 | }); 60 | 61 | export default TDatepickerViewsViewCalendarHeaders; 62 | -------------------------------------------------------------------------------- /src/components/TDatepicker/TDatepickerViewsViewMonths.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | 3 | import TDatepickerViewsViewMonthsMonth from './TDatepickerViewsViewMonthsMonth'; 4 | 5 | const TDatepickerViewsViewMonths = Vue.extend({ 6 | name: 'TDatepickerViewsViewMonths', 7 | 8 | props: { 9 | value: { 10 | type: [Date, Array], 11 | default: null, 12 | }, 13 | activeDate: { 14 | type: Date, 15 | required: true, 16 | }, 17 | getElementCssClass: { 18 | type: Function, 19 | required: true, 20 | }, 21 | showActiveDate: { 22 | type: Boolean, 23 | required: true, 24 | }, 25 | formatNative: { 26 | type: Function, 27 | required: true, 28 | }, 29 | }, 30 | 31 | data() { 32 | return { 33 | localActiveDate: new Date(this.activeDate.valueOf()), 34 | }; 35 | }, 36 | 37 | computed: { 38 | months(): Date[] { 39 | return Array 40 | .from({ length: 12 }, (_x, i) => i) 41 | .map((monthNumber) => this.getMonth(monthNumber)); 42 | }, 43 | }, 44 | 45 | watch: { 46 | activeDate(activeDate: Date) { 47 | this.localActiveDate = new Date(activeDate.valueOf()); 48 | }, 49 | }, 50 | 51 | methods: { 52 | getMonth(monthNumber: number) { 53 | let newDate = new Date(this.localActiveDate.valueOf()); 54 | newDate.setMonth(monthNumber); 55 | 56 | // Means the current day has less days so the extra month is 57 | // in the following month 58 | if (newDate.getDate() !== this.localActiveDate.getDate()) { 59 | // Assign the last day of previous month 60 | newDate = new Date(newDate.getFullYear(), newDate.getMonth(), 0); 61 | } 62 | 63 | return newDate; 64 | }, 65 | }, 66 | 67 | render(createElement: CreateElement): VNode { 68 | return createElement( 69 | 'div', 70 | { 71 | class: this.getElementCssClass('monthWrapper'), 72 | }, 73 | this.months.map((month: Date) => createElement( 74 | TDatepickerViewsViewMonthsMonth, 75 | { 76 | props: { 77 | month, 78 | value: this.value, 79 | activeDate: this.localActiveDate, 80 | getElementCssClass: this.getElementCssClass, 81 | showActiveDate: this.showActiveDate, 82 | formatNative: this.formatNative, 83 | }, 84 | scopedSlots: this.$scopedSlots, 85 | on: { 86 | click: () => this.$emit('input', month), 87 | }, 88 | }, 89 | )), 90 | ); 91 | }, 92 | }); 93 | 94 | export default TDatepickerViewsViewMonths; 95 | -------------------------------------------------------------------------------- /src/components/TDatepicker/TDatepickerViewsViewMonthsMonth.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | import CssClass from '../../types/CssClass'; 3 | import { isSameMonth } from '../../utils/dates'; 4 | 5 | const TDatepickerViewsViewMonthsMonth = Vue.extend({ 6 | name: 'TDatepickerViewsViewMonthsMonth', 7 | 8 | props: { 9 | month: { 10 | type: Date, 11 | required: true, 12 | }, 13 | value: { 14 | type: [Date, Array], 15 | default: null, 16 | }, 17 | activeDate: { 18 | type: Date, 19 | required: true, 20 | }, 21 | getElementCssClass: { 22 | type: Function, 23 | required: true, 24 | }, 25 | formatNative: { 26 | type: Function, 27 | required: true, 28 | }, 29 | showActiveDate: { 30 | type: Boolean, 31 | required: true, 32 | }, 33 | }, 34 | 35 | computed: { 36 | isSelected(): boolean { 37 | const d1 = this.getMonth(); 38 | const d2 = this.value as Date | Date[]; 39 | 40 | if (d2 instanceof Date) { 41 | return isSameMonth(d1, d2); 42 | } 43 | 44 | if (Array.isArray(d2)) { 45 | return d2.some((d) => isSameMonth(d, d1)); 46 | } 47 | 48 | return false; 49 | }, 50 | isActive(): boolean { 51 | const d1 = this.getMonth(); 52 | const d2 = this.activeDate as unknown as Date; 53 | return isSameMonth(d1, d2); 54 | }, 55 | monthFormatted(): string { 56 | return this.formatNative(this.getMonth(), 'M'); 57 | }, 58 | }, 59 | 60 | methods: { 61 | getClass(): CssClass { 62 | if (this.isSelected) { 63 | return this.getElementCssClass('selectedMonth'); 64 | } 65 | 66 | if (this.isActive && this.showActiveDate) { 67 | return this.getElementCssClass('activeMonth'); 68 | } 69 | 70 | return this.getElementCssClass('month'); 71 | }, 72 | getMonth(): Date { 73 | return this.month as unknown as Date; 74 | }, 75 | }, 76 | 77 | render(createElement: CreateElement): VNode { 78 | const monthSlot = this.$scopedSlots.month 79 | ? this.$scopedSlots.month({ 80 | monthFormatted: this.monthFormatted, 81 | isSelected: this.isSelected, 82 | isActive: this.isActive, 83 | month: this.getMonth(), 84 | activeDate: this.activeDate, 85 | value: this.value, 86 | }) : this.monthFormatted; 87 | 88 | return createElement( 89 | 'button', 90 | { 91 | class: this.getClass(), 92 | attrs: { 93 | 'aria-label': this.formatNative(this.getMonth(), 'F, Y'), 94 | 'data-date': this.formatNative(this.getMonth(), 'Y-m'), 95 | type: 'button', 96 | tabindex: -1, 97 | }, 98 | on: { 99 | click: (e: MouseEvent) => this.$emit('click', e), 100 | }, 101 | }, 102 | monthSlot, 103 | ); 104 | }, 105 | }); 106 | 107 | export default TDatepickerViewsViewMonthsMonth; 108 | -------------------------------------------------------------------------------- /src/components/TDatepicker/TDatepickerViewsViewYears.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | 3 | import TDatepickerViewsViewYearsYear from './TDatepickerViewsViewYearsYear'; 4 | import { getYearsRange } from './TDatepickerNavigator'; 5 | 6 | const TDatepickerViewsViewYears = Vue.extend({ 7 | name: 'TDatepickerViewsViewYears', 8 | 9 | props: { 10 | value: { 11 | type: [Date, Array], 12 | default: null, 13 | }, 14 | activeDate: { 15 | type: Date, 16 | required: true, 17 | }, 18 | getElementCssClass: { 19 | type: Function, 20 | required: true, 21 | }, 22 | yearsPerView: { 23 | type: Number, 24 | required: true, 25 | }, 26 | showActiveDate: { 27 | type: Boolean, 28 | required: true, 29 | }, 30 | formatNative: { 31 | type: Function, 32 | required: true, 33 | }, 34 | }, 35 | 36 | data() { 37 | return { 38 | localActiveDate: new Date(this.activeDate.valueOf()), 39 | }; 40 | }, 41 | 42 | computed: { 43 | years(): Date[] { 44 | const [initialYear] = getYearsRange(this.localActiveDate, this.yearsPerView); 45 | return Array 46 | .from({ length: this.yearsPerView }, (_x, i) => i) 47 | .map((year) => this.getYear(initialYear + year)); 48 | }, 49 | }, 50 | 51 | watch: { 52 | activeDate(activeDate: Date) { 53 | this.localActiveDate = new Date(activeDate.valueOf()); 54 | }, 55 | }, 56 | 57 | 58 | methods: { 59 | getYear(year: number) { 60 | let newDate = new Date(this.localActiveDate.valueOf()); 61 | newDate.setFullYear(year); 62 | 63 | // Means the current day has less days so the extra month is 64 | // in the following month 65 | if (newDate.getDate() !== this.localActiveDate.getDate()) { 66 | // Assign the last day of previous month 67 | newDate = new Date(newDate.getFullYear(), newDate.getMonth(), 0); 68 | } 69 | 70 | return newDate; 71 | }, 72 | }, 73 | 74 | render(createElement: CreateElement): VNode { 75 | return createElement( 76 | 'div', 77 | { 78 | class: this.getElementCssClass('yearWrapper'), 79 | }, 80 | this.years.map((year: Date) => createElement( 81 | TDatepickerViewsViewYearsYear, 82 | { 83 | props: { 84 | year, 85 | activeDate: this.localActiveDate, 86 | value: this.value, 87 | getElementCssClass: this.getElementCssClass, 88 | showActiveDate: this.showActiveDate, 89 | formatNative: this.formatNative, 90 | }, 91 | scopedSlots: this.$scopedSlots, 92 | on: { 93 | click: () => this.$emit('input', year), 94 | }, 95 | }, 96 | )), 97 | ); 98 | }, 99 | }); 100 | 101 | export default TDatepickerViewsViewYears; 102 | -------------------------------------------------------------------------------- /src/components/TDatepicker/TDatepickerViewsViewYearsYear.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | import CssClass from '../../types/CssClass'; 3 | 4 | const TDatepickerViewsViewYearsYear = Vue.extend({ 5 | name: 'TDatepickerViewsViewYearsYear', 6 | 7 | props: { 8 | year: { 9 | type: Date, 10 | required: true, 11 | }, 12 | activeDate: { 13 | type: Date, 14 | required: true, 15 | }, 16 | value: { 17 | type: [Date, Array], 18 | default: null, 19 | }, 20 | getElementCssClass: { 21 | type: Function, 22 | required: true, 23 | }, 24 | showActiveDate: { 25 | type: Boolean, 26 | required: true, 27 | }, 28 | formatNative: { 29 | type: Function, 30 | required: true, 31 | }, 32 | }, 33 | 34 | data() { 35 | return { 36 | localActiveDate: new Date(this.activeDate.valueOf()), 37 | }; 38 | }, 39 | 40 | computed: { 41 | isSelected(): boolean { 42 | const d1 = this.getYear(); 43 | const d2 = this.value as Date | Date[]; 44 | 45 | if (d2 instanceof Date) { 46 | return d1.getFullYear() === d2.getFullYear(); 47 | } 48 | 49 | if (Array.isArray(d2)) { 50 | return d2.some((d) => d.getFullYear() === d1.getFullYear()); 51 | } 52 | 53 | return false; 54 | }, 55 | isActive(): boolean { 56 | const d1 = this.getYear(); 57 | const d2 = this.activeDate as unknown as Date; 58 | return d2 && d1.getFullYear() === d2.getFullYear(); 59 | }, 60 | yearFormatted(): string { 61 | return this.formatNative(this.getYear(), 'Y'); 62 | }, 63 | }, 64 | 65 | watch: { 66 | activeDate(activeDate: Date) { 67 | this.localActiveDate = new Date(activeDate.valueOf()); 68 | }, 69 | }, 70 | 71 | methods: { 72 | getClass(): CssClass { 73 | if (this.isSelected) { 74 | return this.getElementCssClass('selectedYear'); 75 | } 76 | 77 | if (this.isActive && this.showActiveDate) { 78 | return this.getElementCssClass('activeYear'); 79 | } 80 | 81 | return this.getElementCssClass('year'); 82 | }, 83 | getYear(): Date { 84 | return this.year as unknown as Date; 85 | }, 86 | }, 87 | 88 | render(createElement: CreateElement): VNode { 89 | const yearSlot = this.$scopedSlots.year 90 | ? this.$scopedSlots.year({ 91 | yearFormatted: this.yearFormatted, 92 | isSelected: this.isSelected, 93 | isActive: this.isActive, 94 | year: this.getYear(), 95 | activeDate: this.activeDate, 96 | value: this.value, 97 | }) : this.yearFormatted; 98 | 99 | return createElement( 100 | 'button', 101 | { 102 | class: this.getClass(), 103 | attrs: { 104 | 'aria-label': this.yearFormatted, 105 | 'data-date': this.yearFormatted, 106 | type: 'button', 107 | tabindex: -1, 108 | }, 109 | on: { 110 | click: (e: MouseEvent) => this.$emit('click', e), 111 | }, 112 | }, 113 | yearSlot, 114 | ); 115 | }, 116 | }); 117 | 118 | export default TDatepickerViewsViewYearsYear; 119 | -------------------------------------------------------------------------------- /src/components/TDialog/TDialogOverlay.ts: -------------------------------------------------------------------------------- 1 | 2 | import Vue, { CreateElement, VNode } from 'vue'; 3 | import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock'; 4 | import TDialogOverlayWrapper from './TDialogOverlayWrapper'; 5 | import { DialogInput } from './TDialogOverlayWrapperTransitionDialog'; 6 | 7 | const TDialogOverlay = Vue.extend({ 8 | name: 'TDialogOverlay', 9 | 10 | props: { 11 | getElementCssClass: { 12 | type: Function, 13 | required: true, 14 | }, 15 | overlayShow: { 16 | type: Boolean, 17 | required: true, 18 | }, 19 | dialogShow: { 20 | type: Boolean, 21 | required: true, 22 | }, 23 | titleTag: { 24 | type: String, 25 | required: true, 26 | }, 27 | title: { 28 | type: String, 29 | default: undefined, 30 | }, 31 | textTag: { 32 | type: String, 33 | required: true, 34 | }, 35 | text: { 36 | type: String, 37 | default: undefined, 38 | }, 39 | icon: { 40 | type: String, 41 | default: undefined, 42 | }, 43 | cancelButtonText: { 44 | type: String, 45 | required: true, 46 | }, 47 | cancelButtonAriaLabel: { 48 | type: String, 49 | default: undefined, 50 | }, 51 | okButtonText: { 52 | type: String, 53 | required: true, 54 | }, 55 | okButtonAriaLabel: { 56 | type: String, 57 | default: undefined, 58 | }, 59 | showCloseButton: { 60 | type: Boolean, 61 | required: true, 62 | }, 63 | preConfirm: { 64 | type: Function, 65 | default: undefined, 66 | }, 67 | inputAttributes: { 68 | type: Object, 69 | default: undefined, 70 | }, 71 | inputType: { 72 | type: String, 73 | required: true, 74 | }, 75 | inputValidator: { 76 | type: Function, 77 | default: undefined, 78 | }, 79 | inputValue: { 80 | type: [String, Array], 81 | default: undefined, 82 | }, 83 | inputOptions: { 84 | type: [Array, Object], 85 | default: undefined, 86 | }, 87 | inputPlaceholder: { 88 | type: String, 89 | default: undefined, 90 | }, 91 | type: { 92 | type: String, 93 | default: null, 94 | }, 95 | }, 96 | 97 | methods: { 98 | clickHandler(e: MouseEvent) { 99 | if (e.target !== this.$el) { 100 | return; 101 | } 102 | 103 | this.$emit('outside-click', e); 104 | }, 105 | keyupHandler(e: KeyboardEvent) { 106 | this.$emit('keyup', e); 107 | }, 108 | focus() { 109 | const overlay = this.$el as HTMLDivElement | undefined; 110 | if (overlay && overlay.focus) { 111 | overlay.focus(); 112 | } 113 | }, 114 | enableBodyScroll() { 115 | const mdl = this.$el as HTMLDivElement; 116 | enableBodyScroll(mdl); 117 | }, 118 | disableBodyScroll() { 119 | const mdl = this.$el as HTMLDivElement; 120 | disableBodyScroll(mdl, { 121 | reserveScrollBarGap: true, 122 | }); 123 | }, 124 | }, 125 | 126 | render(createElement: CreateElement): VNode { 127 | if (!this.overlayShow) { 128 | return createElement(); 129 | } 130 | 131 | return createElement( 132 | 'div', 133 | { 134 | attrs: { 135 | tabindex: 0, 136 | }, 137 | class: this.getElementCssClass('overlay'), 138 | on: { 139 | keyup: this.keyupHandler, 140 | click: this.clickHandler, 141 | }, 142 | }, 143 | [ 144 | createElement( 145 | TDialogOverlayWrapper, 146 | { 147 | props: { 148 | type: this.type, 149 | getElementCssClass: this.getElementCssClass, 150 | dialogShow: this.dialogShow, 151 | titleTag: this.titleTag, 152 | title: this.title, 153 | icon: this.icon, 154 | textTag: this.textTag, 155 | text: this.text, 156 | cancelButtonText: this.cancelButtonText, 157 | cancelButtonAriaLabel: this.cancelButtonAriaLabel, 158 | okButtonText: this.okButtonText, 159 | okButtonAriaLabel: this.okButtonAriaLabel, 160 | showCloseButton: this.showCloseButton, 161 | preConfirm: this.preConfirm, 162 | inputAttributes: this.inputAttributes, 163 | inputType: this.inputType, 164 | inputValidator: this.inputValidator, 165 | inputValue: this.inputValue, 166 | inputOptions: this.inputOptions, 167 | inputPlaceholder: this.inputPlaceholder, 168 | }, 169 | scopedSlots: this.$scopedSlots, 170 | on: { 171 | dismiss: (e: MouseEvent) => this.$emit('dismiss', e), 172 | cancel: (e: MouseEvent) => this.$emit('cancel', e), 173 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 174 | submit: (e: MouseEvent, input: DialogInput, response?: any) => this.$emit('submit', e, input, response), 175 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 176 | 'submit-error': (e: MouseEvent, input: DialogInput, error?: any) => this.$emit('submit-error', e, input, error), 177 | }, 178 | }, 179 | this.$slots.default, 180 | ), 181 | ], 182 | ); 183 | }, 184 | }); 185 | 186 | export default TDialogOverlay; 187 | -------------------------------------------------------------------------------- /src/components/TDialog/TDialogOverlayWrapper.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | import TDialogOverlayWrapperTransition from './TDialogOverlayWrapperTransition'; 3 | import { DialogInput } from './TDialogOverlayWrapperTransitionDialog'; 4 | 5 | const TDialogOverlayWrapper = Vue.extend({ 6 | name: 'TDialogOverlayWrapper', 7 | 8 | props: { 9 | getElementCssClass: { 10 | type: Function, 11 | required: true, 12 | }, 13 | dialogShow: { 14 | type: Boolean, 15 | required: true, 16 | }, 17 | titleTag: { 18 | type: String, 19 | required: true, 20 | }, 21 | title: { 22 | type: String, 23 | default: undefined, 24 | }, 25 | icon: { 26 | type: String, 27 | default: undefined, 28 | }, 29 | textTag: { 30 | type: String, 31 | required: true, 32 | }, 33 | text: { 34 | type: String, 35 | default: undefined, 36 | }, 37 | cancelButtonText: { 38 | type: String, 39 | required: true, 40 | }, 41 | cancelButtonAriaLabel: { 42 | type: String, 43 | default: undefined, 44 | }, 45 | okButtonText: { 46 | type: String, 47 | required: true, 48 | }, 49 | okButtonAriaLabel: { 50 | type: String, 51 | default: undefined, 52 | }, 53 | showCloseButton: { 54 | type: Boolean, 55 | required: true, 56 | }, 57 | preConfirm: { 58 | type: Function, 59 | default: undefined, 60 | }, 61 | inputAttributes: { 62 | type: Object, 63 | default: undefined, 64 | }, 65 | inputType: { 66 | type: String, 67 | required: true, 68 | }, 69 | inputValidator: { 70 | type: Function, 71 | default: undefined, 72 | }, 73 | inputValue: { 74 | type: [String, Array], 75 | default: undefined, 76 | }, 77 | inputOptions: { 78 | type: [Array, Object], 79 | default: undefined, 80 | }, 81 | inputPlaceholder: { 82 | type: String, 83 | default: undefined, 84 | }, 85 | type: { 86 | type: String, 87 | required: true, 88 | }, 89 | }, 90 | 91 | render(createElement: CreateElement): VNode { 92 | return createElement( 93 | 'div', 94 | { 95 | ref: 'wrapper', 96 | class: this.getElementCssClass('wrapper'), 97 | }, 98 | [ 99 | createElement( 100 | TDialogOverlayWrapperTransition, 101 | { 102 | props: { 103 | type: this.type, 104 | dialogShow: this.dialogShow, 105 | getElementCssClass: this.getElementCssClass, 106 | titleTag: this.titleTag, 107 | title: this.title, 108 | icon: this.icon, 109 | textTag: this.textTag, 110 | text: this.text, 111 | cancelButtonText: this.cancelButtonText, 112 | cancelButtonAriaLabel: this.cancelButtonAriaLabel, 113 | okButtonText: this.okButtonText, 114 | okButtonAriaLabel: this.okButtonAriaLabel, 115 | showCloseButton: this.showCloseButton, 116 | preConfirm: this.preConfirm, 117 | inputAttributes: this.inputAttributes, 118 | inputType: this.inputType, 119 | inputValidator: this.inputValidator, 120 | inputValue: this.inputValue, 121 | inputOptions: this.inputOptions, 122 | inputPlaceholder: this.inputPlaceholder, 123 | }, 124 | scopedSlots: this.$scopedSlots, 125 | on: { 126 | dismiss: (e: MouseEvent) => this.$emit('dismiss', e), 127 | cancel: (e: MouseEvent) => this.$emit('cancel', e), 128 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 129 | submit: (e: MouseEvent, input: DialogInput, response?: any) => this.$emit('submit', e, input, response), 130 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 131 | 'submit-error': (e: MouseEvent, input: DialogInput, error?: any) => this.$emit('submit-error', e, input, error), 132 | }, 133 | }, 134 | this.$slots.default, 135 | ), 136 | ], 137 | ); 138 | }, 139 | }); 140 | 141 | export default TDialogOverlayWrapper; 142 | -------------------------------------------------------------------------------- /src/components/TDialog/TDialogOverlayWrapperTransition.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | import TDialogOverlayWrapperTransitionDialog, { DialogInput } from './TDialogOverlayWrapperTransitionDialog'; 3 | 4 | const TDialogOverlayWrapperTransition = Vue.extend({ 5 | name: 'TDialogOverlayWrapperTransition', 6 | 7 | props: { 8 | getElementCssClass: { 9 | type: Function, 10 | required: true, 11 | }, 12 | dialogShow: { 13 | type: Boolean, 14 | required: true, 15 | }, 16 | titleTag: { 17 | type: String, 18 | required: true, 19 | }, 20 | title: { 21 | type: String, 22 | default: undefined, 23 | }, 24 | icon: { 25 | type: String, 26 | default: undefined, 27 | }, 28 | textTag: { 29 | type: String, 30 | required: true, 31 | }, 32 | text: { 33 | type: String, 34 | default: undefined, 35 | }, 36 | cancelButtonText: { 37 | type: String, 38 | required: true, 39 | }, 40 | cancelButtonAriaLabel: { 41 | type: String, 42 | default: undefined, 43 | }, 44 | okButtonText: { 45 | type: String, 46 | required: true, 47 | }, 48 | okButtonAriaLabel: { 49 | type: String, 50 | default: undefined, 51 | }, 52 | showCloseButton: { 53 | type: Boolean, 54 | required: true, 55 | }, 56 | preConfirm: { 57 | type: Function, 58 | default: undefined, 59 | }, 60 | inputAttributes: { 61 | type: Object, 62 | default: undefined, 63 | }, 64 | inputType: { 65 | type: String, 66 | required: true, 67 | }, 68 | inputValidator: { 69 | type: Function, 70 | default: undefined, 71 | }, 72 | inputValue: { 73 | type: [String, Array], 74 | default: undefined, 75 | }, 76 | inputOptions: { 77 | type: [Array, Object], 78 | default: undefined, 79 | }, 80 | inputPlaceholder: { 81 | type: String, 82 | default: undefined, 83 | }, 84 | type: { 85 | type: String, 86 | required: true, 87 | }, 88 | }, 89 | 90 | render(createElement: CreateElement): VNode { 91 | return createElement( 92 | 'transition', 93 | { 94 | props: { 95 | enterClass: this.getElementCssClass('enterClass'), 96 | enterActiveClass: this.getElementCssClass('enterActiveClass'), 97 | enterToClass: this.getElementCssClass('enterToClass'), 98 | leaveClass: this.getElementCssClass('leaveClass'), 99 | leaveActiveClass: this.getElementCssClass('leaveActiveClass'), 100 | leaveToClass: this.getElementCssClass('leaveToClass'), 101 | }, 102 | }, 103 | [ 104 | createElement( 105 | TDialogOverlayWrapperTransitionDialog, 106 | { 107 | props: { 108 | getElementCssClass: this.getElementCssClass, 109 | dialogShow: this.dialogShow, 110 | titleTag: this.titleTag, 111 | title: this.title, 112 | icon: this.icon, 113 | textTag: this.textTag, 114 | text: this.text, 115 | cancelButtonText: this.cancelButtonText, 116 | cancelButtonAriaLabel: this.cancelButtonAriaLabel, 117 | okButtonText: this.okButtonText, 118 | okButtonAriaLabel: this.okButtonAriaLabel, 119 | showCloseButton: this.showCloseButton, 120 | preConfirm: this.preConfirm, 121 | inputAttributes: this.inputAttributes, 122 | inputType: this.inputType, 123 | inputValidator: this.inputValidator, 124 | inputValue: this.inputValue, 125 | inputOptions: this.inputOptions, 126 | inputPlaceholder: this.inputPlaceholder, 127 | type: this.type, 128 | }, 129 | scopedSlots: this.$scopedSlots, 130 | on: { 131 | dismiss: (e: MouseEvent) => this.$emit('dismiss', e), 132 | cancel: (e: MouseEvent) => this.$emit('cancel', e), 133 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 134 | submit: (e: MouseEvent, input: DialogInput, response?: any) => this.$emit('submit', e, input, response), 135 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 136 | 'submit-error': (e: MouseEvent, input: DialogInput, error?: any) => this.$emit('submit-error', e, input, error), 137 | }, 138 | }, 139 | this.$slots.default, 140 | ), 141 | ], 142 | ); 143 | }, 144 | }); 145 | 146 | export default TDialogOverlayWrapperTransition; 147 | -------------------------------------------------------------------------------- /src/components/TDialog/TDialogOverlayWrapperTransitionDialogButtons.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | import { DialogType } from '../../types/Dialog'; 3 | 4 | const TDialogOverlayWrapperTransitionDialogButtons = Vue.extend({ 5 | name: 'TDialogOverlayWrapperTransitionDialogButtons', 6 | 7 | props: { 8 | getElementCssClass: { 9 | type: Function, 10 | required: true, 11 | }, 12 | cancelButtonText: { 13 | type: String, 14 | required: true, 15 | }, 16 | cancelButtonAriaLabel: { 17 | type: String, 18 | default: undefined, 19 | }, 20 | okButtonText: { 21 | type: String, 22 | required: true, 23 | }, 24 | okButtonAriaLabel: { 25 | type: String, 26 | default: undefined, 27 | }, 28 | type: { 29 | type: String, 30 | required: true, 31 | }, 32 | }, 33 | 34 | methods: { 35 | cancel(e?: MouseEvent) { 36 | this.$emit('cancel', e); 37 | }, 38 | ok(e?: MouseEvent) { 39 | this.$emit('submit', e); 40 | }, 41 | }, 42 | 43 | render(createElement: CreateElement): VNode { 44 | const type: DialogType = this.type as DialogType; 45 | 46 | if (this.$scopedSlots.buttons) { 47 | return createElement( 48 | 'div', 49 | { 50 | class: this.getElementCssClass('buttons'), 51 | }, 52 | [ 53 | this.$scopedSlots.buttons({ 54 | cancelButtonAriaLabel: this.cancelButtonAriaLabel, 55 | okButtonAriaLabel: this.okButtonAriaLabel, 56 | cancelButtonText: this.cancelButtonText, 57 | okButtonText: this.okButtonText, 58 | okButtonClass: this.getElementCssClass('okButton'), 59 | cancelButtonClass: this.getElementCssClass('cancelButton'), 60 | dialogType: type, 61 | cancel: this.cancel, 62 | ok: this.ok, 63 | }), 64 | ], 65 | ); 66 | } 67 | 68 | const subElements = []; 69 | 70 | const buttons = { 71 | cancel: createElement( 72 | 'button', 73 | { 74 | attrs: { 75 | type: 'button', 76 | 'aria-label': this.cancelButtonAriaLabel, 77 | }, 78 | class: this.getElementCssClass('cancelButton'), 79 | on: { 80 | click: this.cancel, 81 | }, 82 | }, 83 | this.cancelButtonText, 84 | ), 85 | ok: createElement( 86 | 'button', 87 | { 88 | attrs: { 89 | type: 'button', 90 | 'aria-label': this.okButtonAriaLabel, 91 | }, 92 | class: this.getElementCssClass('okButton'), 93 | on: { 94 | click: this.ok, 95 | }, 96 | }, 97 | this.okButtonText, 98 | ), 99 | }; 100 | 101 | if (type === DialogType.Alert) { 102 | subElements.push(buttons.ok); 103 | } else if (type === DialogType.Confirm || type === DialogType.Prompt) { 104 | subElements.push(buttons.cancel); 105 | subElements.push(buttons.ok); 106 | } 107 | 108 | return createElement( 109 | 'div', 110 | { 111 | class: this.getElementCssClass('buttons'), 112 | }, 113 | subElements, 114 | ); 115 | }, 116 | }); 117 | 118 | export default TDialogOverlayWrapperTransitionDialogButtons; 119 | -------------------------------------------------------------------------------- /src/components/TDialog/TDialogOverlayWrapperTransitionDialogClose.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | 3 | const TDialogOverlayWrapperTransitionDialogClose = Vue.extend({ 4 | name: 'TDialogOverlayWrapperTransitionDialogClose', 5 | 6 | props: { 7 | getElementCssClass: { 8 | type: Function, 9 | required: true, 10 | }, 11 | showCloseButton: { 12 | type: Boolean, 13 | required: true, 14 | }, 15 | }, 16 | 17 | render(createElement: CreateElement): VNode { 18 | if (!this.showCloseButton) { 19 | return createElement(); 20 | } 21 | 22 | if (this.$scopedSlots.closeButton) { 23 | return createElement( 24 | 'button', 25 | { 26 | class: this.getElementCssClass('close'), 27 | attrs: { 28 | type: 'button', 29 | }, 30 | on: { 31 | click: (e: MouseEvent) => this.$emit('dismiss', e), 32 | }, 33 | }, 34 | [ 35 | this.$scopedSlots.closeButton({}), 36 | ], 37 | ); 38 | } 39 | 40 | return createElement( 41 | 'button', 42 | { 43 | class: this.getElementCssClass('close'), 44 | attrs: { 45 | type: 'button', 46 | }, 47 | on: { 48 | click: (e: MouseEvent) => this.$emit('dismiss', e), 49 | }, 50 | }, 51 | [ 52 | createElement( 53 | 'svg', 54 | { 55 | attrs: { 56 | fill: 'currentColor', 57 | xmlns: 'http://www.w3.org/2000/svg', 58 | viewBox: '0 0 20 20', 59 | }, 60 | class: this.getElementCssClass('closeIcon'), 61 | }, 62 | [ 63 | createElement('path', { 64 | attrs: { 65 | 'clip-rule': 'evenodd', 66 | 'fill-rule': 'evenodd', 67 | d: 'M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z', 68 | }, 69 | }), 70 | ], 71 | ), 72 | ], 73 | ); 74 | }, 75 | }); 76 | 77 | export default TDialogOverlayWrapperTransitionDialogClose; 78 | -------------------------------------------------------------------------------- /src/components/TDialog/TDialogOverlayWrapperTransitionDialogContent.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | import { DialogType } from '../../types/Dialog'; 3 | import TDialogOverlayWrapperTransitionDialogContentInput from './TDialogOverlayWrapperTransitionDialogContentInput'; 4 | 5 | const TDialogOverlayWrapperTransitionDialogContent = Vue.extend({ 6 | name: 'TDialogOverlayWrapperTransitionDialogContent', 7 | 8 | props: { 9 | getElementCssClass: { 10 | type: Function, 11 | required: true, 12 | }, 13 | titleTag: { 14 | type: String, 15 | required: true, 16 | }, 17 | title: { 18 | type: String, 19 | default: undefined, 20 | }, 21 | textTag: { 22 | type: String, 23 | required: true, 24 | }, 25 | text: { 26 | type: String, 27 | default: undefined, 28 | }, 29 | type: { 30 | type: String, 31 | required: true, 32 | }, 33 | inputAttributes: { 34 | type: Object, 35 | default: undefined, 36 | }, 37 | inputType: { 38 | type: String, 39 | required: true, 40 | }, 41 | inputValue: { 42 | type: [String, Array], 43 | default: undefined, 44 | }, 45 | inputPlaceholder: { 46 | type: String, 47 | default: undefined, 48 | }, 49 | inputOptions: { 50 | type: [Array, Object], 51 | default: undefined, 52 | }, 53 | errorMessage: { 54 | type: String, 55 | required: true, 56 | }, 57 | }, 58 | 59 | render(createElement: CreateElement): VNode { 60 | const subElements = []; 61 | 62 | if (this.title || this.$scopedSlots.title) { 63 | if (this.$scopedSlots.title) { 64 | subElements.push(createElement( 65 | 'div', 66 | { 67 | class: this.getElementCssClass('titleWrapper'), 68 | }, 69 | [ 70 | this.$scopedSlots.title({ class: this.getElementCssClass('title') }), 71 | ], 72 | )); 73 | } else { 74 | subElements.push(createElement( 75 | 'div', 76 | { 77 | class: this.getElementCssClass('titleWrapper'), 78 | }, 79 | [ 80 | createElement( 81 | this.titleTag, 82 | { 83 | class: this.getElementCssClass('title'), 84 | }, 85 | this.title || '', 86 | ), 87 | ], 88 | )); 89 | } 90 | } 91 | 92 | if (this.$slots.default) { 93 | subElements.push(createElement( 94 | 'div', 95 | { 96 | class: this.getElementCssClass('textWrapper'), 97 | }, 98 | this.$slots.default, 99 | )); 100 | } else if (this.text) { 101 | subElements.push(createElement( 102 | 'div', 103 | { 104 | class: this.getElementCssClass('textWrapper'), 105 | }, 106 | this.text ? [ 107 | createElement( 108 | this.textTag, 109 | { 110 | class: this.getElementCssClass('text'), 111 | }, 112 | this.text, 113 | ), 114 | ] : undefined, 115 | )); 116 | } 117 | 118 | if (this.type === DialogType.Prompt) { 119 | subElements.push( 120 | createElement( 121 | TDialogOverlayWrapperTransitionDialogContentInput, 122 | { 123 | props: { 124 | getElementCssClass: this.getElementCssClass, 125 | inputAttributes: this.inputAttributes, 126 | inputType: this.inputType, 127 | inputValue: this.inputValue, 128 | inputOptions: this.inputOptions, 129 | inputPlaceholder: this.inputPlaceholder, 130 | }, 131 | on: { 132 | input: (val: string) => this.$emit('input', val), 133 | }, 134 | }, 135 | ), 136 | ); 137 | } 138 | 139 | if (this.errorMessage && typeof this.errorMessage === 'string') { 140 | subElements.push(createElement( 141 | 'div', 142 | { 143 | class: this.getElementCssClass('errorMessage'), 144 | }, 145 | this.errorMessage, 146 | )); 147 | } 148 | 149 | return createElement( 150 | 'div', 151 | { 152 | class: this.getElementCssClass('content'), 153 | }, 154 | subElements, 155 | ); 156 | }, 157 | }); 158 | 159 | export default TDialogOverlayWrapperTransitionDialogContent; 160 | -------------------------------------------------------------------------------- /src/components/TDialog/TDialogOverlayWrapperTransitionDialogIcon.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | 3 | export enum IconName { 4 | Success = 'success', 5 | Error = 'error', 6 | Warning = 'warning', 7 | Info = 'info', 8 | Question = 'question', 9 | } 10 | 11 | type HtmlIcons = { 12 | [key in IconName]: string 13 | } 14 | 15 | function getHtmlSvgPath(iconName?: IconName) { 16 | if (!iconName) { return undefined; } 17 | 18 | const icons = {} as HtmlIcons; 19 | 20 | icons[IconName.Success] = ''; 21 | icons[IconName.Error] = ''; 22 | icons[IconName.Warning] = ''; 23 | icons[IconName.Info] = ''; 24 | icons[IconName.Question] = ''; 25 | 26 | return icons[iconName]; 27 | } 28 | 29 | const TDialogOverlayWrapperTransitionDialogIcon = Vue.extend({ 30 | name: 'TDialogOverlayWrapperTransitionDialogIcon', 31 | 32 | props: { 33 | getElementCssClass: { 34 | type: Function, 35 | required: true, 36 | }, 37 | icon: { 38 | type: String, 39 | default: undefined, 40 | }, 41 | }, 42 | 43 | render(createElement: CreateElement): VNode { 44 | if (this.$scopedSlots.icon) { 45 | return createElement( 46 | 'div', 47 | { 48 | class: this.getElementCssClass('iconWrapper'), 49 | }, 50 | [ 51 | this.$scopedSlots.icon({}), 52 | ], 53 | ); 54 | } 55 | 56 | const htmlSvgPath = getHtmlSvgPath(this.icon as IconName | undefined); 57 | 58 | if (!htmlSvgPath) { 59 | return createElement(); 60 | } 61 | 62 | return createElement( 63 | 'div', 64 | { 65 | class: this.getElementCssClass('iconWrapper'), 66 | }, 67 | [ 68 | createElement( 69 | 'svg', 70 | { 71 | class: this.getElementCssClass('icon'), 72 | attrs: { 73 | fill: 'none', 74 | stroke: 'currentColor', 75 | viewBox: '0 0 24 24', 76 | xmlns: 'http://www.w3.org/2000/svg', 77 | }, 78 | domProps: { 79 | innerHTML: htmlSvgPath, 80 | }, 81 | }, 82 | ), 83 | ], 84 | ); 85 | }, 86 | }); 87 | 88 | export default TDialogOverlayWrapperTransitionDialogIcon; 89 | -------------------------------------------------------------------------------- /src/components/TDialog/TDialogOverlayWrapperTransitionDialogLoader.ts: -------------------------------------------------------------------------------- 1 | import Vue, { CreateElement, VNode } from 'vue'; 2 | 3 | const TDialogOverlayWrapperTransitionDialogLoader = Vue.extend({ 4 | name: 'TDialogOverlayWrapperTransitionDialogLoader', 5 | 6 | props: { 7 | getElementCssClass: { 8 | type: Function, 9 | required: true, 10 | }, 11 | busy: { 12 | type: Boolean, 13 | required: true, 14 | }, 15 | }, 16 | 17 | render(createElement: CreateElement): VNode { 18 | if (!this.busy) { 19 | return createElement(); 20 | } 21 | 22 | if (this.$scopedSlots.loader) { 23 | return createElement( 24 | 'div', 25 | { 26 | class: this.getElementCssClass('busyWrapper'), 27 | }, 28 | [ 29 | this.$scopedSlots.loader({}), 30 | ], 31 | ); 32 | } 33 | 34 | return createElement( 35 | 'div', 36 | { 37 | class: this.getElementCssClass('busyWrapper'), 38 | }, 39 | [ 40 | createElement( 41 | 'svg', 42 | { 43 | attrs: { 44 | xmlns: 'http://www.w3.org/2000/svg', 45 | width: 32, 46 | height: 32, 47 | viewBox: '0 0 32 32', 48 | }, 49 | class: this.getElementCssClass('busyIcon'), 50 | }, 51 | [ 52 | createElement('g', { 53 | attrs: { 54 | transform: 'scale(0.03125 0.03125)', 55 | }, 56 | }, 57 | [ 58 | createElement('path', { 59 | attrs: { 60 | d: 'M512 1024c-136.76 0-265.334-53.258-362.040-149.96-96.702-96.706-149.96-225.28-149.96-362.040 0-96.838 27.182-191.134 78.606-272.692 50-79.296 120.664-143.372 204.356-185.3l43 85.832c-68.038 34.084-125.492 86.186-166.15 150.67-41.746 66.208-63.812 142.798-63.812 221.49 0 229.382 186.618 416 416 416s416-186.618 416-416c0-78.692-22.066-155.282-63.81-221.49-40.66-64.484-98.114-116.584-166.15-150.67l43-85.832c83.692 41.928 154.358 106.004 204.356 185.3 51.422 81.558 78.604 175.854 78.604 272.692 0 136.76-53.258 265.334-149.96 362.040-96.706 96.702-225.28 149.96-362.040 149.96z', 61 | }, 62 | }), 63 | ]), 64 | ], 65 | ), 66 | ], 67 | ); 68 | }, 69 | }); 70 | 71 | export default TDialogOverlayWrapperTransitionDialogLoader; 72 | -------------------------------------------------------------------------------- /src/components/TInputGroup.ts: -------------------------------------------------------------------------------- 1 | import intersection from 'lodash.intersection'; 2 | import { CreateElement, VNode } from 'vue'; 3 | import Component from '../base/Component'; 4 | 5 | const TInputGroup = Component.extend({ 6 | name: 'TInputGroup', 7 | 8 | props: { 9 | inputName: { 10 | type: String, 11 | default: undefined, 12 | }, 13 | label: { 14 | type: String, 15 | default: undefined, 16 | }, 17 | description: { 18 | type: String, 19 | default: undefined, 20 | }, 21 | feedback: { 22 | type: String, 23 | default: undefined, 24 | }, 25 | sortedElements: { 26 | type: Array, 27 | default: (): string[] => (['label', 'default', 'feedback', 'description']), 28 | validator(value) { 29 | const expectedValues = ['default', 'description', 'feedback', 'label']; 30 | return value.length === intersection(value, expectedValues).length; 31 | }, 32 | }, 33 | fixedClasses: { 34 | type: Object, 35 | default() { 36 | return {}; 37 | }, 38 | }, 39 | classes: { 40 | type: Object, 41 | default() { 42 | return { 43 | wrapper: '', 44 | label: 'block', 45 | body: '', 46 | feedback: 'text-gray-400 text-sm', 47 | description: 'text-gray-400 text-sm', 48 | }; 49 | }, 50 | }, 51 | }, 52 | 53 | render(createElement) { 54 | const renderFun: (createElement: CreateElement) => VNode = this.render; 55 | return renderFun(createElement); 56 | }, 57 | 58 | 59 | computed: { 60 | /** 61 | * Only render the elements that has a prop or a slot (always the default prop) 62 | * @return {Array} 63 | */ 64 | elementsToRender(): string[] { 65 | const props = this.$props; 66 | const slots = this.$slots; 67 | return (this.sortedElements as string[]) 68 | .filter((e) => e === 'default' || !!props[e] || !!slots[e]); 69 | }, 70 | }, 71 | 72 | methods: { 73 | render(createElement: CreateElement): VNode { 74 | return createElement( 75 | 'div', 76 | { 77 | ref: 'wrapper', 78 | class: this.getElementCssClass('wrapper'), 79 | }, 80 | this.elementsToRender.map((elementName) => createElement( 81 | this.getTagName(elementName), 82 | { 83 | ref: elementName, 84 | class: this.getElementCssClass(elementName === 'default' ? 'body' : elementName), 85 | attrs: { 86 | for: elementName === 'label' ? this.inputName : undefined, 87 | }, 88 | slot: elementName, 89 | }, 90 | this.$slots[elementName] || this.$props[elementName], 91 | )), 92 | ); 93 | }, 94 | 95 | /** 96 | * Get the tag name according to the slot name 97 | * @param {String} slotName 98 | * @return {String} 99 | */ 100 | getTagName(slotName: string) { 101 | switch (slotName) { 102 | case 'label': 103 | return 'label'; 104 | default: 105 | return 'div'; 106 | } 107 | }, 108 | }, 109 | }); 110 | 111 | export default TInputGroup; 112 | -------------------------------------------------------------------------------- /src/components/TRadioGroup.ts: -------------------------------------------------------------------------------- 1 | import { CreateElement, VNode } from 'vue'; 2 | import kebabCase from 'lodash.kebabcase'; 3 | import isEqual from 'lodash.isequal'; 4 | import InputWithOptions from '../base/InputWithOptions'; 5 | import TRadio from '../inputs/TRadio'; 6 | import NormalizedOption from '../types/NormalizedOption'; 7 | import NormalizedOptions from '../types/NormalizedOptions'; 8 | 9 | const TRadioGroup = InputWithOptions.extend({ 10 | name: 'TRadioGroup', 11 | 12 | props: { 13 | groupWrapperTag: { 14 | type: String, 15 | default: 'div', 16 | }, 17 | wrapperTag: { 18 | type: String, 19 | default: 'label', 20 | }, 21 | inputWrapperTag: { 22 | type: String, 23 | default: 'span', 24 | }, 25 | labelTag: { 26 | type: String, 27 | default: 'span', 28 | }, 29 | fixedClasses: { 30 | type: Object, 31 | default() { 32 | return {}; 33 | }, 34 | }, 35 | classes: { 36 | type: Object, 37 | default() { 38 | return { 39 | groupWrapper: 'flex flex-col', 40 | label: '', 41 | input: 'text-blue-500 transition duration-100 ease-in-out border-gray-300 shadow-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none focus:ring-opacity-50 focus:ring-offset-0 disabled:opacity-50 disabled:cursor-not-allowed', 42 | inputWrapper: 'inline-flex', 43 | wrapper: 'inline-flex items-center space-x-2', 44 | }; 45 | }, 46 | }, 47 | }, 48 | 49 | data() { 50 | return { 51 | localValue: this.value, 52 | }; 53 | }, 54 | 55 | watch: { 56 | localValue(localValue: string | null | string[]) { 57 | this.$emit('input', localValue); 58 | 59 | this.$emit('change', localValue); 60 | }, 61 | value(value) { 62 | this.localValue = value; 63 | }, 64 | }, 65 | 66 | render(createElement) { 67 | const createRadioGroupFunc: (createElement: CreateElement) => VNode = this.createRadioGroup; 68 | return createRadioGroupFunc(createElement); 69 | }, 70 | 71 | methods: { 72 | createRadioGroup(createElement: CreateElement) { 73 | return createElement( 74 | this.groupWrapperTag, 75 | { 76 | ref: 'wrapper', 77 | class: this.getElementCssClass('groupWrapper'), 78 | }, 79 | this.createRadioOptions(createElement), 80 | ); 81 | }, 82 | createRadioOptions(createElement: CreateElement): VNode[] { 83 | const options: NormalizedOptions = this.normalizedOptions; 84 | 85 | return options 86 | .map( 87 | (option: NormalizedOption, index) => this.createRadioOption(createElement, option, index), 88 | ); 89 | }, 90 | createRadioOption( 91 | createElement: CreateElement, 92 | option: NormalizedOption, 93 | index: number, 94 | ): VNode { 95 | return createElement( 96 | TRadio, 97 | { 98 | props: { 99 | id: this.buildId(option, index), 100 | name: this.name, 101 | tabindex: this.tabindex, 102 | disabled: this.disabled, 103 | autofocus: this.autofocus, 104 | required: this.required, 105 | model: this.localValue, 106 | label: option.text, 107 | wrapped: true, 108 | value: option.value, 109 | checked: this.value === option.value, 110 | variant: this.variant, 111 | classes: this.classes, 112 | fixedClasses: this.fixedClasses, 113 | variants: this.variants, 114 | wrapperTag: this.wrapperTag, 115 | inputWrapperTag: this.inputWrapperTag, 116 | labelTag: this.labelTag, 117 | }, 118 | scopedSlots: { 119 | default: this.$scopedSlots.default, 120 | }, 121 | on: { 122 | blur: this.blurHandler, 123 | focus: this.focusHandler, 124 | input: (value: string | number) => { 125 | if (isEqual(value, option.value)) { 126 | this.inputHandler(option.value); 127 | } 128 | }, 129 | }, 130 | }, 131 | ); 132 | }, 133 | 134 | buildId(option: NormalizedOption, index: number) { 135 | const parts = []; 136 | 137 | if (this.id) { 138 | parts.push(this.id); 139 | } else if (this.name) { 140 | parts.push(this.name); 141 | } 142 | 143 | if (['string', 'number'].includes(typeof option.value)) { 144 | parts.push(kebabCase(String(option.value))); 145 | } else { 146 | parts.push(index); 147 | } 148 | 149 | return parts.join('-'); 150 | }, 151 | 152 | inputHandler(value: string | number | boolean | symbol | null) { 153 | this.$emit('input', value); 154 | }, 155 | 156 | blurHandler(e: FocusEvent) { 157 | this.$emit('blur', e); 158 | }, 159 | 160 | focusHandler(e: FocusEvent) { 161 | this.$emit('focus', e); 162 | }, 163 | }, 164 | }); 165 | 166 | export default TRadioGroup; 167 | -------------------------------------------------------------------------------- /src/components/TTag.ts: -------------------------------------------------------------------------------- 1 | import { CreateElement, VNode } from 'vue'; 2 | import Component from '../base/Component'; 3 | 4 | const TTag = Component.extend({ 5 | name: 'TTag', 6 | 7 | props: { 8 | text: { 9 | type: String, 10 | default: undefined, 11 | }, 12 | tagName: { 13 | type: String, 14 | default: 'div', 15 | }, 16 | }, 17 | 18 | render(createElement) { 19 | const renderFun: (createElement: CreateElement) => VNode = this.render; 20 | return renderFun(createElement); 21 | }, 22 | 23 | methods: { 24 | render(createElement: CreateElement) { 25 | return createElement( 26 | this.tagName, 27 | { 28 | class: this.componentClass, 29 | }, 30 | this.text === undefined ? this.$slots.default : this.text, 31 | ); 32 | }, 33 | }, 34 | }); 35 | 36 | export default TTag; 37 | -------------------------------------------------------------------------------- /src/configure.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import { VTComponent, CustomProp } from './types/ComponentSettings'; 3 | import CustomProps from './types/CustomProps'; 4 | import configureDialogGlobals from './utils/configureDialogGlobals'; 5 | 6 | const configure = (component: VTComponent, props?: CustomProp): VTComponent => { 7 | const componentProps = component?.options?.props; 8 | const componentName = component?.options?.name; 9 | 10 | if (componentName === 'TModal') { 11 | // eslint-disable-next-line no-param-reassign 12 | Vue.prototype.$modal = new Vue({ 13 | methods: { 14 | show(name: string, params = undefined) { 15 | this.$emit(`show-${name}`, params); 16 | }, 17 | hide(name: string) { 18 | this.$emit(`hide-${name}`); 19 | }, 20 | }, 21 | }); 22 | } else if (componentName === 'TDialog') { 23 | configureDialogGlobals(Vue, props); 24 | } 25 | 26 | if (!props || !componentProps) { 27 | return component; 28 | } 29 | 30 | const customProps: CustomProps = {}; 31 | 32 | Object.keys(props).forEach((customPropName: string) => { 33 | const defaultProp = componentProps[customPropName]; 34 | 35 | if (!defaultProp) { 36 | return; 37 | } 38 | const newDefaultValue = props[customPropName]; 39 | 40 | customProps[customPropName] = { 41 | type: defaultProp?.type, 42 | default: ['object', 'function'].includes(typeof newDefaultValue) 43 | ? () => newDefaultValue 44 | : newDefaultValue, 45 | }; 46 | }); 47 | 48 | return component.extend({ 49 | props: customProps, 50 | }); 51 | }; 52 | 53 | export default configure; 54 | -------------------------------------------------------------------------------- /src/full.ts: -------------------------------------------------------------------------------- 1 | import Vue, { PluginFunction } from 'vue'; 2 | import configure from './configure'; 3 | import * as components from './components'; 4 | import ComponentName from './types/ComponentName'; 5 | import { CustomProp, VTComponent } from './types/ComponentSettings'; 6 | 7 | interface InstallFunction extends PluginFunction { 8 | installed?: boolean; 9 | } 10 | 11 | const entries = Object.entries(components) as [ComponentName, VTComponent][]; 12 | 13 | type AllComponentsSettings = { 14 | [name in ComponentName]: CustomProp 15 | } 16 | 17 | // install function executed by Vue.use() 18 | // eslint-disable-next-line max-len 19 | const install: InstallFunction = function installVueTailwind(vueInstance: typeof Vue, settings?: AllComponentsSettings) { 20 | if (install.installed) return; 21 | 22 | install.installed = true; 23 | 24 | // eslint-disable-next-line no-param-reassign 25 | vueInstance.prototype.$vueTailwind = true; 26 | 27 | entries.forEach(([componentName, component]) => { 28 | const props: CustomProp | undefined = settings ? settings[componentName] : undefined; 29 | vueInstance.component(componentName, configure(component, props)); 30 | }); 31 | }; 32 | 33 | // Create module definition for Vue.use() 34 | const plugin = { 35 | install, 36 | }; 37 | 38 | // Default export is library as a whole, registered via Vue.use() 39 | export default plugin; 40 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import Vue, { PluginFunction } from 'vue'; 2 | import ComponentSettings from './types/ComponentSettings'; 3 | import LibrarySettings from './types/LibrarySettings'; 4 | import configure from './configure'; 5 | 6 | export { default as BaseComponent } from './base/Component'; 7 | 8 | export interface InstallFunction extends PluginFunction { 9 | installed?: boolean; 10 | } 11 | 12 | // install function executed by Vue.use() 13 | // eslint-disable-next-line max-len 14 | const install: InstallFunction = function installVueTailwind(vueInstance: typeof Vue, settings: LibrarySettings) { 15 | if (install.installed) return; 16 | 17 | install.installed = true; 18 | 19 | // eslint-disable-next-line no-param-reassign 20 | vueInstance.prototype.$vueTailwind = true; 21 | 22 | if (!settings) { 23 | return; 24 | } 25 | 26 | Object.keys(settings).forEach((componentName) => { 27 | const componentSettings = settings[componentName]; 28 | 29 | if (typeof componentSettings === 'function' && typeof componentSettings.extend !== undefined) { 30 | const component = componentSettings; 31 | vueInstance.component(componentName, configure(component)); 32 | return; 33 | } 34 | 35 | const { component, props } = componentSettings as ComponentSettings; 36 | 37 | vueInstance.component(componentName, configure(component, props)); 38 | }); 39 | }; 40 | 41 | // Create module definition for Vue.use() 42 | const plugin = { 43 | install, 44 | }; 45 | 46 | // Default export is library as a whole, registered via Vue.use() 47 | export default plugin; 48 | -------------------------------------------------------------------------------- /src/inputs/TInput.ts: -------------------------------------------------------------------------------- 1 | import { CreateElement, VNode } from 'vue'; 2 | import TextInput from '../base/TextInput'; 3 | 4 | const TInput = TextInput.extend({ 5 | name: 'TInput', 6 | props: { 7 | type: { 8 | type: String, 9 | default: 'text', 10 | }, 11 | max: { 12 | type: [String, Number], 13 | default: undefined, 14 | }, 15 | min: { 16 | type: [String, Number], 17 | default: undefined, 18 | }, 19 | classes: { 20 | type: [String, Array, Object], 21 | default: 'block w-full px-3 py-2 text-black placeholder-gray-400 transition duration-100 ease-in-out bg-white border border-gray-300 rounded shadow-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none focus:ring-opacity-50 disabled:opacity-50 disabled:cursor-not-allowed', 22 | }, 23 | }, 24 | render(createElement: CreateElement) { 25 | const renderFun: (ce: CreateElement) => VNode = this.render; 26 | return renderFun(createElement); 27 | }, 28 | methods: { 29 | render(createElement: CreateElement): VNode { 30 | return createElement('input', { 31 | class: this.componentClass, 32 | ref: 'input', 33 | domProps: { 34 | value: this.localValue, 35 | }, 36 | attrs: { 37 | id: this.id, 38 | name: this.name, 39 | disabled: this.disabled, 40 | readonly: this.readonly, 41 | autocomplete: this.autocomplete, 42 | autofocus: this.autofocus, 43 | type: this.type, 44 | required: this.required, 45 | placeholder: this.placeholder, 46 | pattern: this.pattern, 47 | multiple: this.multiple, 48 | minlength: this.minlength, 49 | min: this.min, 50 | maxlength: this.maxlength, 51 | max: this.max, 52 | }, 53 | on: this.getListeners({ 54 | blur: this.blurHandler, 55 | focus: this.focusHandler, 56 | keyup: this.keyupHandler, 57 | keydown: this.keydownHandler, 58 | input: this.inputHandler, 59 | }), 60 | }); 61 | }, 62 | inputHandler(e: Event) { 63 | const target = (e.target as HTMLInputElement); 64 | 65 | this.$emit('input', target.value); 66 | }, 67 | }, 68 | 69 | }); 70 | 71 | export default TInput; 72 | -------------------------------------------------------------------------------- /src/inputs/TTextarea.ts: -------------------------------------------------------------------------------- 1 | import { CreateElement, VNode } from 'vue'; 2 | import TextInput from '../base/TextInput'; 3 | 4 | const TTextarea = TextInput.extend({ 5 | name: 'TTextarea', 6 | props: { 7 | rows: { 8 | type: String, 9 | default: undefined, 10 | }, 11 | cols: { 12 | type: String, 13 | default: undefined, 14 | }, 15 | wrap: { 16 | type: String, 17 | default: 'soft', 18 | }, 19 | classes: { 20 | type: [String, Array, Object], 21 | default: 'block w-full px-3 py-2 text-black placeholder-gray-400 transition duration-100 ease-in-out bg-white border border-gray-300 rounded shadow-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none focus:ring-opacity-50 disabled:opacity-50 disabled:cursor-not-allowed', 22 | }, 23 | }, 24 | render(createElement) { 25 | const renderFun: (createElement: CreateElement) => VNode = this.render; 26 | return renderFun(createElement); 27 | }, 28 | methods: { 29 | render(createElement: CreateElement): VNode { 30 | return createElement('textarea', { 31 | class: this.componentClass, 32 | ref: 'input', 33 | domProps: { 34 | value: this.localValue, 35 | }, 36 | attrs: { 37 | id: this.id, 38 | name: this.name, 39 | disabled: this.disabled, 40 | readonly: this.readonly, 41 | autocomplete: this.autocomplete, 42 | autofocus: this.autofocus, 43 | required: this.required, 44 | placeholder: this.placeholder, 45 | pattern: this.pattern, 46 | multiple: this.multiple, 47 | minlength: this.minlength, 48 | maxlength: this.maxlength, 49 | wrap: this.wrap, 50 | rows: this.rows, 51 | cols: this.cols, 52 | }, 53 | on: this.getListeners({ 54 | blur: this.blurHandler, 55 | focus: this.focusHandler, 56 | keyup: this.keyupHandler, 57 | keydown: this.keydownHandler, 58 | input: this.inputHandler, 59 | }), 60 | }); 61 | }, 62 | inputHandler(e: Event) { 63 | const target = (e.target as HTMLTextAreaElement); 64 | this.$emit('input', target.value); 65 | }, 66 | }, 67 | }); 68 | 69 | export default TTextarea; 70 | -------------------------------------------------------------------------------- /src/l10n/ar.ts: -------------------------------------------------------------------------------- 1 | /* Arabic locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Arabic: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'], 7 | longhand: [ 8 | 'الأحد', 9 | 'الاثنين', 10 | 'الثلاثاء', 11 | 'الأربعاء', 12 | 'الخميس', 13 | 'الجمعة', 14 | 'السبت', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'], 20 | longhand: [ 21 | 'يناير', 22 | 'فبراير', 23 | 'مارس', 24 | 'أبريل', 25 | 'مايو', 26 | 'يونيو', 27 | 'يوليو', 28 | 'أغسطس', 29 | 'سبتمبر', 30 | 'أكتوبر', 31 | 'نوفمبر', 32 | 'ديسمبر', 33 | ], 34 | }, 35 | 36 | rangeSeparator: ' - ', 37 | }; 38 | 39 | export default Arabic; 40 | -------------------------------------------------------------------------------- /src/l10n/at.ts: -------------------------------------------------------------------------------- 1 | /* Austria locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Austria: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'], 7 | longhand: [ 8 | 'Sonntag', 9 | 'Montag', 10 | 'Dienstag', 11 | 'Mittwoch', 12 | 'Donnerstag', 13 | 'Freitag', 14 | 'Samstag', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Jän', 21 | 'Feb', 22 | 'Mär', 23 | 'Apr', 24 | 'Mai', 25 | 'Jun', 26 | 'Jul', 27 | 'Aug', 28 | 'Sep', 29 | 'Okt', 30 | 'Nov', 31 | 'Dez', 32 | ], 33 | longhand: [ 34 | 'Jänner', 35 | 'Februar', 36 | 'März', 37 | 'April', 38 | 'Mai', 39 | 'Juni', 40 | 'Juli', 41 | 'August', 42 | 'September', 43 | 'Oktober', 44 | 'November', 45 | 'Dezember', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | weekAbbreviation: 'KW', 51 | rangeSeparator: ' bis ', 52 | }; 53 | 54 | export default Austria; 55 | -------------------------------------------------------------------------------- /src/l10n/az.ts: -------------------------------------------------------------------------------- 1 | /* Azerbaijan locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Azerbaijan: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['B.', 'B.e.', 'Ç.a.', 'Ç.', 'C.a.', 'C.', 'Ş.'], 7 | longhand: [ 8 | 'Bazar', 9 | 'Bazar ertəsi', 10 | 'Çərşənbə axşamı', 11 | 'Çərşənbə', 12 | 'Cümə axşamı', 13 | 'Cümə', 14 | 'Şənbə', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Yan', 21 | 'Fev', 22 | 'Mar', 23 | 'Apr', 24 | 'May', 25 | 'İyn', 26 | 'İyl', 27 | 'Avq', 28 | 'Sen', 29 | 'Okt', 30 | 'Noy', 31 | 'Dek', 32 | ], 33 | longhand: [ 34 | 'Yanvar', 35 | 'Fevral', 36 | 'Mart', 37 | 'Aprel', 38 | 'May', 39 | 'İyun', 40 | 'İyul', 41 | 'Avqust', 42 | 'Sentyabr', 43 | 'Oktyabr', 44 | 'Noyabr', 45 | 'Dekabr', 46 | ], 47 | }, 48 | firstDayOfWeek: 1, 49 | ordinal: () => '.', 50 | rangeSeparator: ' - ', 51 | weekAbbreviation: 'Hf', 52 | amPM: ['GƏ', 'GS'], 53 | time24hr: true, 54 | }; 55 | 56 | export default Azerbaijan; 57 | -------------------------------------------------------------------------------- /src/l10n/be.ts: -------------------------------------------------------------------------------- 1 | /* Belarusian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Belarusian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Нд', 'Пн', 'Аў', 'Ср', 'Чц', 'Пт', 'Сб'], 7 | longhand: [ 8 | 'Нядзеля', 9 | 'Панядзелак', 10 | 'Аўторак', 11 | 'Серада', 12 | 'Чацвер', 13 | 'Пятніца', 14 | 'Субота', 15 | ], 16 | }, 17 | months: { 18 | shorthand: [ 19 | 'Сту', 20 | 'Лют', 21 | 'Сак', 22 | 'Кра', 23 | 'Тра', 24 | 'Чэр', 25 | 'Ліп', 26 | 'Жні', 27 | 'Вер', 28 | 'Кас', 29 | 'Ліс', 30 | 'Сне', 31 | ], 32 | longhand: [ 33 | 'Студзень', 34 | 'Люты', 35 | 'Сакавік', 36 | 'Красавік', 37 | 'Травень', 38 | 'Чэрвень', 39 | 'Ліпень', 40 | 'Жнівень', 41 | 'Верасень', 42 | 'Кастрычнік', 43 | 'Лістапад', 44 | 'Снежань', 45 | ], 46 | }, 47 | firstDayOfWeek: 1, 48 | ordinal() { 49 | return ''; 50 | }, 51 | rangeSeparator: ' — ', 52 | weekAbbreviation: 'Тыд.', 53 | amPM: ['ДП', 'ПП'], 54 | yearAriaLabel: 'Год', 55 | time24hr: true, 56 | }; 57 | 58 | export default Belarusian; 59 | -------------------------------------------------------------------------------- /src/l10n/bg.ts: -------------------------------------------------------------------------------- 1 | /* Bulgarian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Bulgarian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Нд', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'], 7 | longhand: [ 8 | 'Неделя', 9 | 'Понеделник', 10 | 'Вторник', 11 | 'Сряда', 12 | 'Четвъртък', 13 | 'Петък', 14 | 'Събота', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Яну', 21 | 'Фев', 22 | 'Март', 23 | 'Апр', 24 | 'Май', 25 | 'Юни', 26 | 'Юли', 27 | 'Авг', 28 | 'Сеп', 29 | 'Окт', 30 | 'Ное', 31 | 'Дек', 32 | ], 33 | longhand: [ 34 | 'Януари', 35 | 'Февруари', 36 | 'Март', 37 | 'Април', 38 | 'Май', 39 | 'Юни', 40 | 'Юли', 41 | 'Август', 42 | 'Септември', 43 | 'Октомври', 44 | 'Ноември', 45 | 'Декември', 46 | ], 47 | }, 48 | time24hr: true, 49 | firstDayOfWeek: 1, 50 | }; 51 | 52 | export default Bulgarian; 53 | -------------------------------------------------------------------------------- /src/l10n/bn.ts: -------------------------------------------------------------------------------- 1 | /* Bangla locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Bangla: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'], 7 | longhand: [ 8 | 'রবিবার', 9 | 'সোমবার', 10 | 'মঙ্গলবার', 11 | 'বুধবার', 12 | 'বৃহস্পতিবার', 13 | 'শুক্রবার', 14 | 'শনিবার', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'জানু', 21 | 'ফেব্রু', 22 | 'মার্চ', 23 | 'এপ্রিল', 24 | 'মে', 25 | 'জুন', 26 | 'জুলাই', 27 | 'আগ', 28 | 'সেপ্টে', 29 | 'অক্টো', 30 | 'নভে', 31 | 'ডিসে', 32 | ], 33 | longhand: [ 34 | 'জানুয়ারী', 35 | 'ফেব্রুয়ারী', 36 | 'মার্চ', 37 | 'এপ্রিল', 38 | 'মে', 39 | 'জুন', 40 | 'জুলাই', 41 | 'আগস্ট', 42 | 'সেপ্টেম্বর', 43 | 'অক্টোবর', 44 | 'নভেম্বর', 45 | 'ডিসেম্বর', 46 | ], 47 | }, 48 | }; 49 | 50 | export default Bangla; 51 | -------------------------------------------------------------------------------- /src/l10n/bs.ts: -------------------------------------------------------------------------------- 1 | /* Bosnian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Bosnian: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | 7 | weekdays: { 8 | shorthand: ['Ned', 'Pon', 'Uto', 'Sri', 'Čet', 'Pet', 'Sub'], 9 | longhand: [ 10 | 'Nedjelja', 11 | 'Ponedjeljak', 12 | 'Utorak', 13 | 'Srijeda', 14 | 'Četvrtak', 15 | 'Petak', 16 | 'Subota', 17 | ], 18 | }, 19 | 20 | months: { 21 | shorthand: [ 22 | 'Jan', 23 | 'Feb', 24 | 'Mar', 25 | 'Apr', 26 | 'Maj', 27 | 'Jun', 28 | 'Jul', 29 | 'Avg', 30 | 'Sep', 31 | 'Okt', 32 | 'Nov', 33 | 'Dec', 34 | ], 35 | longhand: [ 36 | 'Januar', 37 | 'Februar', 38 | 'Mart', 39 | 'April', 40 | 'Maj', 41 | 'Juni', 42 | 'Juli', 43 | 'Avgust', 44 | 'Septembar', 45 | 'Oktobar', 46 | 'Novembar', 47 | 'Decembar', 48 | ], 49 | }, 50 | time24hr: true, 51 | }; 52 | 53 | export default Bosnian; 54 | -------------------------------------------------------------------------------- /src/l10n/cat.ts: -------------------------------------------------------------------------------- 1 | /* Catalan locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Catalan: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Dg', 'Dl', 'Dt', 'Dc', 'Dj', 'Dv', 'Ds'], 7 | longhand: [ 8 | 'Diumenge', 9 | 'Dilluns', 10 | 'Dimarts', 11 | 'Dimecres', 12 | 'Dijous', 13 | 'Divendres', 14 | 'Dissabte', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Gen', 21 | 'Febr', 22 | 'Març', 23 | 'Abr', 24 | 'Maig', 25 | 'Juny', 26 | 'Jul', 27 | 'Ag', 28 | 'Set', 29 | 'Oct', 30 | 'Nov', 31 | 'Des', 32 | ], 33 | longhand: [ 34 | 'Gener', 35 | 'Febrer', 36 | 'Març', 37 | 'Abril', 38 | 'Maig', 39 | 'Juny', 40 | 'Juliol', 41 | 'Agost', 42 | 'Setembre', 43 | 'Octubre', 44 | 'Novembre', 45 | 'Desembre', 46 | ], 47 | }, 48 | 49 | ordinal: (nth) => { 50 | const s = nth % 100; 51 | if (s > 3 && s < 21) return 'è'; 52 | switch (s % 10) { 53 | case 1: 54 | return 'r'; 55 | case 2: 56 | return 'n'; 57 | case 3: 58 | return 'r'; 59 | case 4: 60 | return 't'; 61 | default: 62 | return 'è'; 63 | } 64 | }, 65 | 66 | firstDayOfWeek: 1, 67 | time24hr: true, 68 | }; 69 | 70 | export default Catalan; 71 | -------------------------------------------------------------------------------- /src/l10n/cs.ts: -------------------------------------------------------------------------------- 1 | /* Czech locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Czech: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'], 7 | longhand: [ 8 | 'Neděle', 9 | 'Pondělí', 10 | 'Úterý', 11 | 'Středa', 12 | 'Čtvrtek', 13 | 'Pátek', 14 | 'Sobota', 15 | ], 16 | }, 17 | months: { 18 | shorthand: [ 19 | 'Led', 20 | 'Ún', 21 | 'Bře', 22 | 'Dub', 23 | 'Kvě', 24 | 'Čer', 25 | 'Čvc', 26 | 'Srp', 27 | 'Zář', 28 | 'Říj', 29 | 'Lis', 30 | 'Pro', 31 | ], 32 | longhand: [ 33 | 'Leden', 34 | 'Únor', 35 | 'Březen', 36 | 'Duben', 37 | 'Květen', 38 | 'Červen', 39 | 'Červenec', 40 | 'Srpen', 41 | 'Září', 42 | 'Říjen', 43 | 'Listopad', 44 | 'Prosinec', 45 | ], 46 | }, 47 | firstDayOfWeek: 1, 48 | ordinal() { 49 | return '.'; 50 | }, 51 | rangeSeparator: ' do ', 52 | weekAbbreviation: 'Týd.', 53 | amPM: ['dop.', 'odp.'], 54 | yearAriaLabel: 'Rok', 55 | time24hr: true, 56 | }; 57 | 58 | export default Czech; 59 | -------------------------------------------------------------------------------- /src/l10n/cy.ts: -------------------------------------------------------------------------------- 1 | /* Welsh locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Welsh: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Sul', 'Llun', 'Maw', 'Mer', 'Iau', 'Gwe', 'Sad'], 7 | longhand: [ 8 | 'Dydd Sul', 9 | 'Dydd Llun', 10 | 'Dydd Mawrth', 11 | 'Dydd Mercher', 12 | 'Dydd Iau', 13 | 'Dydd Gwener', 14 | 'Dydd Sadwrn', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Ion', 21 | 'Chwef', 22 | 'Maw', 23 | 'Ebr', 24 | 'Mai', 25 | 'Meh', 26 | 'Gorff', 27 | 'Awst', 28 | 'Medi', 29 | 'Hyd', 30 | 'Tach', 31 | 'Rhag', 32 | ], 33 | longhand: [ 34 | 'Ionawr', 35 | 'Chwefror', 36 | 'Mawrth', 37 | 'Ebrill', 38 | 'Mai', 39 | 'Mehefin', 40 | 'Gorffennaf', 41 | 'Awst', 42 | 'Medi', 43 | 'Hydref', 44 | 'Tachwedd', 45 | 'Rhagfyr', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | 51 | ordinal: (nth) => { 52 | if (nth === 1) return 'af'; 53 | 54 | if (nth === 2) return 'ail'; 55 | 56 | if (nth === 3 || nth === 4) return 'ydd'; 57 | 58 | if (nth === 5 || nth === 6) return 'ed'; 59 | 60 | if ( 61 | (nth >= 7 && nth <= 10) 62 | || nth === 12 63 | || nth === 15 64 | || nth === 18 65 | || nth === 20 66 | ) { return 'fed'; } 67 | 68 | if ( 69 | nth === 11 70 | || nth === 13 71 | || nth === 14 72 | || nth === 16 73 | || nth === 17 74 | || nth === 19 75 | ) { return 'eg'; } 76 | 77 | if (nth >= 21 && nth <= 39) return 'ain'; 78 | 79 | // Inconclusive. 80 | return ''; 81 | }, 82 | time24hr: true, 83 | }; 84 | 85 | export default Welsh; 86 | -------------------------------------------------------------------------------- /src/l10n/da.ts: -------------------------------------------------------------------------------- 1 | /* Danish locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Danish: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['søn', 'man', 'tir', 'ons', 'tors', 'fre', 'lør'], 7 | longhand: [ 8 | 'søndag', 9 | 'mandag', 10 | 'tirsdag', 11 | 'onsdag', 12 | 'torsdag', 13 | 'fredag', 14 | 'lørdag', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'jan', 21 | 'feb', 22 | 'mar', 23 | 'apr', 24 | 'maj', 25 | 'jun', 26 | 'jul', 27 | 'aug', 28 | 'sep', 29 | 'okt', 30 | 'nov', 31 | 'dec', 32 | ], 33 | longhand: [ 34 | 'januar', 35 | 'februar', 36 | 'marts', 37 | 'april', 38 | 'maj', 39 | 'juni', 40 | 'juli', 41 | 'august', 42 | 'september', 43 | 'oktober', 44 | 'november', 45 | 'december', 46 | ], 47 | }, 48 | 49 | ordinal: () => '.', 50 | 51 | firstDayOfWeek: 1, 52 | rangeSeparator: ' til ', 53 | weekAbbreviation: 'uge', 54 | time24hr: true, 55 | }; 56 | 57 | export default Danish; 58 | -------------------------------------------------------------------------------- /src/l10n/de.ts: -------------------------------------------------------------------------------- 1 | /* German locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const German: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'], 7 | longhand: [ 8 | 'Sonntag', 9 | 'Montag', 10 | 'Dienstag', 11 | 'Mittwoch', 12 | 'Donnerstag', 13 | 'Freitag', 14 | 'Samstag', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Jan', 21 | 'Feb', 22 | 'Mär', 23 | 'Apr', 24 | 'Mai', 25 | 'Jun', 26 | 'Jul', 27 | 'Aug', 28 | 'Sep', 29 | 'Okt', 30 | 'Nov', 31 | 'Dez', 32 | ], 33 | longhand: [ 34 | 'Januar', 35 | 'Februar', 36 | 'März', 37 | 'April', 38 | 'Mai', 39 | 'Juni', 40 | 'Juli', 41 | 'August', 42 | 'September', 43 | 'Oktober', 44 | 'November', 45 | 'Dezember', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | weekAbbreviation: 'KW', 51 | rangeSeparator: ' bis ', 52 | time24hr: true, 53 | }; 54 | 55 | export default German; 56 | -------------------------------------------------------------------------------- /src/l10n/default.ts: -------------------------------------------------------------------------------- 1 | import { Locale } from '../types/locale'; 2 | 3 | export const English: Locale = { 4 | weekdays: { 5 | shorthand: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], 6 | longhand: [ 7 | 'Sunday', 8 | 'Monday', 9 | 'Tuesday', 10 | 'Wednesday', 11 | 'Thursday', 12 | 'Friday', 13 | 'Saturday', 14 | ], 15 | }, 16 | months: { 17 | shorthand: [ 18 | 'Jan', 19 | 'Feb', 20 | 'Mar', 21 | 'Apr', 22 | 'May', 23 | 'Jun', 24 | 'Jul', 25 | 'Aug', 26 | 'Sep', 27 | 'Oct', 28 | 'Nov', 29 | 'Dec', 30 | ], 31 | longhand: [ 32 | 'January', 33 | 'February', 34 | 'March', 35 | 'April', 36 | 'May', 37 | 'June', 38 | 'July', 39 | 'August', 40 | 'September', 41 | 'October', 42 | 'November', 43 | 'December', 44 | ], 45 | }, 46 | daysInMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], 47 | firstDayOfWeek: 0, 48 | ordinal: (nth: number) => { 49 | const s = nth % 100; 50 | if (s > 3 && s < 21) return 'th'; 51 | switch (s % 10) { 52 | case 1: 53 | return 'st'; 54 | case 2: 55 | return 'nd'; 56 | case 3: 57 | return 'rd'; 58 | default: 59 | return 'th'; 60 | } 61 | }, 62 | rangeSeparator: ' to ', 63 | weekAbbreviation: 'Wk', 64 | amPM: ['AM', 'PM'], 65 | yearAriaLabel: 'Year', 66 | monthAriaLabel: 'Month', 67 | hourAriaLabel: 'Hour', 68 | minuteAriaLabel: 'Minute', 69 | time24hr: false, 70 | timeLabel: 'Time', 71 | okLabel: 'Ok', 72 | }; 73 | 74 | export default English; 75 | -------------------------------------------------------------------------------- /src/l10n/eo.ts: -------------------------------------------------------------------------------- 1 | /* Esperanto locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Esperanto: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | 7 | rangeSeparator: ' ĝis ', 8 | weekAbbreviation: 'Sem', 9 | 10 | weekdays: { 11 | shorthand: ['Dim', 'Lun', 'Mar', 'Mer', 'Ĵaŭ', 'Ven', 'Sab'], 12 | longhand: [ 13 | 'dimanĉo', 14 | 'lundo', 15 | 'mardo', 16 | 'merkredo', 17 | 'ĵaŭdo', 18 | 'vendredo', 19 | 'sabato', 20 | ], 21 | }, 22 | 23 | months: { 24 | shorthand: [ 25 | 'Jan', 26 | 'Feb', 27 | 'Mar', 28 | 'Apr', 29 | 'Maj', 30 | 'Jun', 31 | 'Jul', 32 | 'Aŭg', 33 | 'Sep', 34 | 'Okt', 35 | 'Nov', 36 | 'Dec', 37 | ], 38 | longhand: [ 39 | 'januaro', 40 | 'februaro', 41 | 'marto', 42 | 'aprilo', 43 | 'majo', 44 | 'junio', 45 | 'julio', 46 | 'aŭgusto', 47 | 'septembro', 48 | 'oktobro', 49 | 'novembro', 50 | 'decembro', 51 | ], 52 | }, 53 | 54 | ordinal: () => '-a', 55 | time24hr: true, 56 | }; 57 | 58 | export default Esperanto; 59 | -------------------------------------------------------------------------------- /src/l10n/es.ts: -------------------------------------------------------------------------------- 1 | /* Spanish locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Spanish: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'], 7 | longhand: [ 8 | 'Domingo', 9 | 'Lunes', 10 | 'Martes', 11 | 'Miércoles', 12 | 'Jueves', 13 | 'Viernes', 14 | 'Sábado', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Ene', 21 | 'Feb', 22 | 'Mar', 23 | 'Abr', 24 | 'May', 25 | 'Jun', 26 | 'Jul', 27 | 'Ago', 28 | 'Sep', 29 | 'Oct', 30 | 'Nov', 31 | 'Dic', 32 | ], 33 | longhand: [ 34 | 'Enero', 35 | 'Febrero', 36 | 'Marzo', 37 | 'Abril', 38 | 'Mayo', 39 | 'Junio', 40 | 'Julio', 41 | 'Agosto', 42 | 'Septiembre', 43 | 'Octubre', 44 | 'Noviembre', 45 | 'Diciembre', 46 | ], 47 | }, 48 | 49 | ordinal: () => 'º', 50 | 51 | firstDayOfWeek: 1, 52 | rangeSeparator: ' a ', 53 | time24hr: true, 54 | timeLabel: 'Hora', 55 | okLabel: 'Ok', 56 | }; 57 | 58 | export default Spanish; 59 | -------------------------------------------------------------------------------- /src/l10n/et.ts: -------------------------------------------------------------------------------- 1 | /* Estonian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Estonian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['P', 'E', 'T', 'K', 'N', 'R', 'L'], 7 | longhand: [ 8 | 'Pühapäev', 9 | 'Esmaspäev', 10 | 'Teisipäev', 11 | 'Kolmapäev', 12 | 'Neljapäev', 13 | 'Reede', 14 | 'Laupäev', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Jaan', 21 | 'Veebr', 22 | 'Märts', 23 | 'Apr', 24 | 'Mai', 25 | 'Juuni', 26 | 'Juuli', 27 | 'Aug', 28 | 'Sept', 29 | 'Okt', 30 | 'Nov', 31 | 'Dets', 32 | ], 33 | longhand: [ 34 | 'Jaanuar', 35 | 'Veebruar', 36 | 'Märts', 37 | 'Aprill', 38 | 'Mai', 39 | 'Juuni', 40 | 'Juuli', 41 | 'August', 42 | 'September', 43 | 'Oktoober', 44 | 'November', 45 | 'Detsember', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | 51 | ordinal() { 52 | return '.'; 53 | }, 54 | 55 | weekAbbreviation: 'Näd', 56 | rangeSeparator: ' kuni ', 57 | time24hr: true, 58 | }; 59 | 60 | export default Estonian; 61 | -------------------------------------------------------------------------------- /src/l10n/fa.ts: -------------------------------------------------------------------------------- 1 | /* Farsi (Persian) locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Persian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['یک', 'دو', 'سه', 'چهار', 'پنج', 'جمعه', 'شنبه'], 7 | longhand: [ 8 | 'یک‌شنبه', 9 | 'دوشنبه', 10 | 'سه‌شنبه', 11 | 'چهارشنبه', 12 | 'پنچ‌شنبه', 13 | 'جمعه', 14 | 'شنبه', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'ژانویه', 21 | 'فوریه', 22 | 'مارس', 23 | 'آوریل', 24 | 'مه', 25 | 'ژوئن', 26 | 'ژوئیه', 27 | 'اوت', 28 | 'سپتامبر', 29 | 'اکتبر', 30 | 'نوامبر', 31 | 'دسامبر', 32 | ], 33 | longhand: [ 34 | 'ژانویه', 35 | 'فوریه', 36 | 'مارس', 37 | 'آوریل', 38 | 'مه', 39 | 'ژوئن', 40 | 'ژوئیه', 41 | 'اوت', 42 | 'سپتامبر', 43 | 'اکتبر', 44 | 'نوامبر', 45 | 'دسامبر', 46 | ], 47 | }, 48 | firstDayOfWeek: 6, 49 | ordinal: () => '', 50 | }; 51 | 52 | export default Persian; 53 | -------------------------------------------------------------------------------- /src/l10n/fi.ts: -------------------------------------------------------------------------------- 1 | /* Finnish locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Finnish: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | 7 | weekdays: { 8 | shorthand: ['Su', 'Ma', 'Ti', 'Ke', 'To', 'Pe', 'La'], 9 | longhand: [ 10 | 'Sunnuntai', 11 | 'Maanantai', 12 | 'Tiistai', 13 | 'Keskiviikko', 14 | 'Torstai', 15 | 'Perjantai', 16 | 'Lauantai', 17 | ], 18 | }, 19 | 20 | months: { 21 | shorthand: [ 22 | 'Tammi', 23 | 'Helmi', 24 | 'Maalis', 25 | 'Huhti', 26 | 'Touko', 27 | 'Kesä', 28 | 'Heinä', 29 | 'Elo', 30 | 'Syys', 31 | 'Loka', 32 | 'Marras', 33 | 'Joulu', 34 | ], 35 | longhand: [ 36 | 'Tammikuu', 37 | 'Helmikuu', 38 | 'Maaliskuu', 39 | 'Huhtikuu', 40 | 'Toukokuu', 41 | 'Kesäkuu', 42 | 'Heinäkuu', 43 | 'Elokuu', 44 | 'Syyskuu', 45 | 'Lokakuu', 46 | 'Marraskuu', 47 | 'Joulukuu', 48 | ], 49 | }, 50 | 51 | ordinal: () => '.', 52 | time24hr: true, 53 | }; 54 | 55 | export default Finnish; 56 | -------------------------------------------------------------------------------- /src/l10n/fo.ts: -------------------------------------------------------------------------------- 1 | /* Faroese locale for flatpickr */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Faroese: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Sun', 'Mán', 'Týs', 'Mik', 'Hós', 'Frí', 'Ley'], 7 | longhand: [ 8 | 'Sunnudagur', 9 | 'Mánadagur', 10 | 'Týsdagur', 11 | 'Mikudagur', 12 | 'Hósdagur', 13 | 'Fríggjadagur', 14 | 'Leygardagur', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Jan', 21 | 'Feb', 22 | 'Mar', 23 | 'Apr', 24 | 'Mai', 25 | 'Jun', 26 | 'Jul', 27 | 'Aug', 28 | 'Sep', 29 | 'Okt', 30 | 'Nov', 31 | 'Des', 32 | ], 33 | longhand: [ 34 | 'Januar', 35 | 'Februar', 36 | 'Mars', 37 | 'Apríl', 38 | 'Mai', 39 | 'Juni', 40 | 'Juli', 41 | 'August', 42 | 'Septembur', 43 | 'Oktobur', 44 | 'Novembur', 45 | 'Desembur', 46 | ], 47 | }, 48 | 49 | ordinal: () => '.', 50 | 51 | firstDayOfWeek: 1, 52 | rangeSeparator: ' til ', 53 | weekAbbreviation: 'vika', 54 | yearAriaLabel: 'Ár', 55 | time24hr: true, 56 | }; 57 | 58 | export default Faroese; 59 | -------------------------------------------------------------------------------- /src/l10n/fr.ts: -------------------------------------------------------------------------------- 1 | /* French locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const French: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | 7 | weekdays: { 8 | shorthand: ['dim', 'lun', 'mar', 'mer', 'jeu', 'ven', 'sam'], 9 | longhand: [ 10 | 'dimanche', 11 | 'lundi', 12 | 'mardi', 13 | 'mercredi', 14 | 'jeudi', 15 | 'vendredi', 16 | 'samedi', 17 | ], 18 | }, 19 | 20 | months: { 21 | shorthand: [ 22 | 'janv', 23 | 'févr', 24 | 'mars', 25 | 'avr', 26 | 'mai', 27 | 'juin', 28 | 'juil', 29 | 'août', 30 | 'sept', 31 | 'oct', 32 | 'nov', 33 | 'déc', 34 | ], 35 | longhand: [ 36 | 'janvier', 37 | 'février', 38 | 'mars', 39 | 'avril', 40 | 'mai', 41 | 'juin', 42 | 'juillet', 43 | 'août', 44 | 'septembre', 45 | 'octobre', 46 | 'novembre', 47 | 'décembre', 48 | ], 49 | }, 50 | 51 | ordinal: (nth) => { 52 | if (nth > 1) return ''; 53 | 54 | return 'er'; 55 | }, 56 | rangeSeparator: ' au ', 57 | weekAbbreviation: 'Sem', 58 | time24hr: true, 59 | }; 60 | 61 | export default French; 62 | -------------------------------------------------------------------------------- /src/l10n/ga.ts: -------------------------------------------------------------------------------- 1 | /* Gaelic Irish locale for flatpickr */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Irish: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | 7 | weekdays: { 8 | shorthand: ['Dom', 'Lua', 'Mái', 'Céa', 'Déa', 'Aoi', 'Sat'], 9 | longhand: [ 10 | 'Dé Domhnaigh', 11 | 'Dé Luain', 12 | 'Dé Máirt', 13 | 'Dé Céadaoin', 14 | 'Déardaoin', 15 | 'Dé hAoine', 16 | 'Dé Sathairn', 17 | ], 18 | }, 19 | 20 | months: { 21 | shorthand: [ 22 | 'Ean', 23 | 'Fea', 24 | 'Már', 25 | 'Aib', 26 | 'Bea', 27 | 'Mei', 28 | 'Iúi', 29 | 'Lún', 30 | 'MFo', 31 | 'DFo', 32 | 'Sam', 33 | 'Nol', 34 | ], 35 | longhand: [ 36 | 'Eanáir', 37 | 'Feabhra', 38 | 'Márta', 39 | 'Aibreán', 40 | 'Bealtaine', 41 | 'Meitheamh', 42 | 'Iúil', 43 | 'Lúnasa', 44 | 'Meán Fómhair', 45 | 'Deireadh Fómhair', 46 | 'Samhain', 47 | 'Nollaig', 48 | ], 49 | }, 50 | time24hr: true, 51 | }; 52 | 53 | export default Irish; 54 | -------------------------------------------------------------------------------- /src/l10n/gr.ts: -------------------------------------------------------------------------------- 1 | /* Greek locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Greek: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Κυ', 'Δε', 'Τρ', 'Τε', 'Πέ', 'Πα', 'Σά'], 7 | longhand: [ 8 | 'Κυριακή', 9 | 'Δευτέρα', 10 | 'Τρίτη', 11 | 'Τετάρτη', 12 | 'Πέμπτη', 13 | 'Παρασκευή', 14 | 'Σάββατο', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Ιαν', 21 | 'Φεβ', 22 | 'Μάρ', 23 | 'Απρ', 24 | 'Μάι', 25 | 'Ιού', 26 | 'Ιού', 27 | 'Αύγ', 28 | 'Σεπ', 29 | 'Οκτ', 30 | 'Νοέ', 31 | 'Δεκ', 32 | ], 33 | longhand: [ 34 | 'Ιανουάριος', 35 | 'Φεβρουάριος', 36 | 'Μάρτιος', 37 | 'Απρίλιος', 38 | 'Μάιος', 39 | 'Ιούνιος', 40 | 'Ιούλιος', 41 | 'Αύγουστος', 42 | 'Σεπτέμβριος', 43 | 'Οκτώβριος', 44 | 'Νοέμβριος', 45 | 'Δεκέμβριος', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | 51 | ordinal() { 52 | return ''; 53 | }, 54 | 55 | weekAbbreviation: 'Εβδ', 56 | rangeSeparator: ' έως ', 57 | 58 | amPM: ['ΠΜ', 'ΜΜ'], 59 | }; 60 | 61 | export default Greek; 62 | -------------------------------------------------------------------------------- /src/l10n/he.ts: -------------------------------------------------------------------------------- 1 | /* Hebrew locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Hebrew: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ש'], 7 | longhand: ['ראשון', 'שני', 'שלישי', 'רביעי', 'חמישי', 'שישי', 'שבת'], 8 | }, 9 | 10 | months: { 11 | shorthand: [ 12 | 'ינו׳', 13 | 'פבר׳', 14 | 'מרץ', 15 | 'אפר׳', 16 | 'מאי', 17 | 'יוני', 18 | 'יולי', 19 | 'אוג׳', 20 | 'ספט׳', 21 | 'אוק׳', 22 | 'נוב׳', 23 | 'דצמ׳', 24 | ], 25 | longhand: [ 26 | 'ינואר', 27 | 'פברואר', 28 | 'מרץ', 29 | 'אפריל', 30 | 'מאי', 31 | 'יוני', 32 | 'יולי', 33 | 'אוגוסט', 34 | 'ספטמבר', 35 | 'אוקטובר', 36 | 'נובמבר', 37 | 'דצמבר', 38 | ], 39 | }, 40 | rangeSeparator: ' אל ', 41 | time24hr: true, 42 | }; 43 | 44 | export default Hebrew; 45 | -------------------------------------------------------------------------------- /src/l10n/hi.ts: -------------------------------------------------------------------------------- 1 | /* Hindi locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Hindi: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'], 7 | longhand: [ 8 | 'रविवार', 9 | 'सोमवार', 10 | 'मंगलवार', 11 | 'बुधवार', 12 | 'गुरुवार', 13 | 'शुक्रवार', 14 | 'शनिवार', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'जन', 21 | 'फर', 22 | 'मार्च', 23 | 'अप्रेल', 24 | 'मई', 25 | 'जून', 26 | 'जूलाई', 27 | 'अग', 28 | 'सित', 29 | 'अक्ट', 30 | 'नव', 31 | 'दि', 32 | ], 33 | longhand: [ 34 | 'जनवरी ', 35 | 'फरवरी', 36 | 'मार्च', 37 | 'अप्रेल', 38 | 'मई', 39 | 'जून', 40 | 'जूलाई', 41 | 'अगस्त ', 42 | 'सितम्बर', 43 | 'अक्टूबर', 44 | 'नवम्बर', 45 | 'दिसम्बर', 46 | ], 47 | }, 48 | }; 49 | 50 | export default Hindi; 51 | -------------------------------------------------------------------------------- /src/l10n/hr.ts: -------------------------------------------------------------------------------- 1 | /* Croatian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Croatian: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | 7 | weekdays: { 8 | shorthand: ['Ned', 'Pon', 'Uto', 'Sri', 'Čet', 'Pet', 'Sub'], 9 | longhand: [ 10 | 'Nedjelja', 11 | 'Ponedjeljak', 12 | 'Utorak', 13 | 'Srijeda', 14 | 'Četvrtak', 15 | 'Petak', 16 | 'Subota', 17 | ], 18 | }, 19 | 20 | months: { 21 | shorthand: [ 22 | 'Sij', 23 | 'Velj', 24 | 'Ožu', 25 | 'Tra', 26 | 'Svi', 27 | 'Lip', 28 | 'Srp', 29 | 'Kol', 30 | 'Ruj', 31 | 'Lis', 32 | 'Stu', 33 | 'Pro', 34 | ], 35 | longhand: [ 36 | 'Siječanj', 37 | 'Veljača', 38 | 'Ožujak', 39 | 'Travanj', 40 | 'Svibanj', 41 | 'Lipanj', 42 | 'Srpanj', 43 | 'Kolovoz', 44 | 'Rujan', 45 | 'Listopad', 46 | 'Studeni', 47 | 'Prosinac', 48 | ], 49 | }, 50 | time24hr: true, 51 | }; 52 | 53 | export default Croatian; 54 | -------------------------------------------------------------------------------- /src/l10n/hu.ts: -------------------------------------------------------------------------------- 1 | /* Hungarian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Hungarian: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | 7 | weekdays: { 8 | shorthand: ['V', 'H', 'K', 'Sz', 'Cs', 'P', 'Szo'], 9 | longhand: [ 10 | 'Vasárnap', 11 | 'Hétfő', 12 | 'Kedd', 13 | 'Szerda', 14 | 'Csütörtök', 15 | 'Péntek', 16 | 'Szombat', 17 | ], 18 | }, 19 | 20 | months: { 21 | shorthand: [ 22 | 'Jan', 23 | 'Feb', 24 | 'Már', 25 | 'Ápr', 26 | 'Máj', 27 | 'Jún', 28 | 'Júl', 29 | 'Aug', 30 | 'Szep', 31 | 'Okt', 32 | 'Nov', 33 | 'Dec', 34 | ], 35 | longhand: [ 36 | 'Január', 37 | 'Február', 38 | 'Március', 39 | 'Április', 40 | 'Május', 41 | 'Június', 42 | 'Július', 43 | 'Augusztus', 44 | 'Szeptember', 45 | 'Október', 46 | 'November', 47 | 'December', 48 | ], 49 | }, 50 | 51 | ordinal() { 52 | return '.'; 53 | }, 54 | 55 | weekAbbreviation: 'Hét', 56 | rangeSeparator: ' - ', 57 | time24hr: true, 58 | }; 59 | 60 | export default Hungarian; 61 | -------------------------------------------------------------------------------- /src/l10n/id.ts: -------------------------------------------------------------------------------- 1 | /* Indonesian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Indonesian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'], 7 | longhand: ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'], 8 | }, 9 | 10 | months: { 11 | shorthand: [ 12 | 'Jan', 13 | 'Feb', 14 | 'Mar', 15 | 'Apr', 16 | 'Mei', 17 | 'Jun', 18 | 'Jul', 19 | 'Agu', 20 | 'Sep', 21 | 'Okt', 22 | 'Nov', 23 | 'Des', 24 | ], 25 | longhand: [ 26 | 'Januari', 27 | 'Februari', 28 | 'Maret', 29 | 'April', 30 | 'Mei', 31 | 'Juni', 32 | 'Juli', 33 | 'Agustus', 34 | 'September', 35 | 'Oktober', 36 | 'November', 37 | 'Desember', 38 | ], 39 | }, 40 | 41 | firstDayOfWeek: 1, 42 | 43 | ordinal: () => '', 44 | time24hr: true, 45 | rangeSeparator: ' - ', 46 | }; 47 | 48 | export default Indonesian; 49 | -------------------------------------------------------------------------------- /src/l10n/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable camelcase */ 2 | import { LocaleName, CustomLocale } from '../types/locale'; 3 | 4 | import { Arabic as ar } from './ar'; 5 | import { Austria as at } from './at'; 6 | import { Azerbaijan as az } from './az'; 7 | import { Belarusian as be } from './be'; 8 | import { Bosnian as bs } from './bs'; 9 | import { Bulgarian as bg } from './bg'; 10 | import { Bangla as bn } from './bn'; 11 | import { Catalan as cat } from './cat'; 12 | import { Czech as cs } from './cs'; 13 | import { Welsh as cy } from './cy'; 14 | import { Danish as da } from './da'; 15 | import { German as de } from './de'; 16 | import { English as en } from './default'; 17 | import { Esperanto as eo } from './eo'; 18 | import { Spanish as es } from './es'; 19 | import { Estonian as et } from './et'; 20 | import { Persian as fa } from './fa'; 21 | import { Finnish as fi } from './fi'; 22 | import { Faroese as fo } from './fo'; 23 | import { French as fr } from './fr'; 24 | import { Greek as gr } from './gr'; 25 | import { Hebrew as he } from './he'; 26 | import { Hindi as hi } from './hi'; 27 | import { Croatian as hr } from './hr'; 28 | import { Hungarian as hu } from './hu'; 29 | import { Indonesian as id } from './id'; 30 | import { Icelandic as is } from './is'; 31 | import { Italian as it } from './it'; 32 | import { Japanese as ja } from './ja'; 33 | import { Georgian as ka } from './ka'; 34 | import { Korean as ko } from './ko'; 35 | import { Khmer as km } from './km'; 36 | import { Kazakh as kz } from './kz'; 37 | import { Lithuanian as lt } from './lt'; 38 | import { Latvian as lv } from './lv'; 39 | import { Macedonian as mk } from './mk'; 40 | import { Mongolian as mn } from './mn'; 41 | import { Malaysian as ms } from './ms'; 42 | import { Burmese as my } from './my'; 43 | import { Dutch as nl } from './nl'; 44 | import { Norwegian as no } from './no'; 45 | import { Punjabi as pa } from './pa'; 46 | import { Polish as pl } from './pl'; 47 | import { Portuguese as pt } from './pt'; 48 | import { Romanian as ro } from './ro'; 49 | import { Russian as ru } from './ru'; 50 | import { Sinhala as si } from './si'; 51 | import { Slovak as sk } from './sk'; 52 | import { Slovenian as sl } from './sl'; 53 | import { Albanian as sq } from './sq'; 54 | import { Serbian as sr } from './sr'; 55 | import { Swedish as sv } from './sv'; 56 | import { Thai as th } from './th'; 57 | import { Turkish as tr } from './tr'; 58 | import { Ukrainian as uk } from './uk'; 59 | import { Uzbek as uz } from './uz'; 60 | import { UzbekLatin as uzLatn } from './uz_latn'; 61 | import { Vietnamese as vn } from './vn'; 62 | import { Mandarin as zh } from './zh'; 63 | import { MandarinTraditional as zh_tw } from './zh-tw'; 64 | 65 | const l10n: Record = { 66 | ar, 67 | at, 68 | az, 69 | be, 70 | bg, 71 | bn, 72 | bs, 73 | ca: cat, 74 | cat, 75 | cs, 76 | cy, 77 | da, 78 | de, 79 | default: { ...en }, 80 | en, 81 | eo, 82 | es, 83 | et, 84 | fa, 85 | fi, 86 | fo, 87 | fr, 88 | gr, 89 | he, 90 | hi, 91 | hr, 92 | hu, 93 | id, 94 | is, 95 | it, 96 | ja, 97 | ka, 98 | ko, 99 | km, 100 | kz, 101 | lt, 102 | lv, 103 | mk, 104 | mn, 105 | ms, 106 | my, 107 | nl, 108 | no, 109 | pa, 110 | pl, 111 | pt, 112 | ro, 113 | ru, 114 | si, 115 | sk, 116 | sl, 117 | sq, 118 | sr, 119 | sv, 120 | th, 121 | tr, 122 | uk, 123 | vn, 124 | zh, 125 | zh_tw, 126 | uz, 127 | uz_latn: uzLatn, 128 | }; 129 | 130 | export default l10n; 131 | -------------------------------------------------------------------------------- /src/l10n/is.ts: -------------------------------------------------------------------------------- 1 | /* Icelandic locale for flatpickr */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | 5 | export const Icelandic: CustomLocale = { 6 | weekdays: { 7 | shorthand: ['Sun', 'Mán', 'Þri', 'Mið', 'Fim', 'Fös', 'Lau'], 8 | longhand: [ 9 | 'Sunnudagur', 10 | 'Mánudagur', 11 | 'Þriðjudagur', 12 | 'Miðvikudagur', 13 | 'Fimmtudagur', 14 | 'Föstudagur', 15 | 'Laugardagur', 16 | ], 17 | }, 18 | 19 | months: { 20 | shorthand: [ 21 | 'Jan', 22 | 'Feb', 23 | 'Mar', 24 | 'Apr', 25 | 'Maí', 26 | 'Jún', 27 | 'Júl', 28 | 'Ágú', 29 | 'Sep', 30 | 'Okt', 31 | 'Nóv', 32 | 'Des', 33 | ], 34 | longhand: [ 35 | 'Janúar', 36 | 'Febrúar', 37 | 'Mars', 38 | 'Apríl', 39 | 'Maí', 40 | 'Júní', 41 | 'Júlí', 42 | 'Ágúst', 43 | 'September', 44 | 'Október', 45 | 'Nóvember', 46 | 'Desember', 47 | ], 48 | }, 49 | 50 | ordinal: () => '.', 51 | 52 | firstDayOfWeek: 1, 53 | rangeSeparator: ' til ', 54 | weekAbbreviation: 'vika', 55 | yearAriaLabel: 'Ár', 56 | time24hr: true, 57 | }; 58 | 59 | export default Icelandic; 60 | -------------------------------------------------------------------------------- /src/l10n/it.ts: -------------------------------------------------------------------------------- 1 | /* Italian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Italian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'], 7 | longhand: [ 8 | 'Domenica', 9 | 'Lunedì', 10 | 'Martedì', 11 | 'Mercoledì', 12 | 'Giovedì', 13 | 'Venerdì', 14 | 'Sabato', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Gen', 21 | 'Feb', 22 | 'Mar', 23 | 'Apr', 24 | 'Mag', 25 | 'Giu', 26 | 'Lug', 27 | 'Ago', 28 | 'Set', 29 | 'Ott', 30 | 'Nov', 31 | 'Dic', 32 | ], 33 | longhand: [ 34 | 'Gennaio', 35 | 'Febbraio', 36 | 'Marzo', 37 | 'Aprile', 38 | 'Maggio', 39 | 'Giugno', 40 | 'Luglio', 41 | 'Agosto', 42 | 'Settembre', 43 | 'Ottobre', 44 | 'Novembre', 45 | 'Dicembre', 46 | ], 47 | }, 48 | firstDayOfWeek: 1, 49 | ordinal: () => '°', 50 | rangeSeparator: ' al ', 51 | weekAbbreviation: 'Se', 52 | time24hr: true, 53 | }; 54 | 55 | export default Italian; 56 | -------------------------------------------------------------------------------- /src/l10n/ja.ts: -------------------------------------------------------------------------------- 1 | /* Japanese locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Japanese: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['日', '月', '火', '水', '木', '金', '土'], 7 | longhand: [ 8 | '日曜日', 9 | '月曜日', 10 | '火曜日', 11 | '水曜日', 12 | '木曜日', 13 | '金曜日', 14 | '土曜日', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | '1月', 21 | '2月', 22 | '3月', 23 | '4月', 24 | '5月', 25 | '6月', 26 | '7月', 27 | '8月', 28 | '9月', 29 | '10月', 30 | '11月', 31 | '12月', 32 | ], 33 | longhand: [ 34 | '1月', 35 | '2月', 36 | '3月', 37 | '4月', 38 | '5月', 39 | '6月', 40 | '7月', 41 | '8月', 42 | '9月', 43 | '10月', 44 | '11月', 45 | '12月', 46 | ], 47 | }, 48 | time24hr: true, 49 | rangeSeparator: ' から ', 50 | firstDayOfWeek: 1, 51 | }; 52 | 53 | export default Japanese; 54 | -------------------------------------------------------------------------------- /src/l10n/ka.ts: -------------------------------------------------------------------------------- 1 | /* Georgian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Georgian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['კვ', 'ორ', 'სა', 'ოთ', 'ხუ', 'პა', 'შა'], 7 | longhand: [ 8 | 'კვირა', 9 | 'ორშაბათი', 10 | 'სამშაბათი', 11 | 'ოთხშაბათი', 12 | 'ხუთშაბათი', 13 | 'პარასკევი', 14 | 'შაბათი', 15 | ], 16 | }, 17 | months: { 18 | shorthand: [ 19 | 'იან', 20 | 'თებ', 21 | 'მარ', 22 | 'აპრ', 23 | 'მაი', 24 | 'ივნ', 25 | 'ივლ', 26 | 'აგვ', 27 | 'სექ', 28 | 'ოქტ', 29 | 'ნოე', 30 | 'დეკ', 31 | ], 32 | longhand: [ 33 | 'იანვარი', 34 | 'თებერვალი', 35 | 'მარტი', 36 | 'აპრილი', 37 | 'მაისი', 38 | 'ივნისი', 39 | 'ივლისი', 40 | 'აგვისტო', 41 | 'სექტემბერი', 42 | 'ოქტომბერი', 43 | 'ნოემბერი', 44 | 'დეკემბერი', 45 | ], 46 | }, 47 | firstDayOfWeek: 1, 48 | ordinal() { 49 | return ''; 50 | }, 51 | rangeSeparator: ' — ', 52 | weekAbbreviation: 'კვ.', 53 | amPM: ['AM', 'PM'], 54 | yearAriaLabel: 'წელი', 55 | time24hr: true, 56 | }; 57 | 58 | export default Georgian; 59 | -------------------------------------------------------------------------------- /src/l10n/km.ts: -------------------------------------------------------------------------------- 1 | /* Khmer locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Khmer: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['អាទិត្យ', 'ចន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស.', 'សុក្រ', 'សៅរ៍'], 7 | longhand: [ 8 | 'អាទិត្យ', 9 | 'ចន្ទ', 10 | 'អង្គារ', 11 | 'ពុធ', 12 | 'ព្រហស្បតិ៍', 13 | 'សុក្រ', 14 | 'សៅរ៍', 15 | ], 16 | }, 17 | months: { 18 | shorthand: [ 19 | 'មករា', 20 | 'កុម្ភះ', 21 | 'មីនា', 22 | 'មេសា', 23 | 'ឧសភា', 24 | 'មិថុនា', 25 | 'កក្កដា', 26 | 'សីហា', 27 | 'កញ្ញា', 28 | 'តុលា', 29 | 'វិច្ឆិកា', 30 | 'ធ្នូ', 31 | ], 32 | longhand: [ 33 | 'មករា', 34 | 'កុម្ភះ', 35 | 'មីនា', 36 | 'មេសា', 37 | 'ឧសភា', 38 | 'មិថុនា', 39 | 'កក្កដា', 40 | 'សីហា', 41 | 'កញ្ញា', 42 | 'តុលា', 43 | 'វិច្ឆិកា', 44 | 'ធ្នូ', 45 | ], 46 | }, 47 | ordinal: () => '', 48 | firstDayOfWeek: 1, 49 | rangeSeparator: ' ដល់ ', 50 | weekAbbreviation: 'សប្តាហ៍', 51 | yearAriaLabel: 'ឆ្នាំ', 52 | time24hr: true, 53 | }; 54 | 55 | export default Khmer; 56 | -------------------------------------------------------------------------------- /src/l10n/ko.ts: -------------------------------------------------------------------------------- 1 | /* Republic of Korea locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Korean: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['일', '월', '화', '수', '목', '금', '토'], 7 | longhand: [ 8 | '일요일', 9 | '월요일', 10 | '화요일', 11 | '수요일', 12 | '목요일', 13 | '금요일', 14 | '토요일', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | '1월', 21 | '2월', 22 | '3월', 23 | '4월', 24 | '5월', 25 | '6월', 26 | '7월', 27 | '8월', 28 | '9월', 29 | '10월', 30 | '11월', 31 | '12월', 32 | ], 33 | longhand: [ 34 | '1월', 35 | '2월', 36 | '3월', 37 | '4월', 38 | '5월', 39 | '6월', 40 | '7월', 41 | '8월', 42 | '9월', 43 | '10월', 44 | '11월', 45 | '12월', 46 | ], 47 | }, 48 | 49 | ordinal: () => '일', 50 | 51 | rangeSeparator: ' ~ ', 52 | }; 53 | 54 | export default Korean; 55 | -------------------------------------------------------------------------------- /src/l10n/kz.ts: -------------------------------------------------------------------------------- 1 | /* Kazakh locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Kazakh: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Жс', 'Дс', 'Сc', 'Ср', 'Бс', 'Жм', 'Сб'], 7 | longhand: [ 8 | 'Жексенбi', 9 | 'Дүйсенбi', 10 | 'Сейсенбi', 11 | 'Сәрсенбi', 12 | 'Бейсенбi', 13 | 'Жұма', 14 | 'Сенбi', 15 | ], 16 | }, 17 | months: { 18 | shorthand: [ 19 | 'Қаң', 20 | 'Ақп', 21 | 'Нау', 22 | 'Сәу', 23 | 'Мам', 24 | 'Мау', 25 | 'Шiл', 26 | 'Там', 27 | 'Қыр', 28 | 'Қаз', 29 | 'Қар', 30 | 'Жел', 31 | ], 32 | longhand: [ 33 | 'Қаңтар', 34 | 'Ақпан', 35 | 'Наурыз', 36 | 'Сәуiр', 37 | 'Мамыр', 38 | 'Маусым', 39 | 'Шiлде', 40 | 'Тамыз', 41 | 'Қыркүйек', 42 | 'Қазан', 43 | 'Қараша', 44 | 'Желтоқсан', 45 | ], 46 | }, 47 | firstDayOfWeek: 1, 48 | ordinal() { 49 | return ''; 50 | }, 51 | rangeSeparator: ' — ', 52 | weekAbbreviation: 'Апта', 53 | amPM: ['ТД', 'ТК'], 54 | yearAriaLabel: 'Жыл', 55 | }; 56 | 57 | export default Kazakh; 58 | -------------------------------------------------------------------------------- /src/l10n/lt.ts: -------------------------------------------------------------------------------- 1 | /* Lithuanian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Lithuanian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['S', 'Pr', 'A', 'T', 'K', 'Pn', 'Š'], 7 | longhand: [ 8 | 'Sekmadienis', 9 | 'Pirmadienis', 10 | 'Antradienis', 11 | 'Trečiadienis', 12 | 'Ketvirtadienis', 13 | 'Penktadienis', 14 | 'Šeštadienis', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Sau', 21 | 'Vas', 22 | 'Kov', 23 | 'Bal', 24 | 'Geg', 25 | 'Bir', 26 | 'Lie', 27 | 'Rgp', 28 | 'Rgs', 29 | 'Spl', 30 | 'Lap', 31 | 'Grd', 32 | ], 33 | longhand: [ 34 | 'Sausis', 35 | 'Vasaris', 36 | 'Kovas', 37 | 'Balandis', 38 | 'Gegužė', 39 | 'Birželis', 40 | 'Liepa', 41 | 'Rugpjūtis', 42 | 'Rugsėjis', 43 | 'Spalis', 44 | 'Lapkritis', 45 | 'Gruodis', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | 51 | ordinal() { 52 | return '-a'; 53 | }, 54 | rangeSeparator: ' iki ', 55 | weekAbbreviation: 'Sav', 56 | time24hr: true, 57 | }; 58 | 59 | export default Lithuanian; 60 | -------------------------------------------------------------------------------- /src/l10n/lv.ts: -------------------------------------------------------------------------------- 1 | /* Latvian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Latvian: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | 7 | weekdays: { 8 | shorthand: ['Sv', 'Pr', 'Ot', 'Tr', 'Ce', 'Pk', 'Se'], 9 | longhand: [ 10 | 'Svētdiena', 11 | 'Pirmdiena', 12 | 'Otrdiena', 13 | 'Trešdiena', 14 | 'Ceturtdiena', 15 | 'Piektdiena', 16 | 'Sestdiena', 17 | ], 18 | }, 19 | 20 | months: { 21 | shorthand: [ 22 | 'Jan', 23 | 'Feb', 24 | 'Mar', 25 | 'Apr', 26 | 'Mai', 27 | 'Jūn', 28 | 'Jūl', 29 | 'Aug', 30 | 'Sep', 31 | 'Okt', 32 | 'Nov', 33 | 'Dec', 34 | ], 35 | longhand: [ 36 | 'Janvāris', 37 | 'Februāris', 38 | 'Marts', 39 | 'Aprīlis', 40 | 'Maijs', 41 | 'Jūnijs', 42 | 'Jūlijs', 43 | 'Augusts', 44 | 'Septembris', 45 | 'Oktobris', 46 | 'Novembris', 47 | 'Decembris', 48 | ], 49 | }, 50 | 51 | rangeSeparator: ' līdz ', 52 | time24hr: true, 53 | }; 54 | 55 | export default Latvian; 56 | -------------------------------------------------------------------------------- /src/l10n/mk.ts: -------------------------------------------------------------------------------- 1 | /* Macedonian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Macedonian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Не', 'По', 'Вт', 'Ср', 'Че', 'Пе', 'Са'], 7 | longhand: [ 8 | 'Недела', 9 | 'Понеделник', 10 | 'Вторник', 11 | 'Среда', 12 | 'Четврток', 13 | 'Петок', 14 | 'Сабота', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Јан', 21 | 'Фев', 22 | 'Мар', 23 | 'Апр', 24 | 'Мај', 25 | 'Јун', 26 | 'Јул', 27 | 'Авг', 28 | 'Сеп', 29 | 'Окт', 30 | 'Ное', 31 | 'Дек', 32 | ], 33 | longhand: [ 34 | 'Јануари', 35 | 'Февруари', 36 | 'Март', 37 | 'Април', 38 | 'Мај', 39 | 'Јуни', 40 | 'Јули', 41 | 'Август', 42 | 'Септември', 43 | 'Октомври', 44 | 'Ноември', 45 | 'Декември', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | weekAbbreviation: 'Нед.', 51 | rangeSeparator: ' до ', 52 | time24hr: true, 53 | }; 54 | 55 | export default Macedonian; 56 | -------------------------------------------------------------------------------- /src/l10n/mn.ts: -------------------------------------------------------------------------------- 1 | /* Mongolian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Mongolian: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | weekdays: { 7 | shorthand: ['Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя', 'Ня'], 8 | longhand: ['Даваа', 'Мягмар', 'Лхагва', 'Пүрэв', 'Баасан', 'Бямба', 'Ням'], 9 | }, 10 | 11 | months: { 12 | shorthand: [ 13 | '1-р сар', 14 | '2-р сар', 15 | '3-р сар', 16 | '4-р сар', 17 | '5-р сар', 18 | '6-р сар', 19 | '7-р сар', 20 | '8-р сар', 21 | '9-р сар', 22 | '10-р сар', 23 | '11-р сар', 24 | '12-р сар', 25 | ], 26 | longhand: [ 27 | 'Нэгдүгээр сар', 28 | 'Хоёрдугаар сар', 29 | 'Гуравдугаар сар', 30 | 'Дөрөвдүгээр сар', 31 | 'Тавдугаар сар', 32 | 'Зургаадугаар сар', 33 | 'Долдугаар сар', 34 | 'Наймдугаар сар', 35 | 'Есдүгээр сар', 36 | 'Аравдугаар сар', 37 | 'Арваннэгдүгээр сар', 38 | 'Арванхоёрдугаар сар', 39 | ], 40 | }, 41 | rangeSeparator: '-с ', 42 | time24hr: true, 43 | }; 44 | 45 | export default Mongolian; 46 | -------------------------------------------------------------------------------- /src/l10n/ms.ts: -------------------------------------------------------------------------------- 1 | /* Malaysian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Malaysian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Min', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'], 7 | longhand: [ 8 | 'Minggu', 9 | 'Isnin', 10 | 'Selasa', 11 | 'Rabu', 12 | 'Khamis', 13 | 'Jumaat', 14 | 'Sabtu', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Jan', 21 | 'Feb', 22 | 'Mac', 23 | 'Apr', 24 | 'Mei', 25 | 'Jun', 26 | 'Jul', 27 | 'Ogo', 28 | 'Sep', 29 | 'Okt', 30 | 'Nov', 31 | 'Dis', 32 | ], 33 | longhand: [ 34 | 'Januari', 35 | 'Februari', 36 | 'Mac', 37 | 'April', 38 | 'Mei', 39 | 'Jun', 40 | 'Julai', 41 | 'Ogos', 42 | 'September', 43 | 'Oktober', 44 | 'November', 45 | 'Disember', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | 51 | ordinal: () => '', 52 | }; 53 | 54 | 55 | export default Malaysian; 56 | -------------------------------------------------------------------------------- /src/l10n/my.ts: -------------------------------------------------------------------------------- 1 | /* Burmese locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Burmese: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['နွေ', 'လာ', 'ဂါ', 'ဟူး', 'ကြာ', 'သော', 'နေ'], 7 | longhand: [ 8 | 'တနင်္ဂနွေ', 9 | 'တနင်္လာ', 10 | 'အင်္ဂါ', 11 | 'ဗုဒ္ဓဟူး', 12 | 'ကြာသပတေး', 13 | 'သောကြာ', 14 | 'စနေ', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'ဇန်', 21 | 'ဖေ', 22 | 'မတ်', 23 | 'ပြီ', 24 | 'မေ', 25 | 'ဇွန်', 26 | 'လိုင်', 27 | 'သြ', 28 | 'စက်', 29 | 'အောက်', 30 | 'နို', 31 | 'ဒီ', 32 | ], 33 | longhand: [ 34 | 'ဇန်နဝါရီ', 35 | 'ဖေဖော်ဝါရီ', 36 | 'မတ်', 37 | 'ဧပြီ', 38 | 'မေ', 39 | 'ဇွန်', 40 | 'ဇူလိုင်', 41 | 'သြဂုတ်', 42 | 'စက်တင်ဘာ', 43 | 'အောက်တိုဘာ', 44 | 'နိုဝင်ဘာ', 45 | 'ဒီဇင်ဘာ', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | 51 | ordinal: () => '', 52 | time24hr: true, 53 | }; 54 | 55 | export default Burmese; 56 | -------------------------------------------------------------------------------- /src/l10n/nl.ts: -------------------------------------------------------------------------------- 1 | /* Dutch locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Dutch: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'], 7 | longhand: [ 8 | 'zondag', 9 | 'maandag', 10 | 'dinsdag', 11 | 'woensdag', 12 | 'donderdag', 13 | 'vrijdag', 14 | 'zaterdag', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'jan', 21 | 'feb', 22 | 'mrt', 23 | 'apr', 24 | 'mei', 25 | 'jun', 26 | 'jul', 27 | 'aug', 28 | 'sept', 29 | 'okt', 30 | 'nov', 31 | 'dec', 32 | ], 33 | longhand: [ 34 | 'januari', 35 | 'februari', 36 | 'maart', 37 | 'april', 38 | 'mei', 39 | 'juni', 40 | 'juli', 41 | 'augustus', 42 | 'september', 43 | 'oktober', 44 | 'november', 45 | 'december', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | weekAbbreviation: 'wk', 51 | rangeSeparator: ' t/m ', 52 | time24hr: true, 53 | 54 | ordinal: (nth) => { 55 | if (nth === 1 || nth === 8 || nth >= 20) return 'ste'; 56 | 57 | return 'de'; 58 | }, 59 | }; 60 | 61 | export default Dutch; 62 | -------------------------------------------------------------------------------- /src/l10n/no.ts: -------------------------------------------------------------------------------- 1 | /* Norwegian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | 5 | export const Norwegian: CustomLocale = { 6 | weekdays: { 7 | shorthand: ['Søn', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'Lør'], 8 | longhand: [ 9 | 'Søndag', 10 | 'Mandag', 11 | 'Tirsdag', 12 | 'Onsdag', 13 | 'Torsdag', 14 | 'Fredag', 15 | 'Lørdag', 16 | ], 17 | }, 18 | 19 | months: { 20 | shorthand: [ 21 | 'Jan', 22 | 'Feb', 23 | 'Mar', 24 | 'Apr', 25 | 'Mai', 26 | 'Jun', 27 | 'Jul', 28 | 'Aug', 29 | 'Sep', 30 | 'Okt', 31 | 'Nov', 32 | 'Des', 33 | ], 34 | longhand: [ 35 | 'Januar', 36 | 'Februar', 37 | 'Mars', 38 | 'April', 39 | 'Mai', 40 | 'Juni', 41 | 'Juli', 42 | 'August', 43 | 'September', 44 | 'Oktober', 45 | 'November', 46 | 'Desember', 47 | ], 48 | }, 49 | 50 | firstDayOfWeek: 1, 51 | rangeSeparator: ' til ', 52 | weekAbbreviation: 'Uke', 53 | time24hr: true, 54 | 55 | ordinal: () => '.', 56 | }; 57 | 58 | export default Norwegian; 59 | -------------------------------------------------------------------------------- /src/l10n/pa.ts: -------------------------------------------------------------------------------- 1 | /* Punjabi locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | 5 | export const Punjabi: CustomLocale = { 6 | weekdays: { 7 | shorthand: ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕਰ', 'ਸ਼ਨਿੱਚਰ'], 8 | longhand: [ 9 | 'ਐਤਵਾਰ', 10 | 'ਸੋਮਵਾਰ', 11 | 'ਮੰਗਲਵਾਰ', 12 | 'ਬੁੱਧਵਾਰ', 13 | 'ਵੀਰਵਾਰ', 14 | 'ਸ਼ੁੱਕਰਵਾਰ', 15 | 'ਸ਼ਨਿੱਚਰਵਾਰ', 16 | ], 17 | }, 18 | 19 | months: { 20 | shorthand: [ 21 | 'ਜਨ', 22 | 'ਫ਼ਰ', 23 | 'ਮਾਰ', 24 | 'ਅਪ੍ਰੈ', 25 | 'ਮਈ', 26 | 'ਜੂਨ', 27 | 'ਜੁਲਾ', 28 | 'ਅਗ', 29 | 'ਸਤੰ', 30 | 'ਅਕ', 31 | 'ਨਵੰ', 32 | 'ਦਸੰ', 33 | ], 34 | longhand: [ 35 | 'ਜਨਵਰੀ', 36 | 'ਫ਼ਰਵਰੀ', 37 | 'ਮਾਰਚ', 38 | 'ਅਪ੍ਰੈਲ', 39 | 'ਮਈ', 40 | 'ਜੂਨ', 41 | 'ਜੁਲਾਈ', 42 | 'ਅਗਸਤ', 43 | 'ਸਤੰਬਰ', 44 | 'ਅਕਤੂਬਰ', 45 | 'ਨਵੰਬਰ', 46 | 'ਦਸੰਬਰ', 47 | ], 48 | }, 49 | time24hr: true, 50 | }; 51 | 52 | export default Punjabi; 53 | -------------------------------------------------------------------------------- /src/l10n/pl.ts: -------------------------------------------------------------------------------- 1 | /* Polish locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Polish: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Nd', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'So'], 7 | longhand: [ 8 | 'Niedziela', 9 | 'Poniedziałek', 10 | 'Wtorek', 11 | 'Środa', 12 | 'Czwartek', 13 | 'Piątek', 14 | 'Sobota', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Sty', 21 | 'Lut', 22 | 'Mar', 23 | 'Kwi', 24 | 'Maj', 25 | 'Cze', 26 | 'Lip', 27 | 'Sie', 28 | 'Wrz', 29 | 'Paź', 30 | 'Lis', 31 | 'Gru', 32 | ], 33 | longhand: [ 34 | 'Styczeń', 35 | 'Luty', 36 | 'Marzec', 37 | 'Kwiecień', 38 | 'Maj', 39 | 'Czerwiec', 40 | 'Lipiec', 41 | 'Sierpień', 42 | 'Wrzesień', 43 | 'Październik', 44 | 'Listopad', 45 | 'Grudzień', 46 | ], 47 | }, 48 | rangeSeparator: ' do ', 49 | weekAbbreviation: 'tydz.', 50 | firstDayOfWeek: 1, 51 | time24hr: true, 52 | 53 | ordinal: () => '.', 54 | }; 55 | 56 | export default Polish; 57 | -------------------------------------------------------------------------------- /src/l10n/pt.ts: -------------------------------------------------------------------------------- 1 | /* Portuguese locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Portuguese: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'], 7 | longhand: [ 8 | 'Domingo', 9 | 'Segunda-feira', 10 | 'Terça-feira', 11 | 'Quarta-feira', 12 | 'Quinta-feira', 13 | 'Sexta-feira', 14 | 'Sábado', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Jan', 21 | 'Fev', 22 | 'Mar', 23 | 'Abr', 24 | 'Mai', 25 | 'Jun', 26 | 'Jul', 27 | 'Ago', 28 | 'Set', 29 | 'Out', 30 | 'Nov', 31 | 'Dez', 32 | ], 33 | longhand: [ 34 | 'Janeiro', 35 | 'Fevereiro', 36 | 'Março', 37 | 'Abril', 38 | 'Maio', 39 | 'Junho', 40 | 'Julho', 41 | 'Agosto', 42 | 'Setembro', 43 | 'Outubro', 44 | 'Novembro', 45 | 'Dezembro', 46 | ], 47 | }, 48 | 49 | rangeSeparator: ' até ', 50 | time24hr: true, 51 | }; 52 | 53 | export default Portuguese; 54 | -------------------------------------------------------------------------------- /src/l10n/ro.ts: -------------------------------------------------------------------------------- 1 | /* Romanian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Romanian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'], 7 | longhand: [ 8 | 'Duminică', 9 | 'Luni', 10 | 'Marți', 11 | 'Miercuri', 12 | 'Joi', 13 | 'Vineri', 14 | 'Sâmbătă', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Ian', 21 | 'Feb', 22 | 'Mar', 23 | 'Apr', 24 | 'Mai', 25 | 'Iun', 26 | 'Iul', 27 | 'Aug', 28 | 'Sep', 29 | 'Oct', 30 | 'Noi', 31 | 'Dec', 32 | ], 33 | longhand: [ 34 | 'Ianuarie', 35 | 'Februarie', 36 | 'Martie', 37 | 'Aprilie', 38 | 'Mai', 39 | 'Iunie', 40 | 'Iulie', 41 | 'August', 42 | 'Septembrie', 43 | 'Octombrie', 44 | 'Noiembrie', 45 | 'Decembrie', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | time24hr: true, 51 | 52 | ordinal: () => '', 53 | }; 54 | 55 | export default Romanian; 56 | -------------------------------------------------------------------------------- /src/l10n/ru.ts: -------------------------------------------------------------------------------- 1 | /* Russian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Russian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'], 7 | longhand: [ 8 | 'Воскресенье', 9 | 'Понедельник', 10 | 'Вторник', 11 | 'Среда', 12 | 'Четверг', 13 | 'Пятница', 14 | 'Суббота', 15 | ], 16 | }, 17 | months: { 18 | shorthand: [ 19 | 'Янв', 20 | 'Фев', 21 | 'Март', 22 | 'Апр', 23 | 'Май', 24 | 'Июнь', 25 | 'Июль', 26 | 'Авг', 27 | 'Сен', 28 | 'Окт', 29 | 'Ноя', 30 | 'Дек', 31 | ], 32 | longhand: [ 33 | 'Январь', 34 | 'Февраль', 35 | 'Март', 36 | 'Апрель', 37 | 'Май', 38 | 'Июнь', 39 | 'Июль', 40 | 'Август', 41 | 'Сентябрь', 42 | 'Октябрь', 43 | 'Ноябрь', 44 | 'Декабрь', 45 | ], 46 | }, 47 | firstDayOfWeek: 1, 48 | ordinal() { 49 | return ''; 50 | }, 51 | rangeSeparator: ' — ', 52 | weekAbbreviation: 'Нед.', 53 | amPM: ['ДП', 'ПП'], 54 | yearAriaLabel: 'Год', 55 | time24hr: true, 56 | }; 57 | 58 | export default Russian; 59 | -------------------------------------------------------------------------------- /src/l10n/si.ts: -------------------------------------------------------------------------------- 1 | /* Sinhala locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Sinhala: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['ඉ', 'ස', 'අ', 'බ', 'බ්‍ර', 'සි', 'සෙ'], 7 | longhand: [ 8 | 'ඉරිදා', 9 | 'සඳුදා', 10 | 'අඟහරුවාදා', 11 | 'බදාදා', 12 | 'බ්‍රහස්පතින්දා', 13 | 'සිකුරාදා', 14 | 'සෙනසුරාදා', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'ජන', 21 | 'පෙබ', 22 | 'මාර්', 23 | 'අප්‍රේ', 24 | 'මැයි', 25 | 'ජුනි', 26 | 'ජූලි', 27 | 'අගෝ', 28 | 'සැප්', 29 | 'ඔක්', 30 | 'නොවැ', 31 | 'දෙසැ', 32 | ], 33 | longhand: [ 34 | 'ජනවාරි', 35 | 'පෙබරවාරි', 36 | 'මාර්තු', 37 | 'අප්‍රේල්', 38 | 'මැයි', 39 | 'ජුනි', 40 | 'ජූලි', 41 | 'අගෝස්තු', 42 | 'සැප්තැම්බර්', 43 | 'ඔක්තෝබර්', 44 | 'නොවැම්බර්', 45 | 'දෙසැම්බර්', 46 | ], 47 | }, 48 | time24hr: true, 49 | }; 50 | 51 | export default Sinhala; 52 | -------------------------------------------------------------------------------- /src/l10n/sk.ts: -------------------------------------------------------------------------------- 1 | /* Slovak locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Slovak: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Ned', 'Pon', 'Ut', 'Str', 'Štv', 'Pia', 'Sob'], 7 | longhand: [ 8 | 'Nedeľa', 9 | 'Pondelok', 10 | 'Utorok', 11 | 'Streda', 12 | 'Štvrtok', 13 | 'Piatok', 14 | 'Sobota', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Jan', 21 | 'Feb', 22 | 'Mar', 23 | 'Apr', 24 | 'Máj', 25 | 'Jún', 26 | 'Júl', 27 | 'Aug', 28 | 'Sep', 29 | 'Okt', 30 | 'Nov', 31 | 'Dec', 32 | ], 33 | longhand: [ 34 | 'Január', 35 | 'Február', 36 | 'Marec', 37 | 'Apríl', 38 | 'Máj', 39 | 'Jún', 40 | 'Júl', 41 | 'August', 42 | 'September', 43 | 'Október', 44 | 'November', 45 | 'December', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | rangeSeparator: ' do ', 51 | time24hr: true, 52 | ordinal() { 53 | return '.'; 54 | }, 55 | }; 56 | 57 | export default Slovak; 58 | -------------------------------------------------------------------------------- /src/l10n/sl.ts: -------------------------------------------------------------------------------- 1 | /* Slovenian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Slovenian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Ned', 'Pon', 'Tor', 'Sre', 'Čet', 'Pet', 'Sob'], 7 | longhand: [ 8 | 'Nedelja', 9 | 'Ponedeljek', 10 | 'Torek', 11 | 'Sreda', 12 | 'Četrtek', 13 | 'Petek', 14 | 'Sobota', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Jan', 21 | 'Feb', 22 | 'Mar', 23 | 'Apr', 24 | 'Maj', 25 | 'Jun', 26 | 'Jul', 27 | 'Avg', 28 | 'Sep', 29 | 'Okt', 30 | 'Nov', 31 | 'Dec', 32 | ], 33 | longhand: [ 34 | 'Januar', 35 | 'Februar', 36 | 'Marec', 37 | 'April', 38 | 'Maj', 39 | 'Junij', 40 | 'Julij', 41 | 'Avgust', 42 | 'September', 43 | 'Oktober', 44 | 'November', 45 | 'December', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | rangeSeparator: ' do ', 51 | time24hr: true, 52 | ordinal() { 53 | return '.'; 54 | }, 55 | }; 56 | 57 | export default Slovenian; 58 | -------------------------------------------------------------------------------- /src/l10n/sq.ts: -------------------------------------------------------------------------------- 1 | /* Albanian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | 5 | export const Albanian: CustomLocale = { 6 | weekdays: { 7 | shorthand: ['Di', 'Hë', 'Ma', 'Më', 'En', 'Pr', 'Sh'], 8 | longhand: [ 9 | 'E Diel', 10 | 'E Hënë', 11 | 'E Martë', 12 | 'E Mërkurë', 13 | 'E Enjte', 14 | 'E Premte', 15 | 'E Shtunë', 16 | ], 17 | }, 18 | 19 | months: { 20 | shorthand: [ 21 | 'Jan', 22 | 'Shk', 23 | 'Mar', 24 | 'Pri', 25 | 'Maj', 26 | 'Qer', 27 | 'Kor', 28 | 'Gus', 29 | 'Sht', 30 | 'Tet', 31 | 'Nën', 32 | 'Dhj', 33 | ], 34 | longhand: [ 35 | 'Janar', 36 | 'Shkurt', 37 | 'Mars', 38 | 'Prill', 39 | 'Maj', 40 | 'Qershor', 41 | 'Korrik', 42 | 'Gusht', 43 | 'Shtator', 44 | 'Tetor', 45 | 'Nëntor', 46 | 'Dhjetor', 47 | ], 48 | }, 49 | time24hr: true, 50 | }; 51 | 52 | export default Albanian; 53 | -------------------------------------------------------------------------------- /src/l10n/sr-cyr.ts: -------------------------------------------------------------------------------- 1 | /* Serbian Cyrillic locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const SerbianCyrillic: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Нед', 'Пон', 'Уто', 'Сре', 'Чет', 'Пет', 'Суб'], 7 | longhand: [ 8 | 'Недеља', 9 | 'Понедељак', 10 | 'Уторак', 11 | 'Среда', 12 | 'Четвртак', 13 | 'Петак', 14 | 'Субота', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Јан', 21 | 'Феб', 22 | 'Мар', 23 | 'Апр', 24 | 'Мај', 25 | 'Јун', 26 | 'Јул', 27 | 'Авг', 28 | 'Сеп', 29 | 'Окт', 30 | 'Нов', 31 | 'Дец', 32 | ], 33 | longhand: [ 34 | 'Јануар', 35 | 'Фебруар', 36 | 'Март', 37 | 'Април', 38 | 'Мај', 39 | 'Јун', 40 | 'Јул', 41 | 'Август', 42 | 'Септембар', 43 | 'Октобар', 44 | 'Новембар', 45 | 'Децембар', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | weekAbbreviation: 'Нед.', 51 | rangeSeparator: ' до ', 52 | }; 53 | 54 | export default SerbianCyrillic; 55 | -------------------------------------------------------------------------------- /src/l10n/sr.ts: -------------------------------------------------------------------------------- 1 | /* Serbian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Serbian: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Ned', 'Pon', 'Uto', 'Sre', 'Čet', 'Pet', 'Sub'], 7 | longhand: [ 8 | 'Nedelja', 9 | 'Ponedeljak', 10 | 'Utorak', 11 | 'Sreda', 12 | 'Četvrtak', 13 | 'Petak', 14 | 'Subota', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Jan', 21 | 'Feb', 22 | 'Mar', 23 | 'Apr', 24 | 'Maj', 25 | 'Jun', 26 | 'Jul', 27 | 'Avg', 28 | 'Sep', 29 | 'Okt', 30 | 'Nov', 31 | 'Dec', 32 | ], 33 | longhand: [ 34 | 'Januar', 35 | 'Februar', 36 | 'Mart', 37 | 'April', 38 | 'Maj', 39 | 'Jun', 40 | 'Jul', 41 | 'Avgust', 42 | 'Septembar', 43 | 'Oktobar', 44 | 'Novembar', 45 | 'Decembar', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | weekAbbreviation: 'Ned.', 51 | rangeSeparator: ' do ', 52 | time24hr: true, 53 | }; 54 | 55 | export default Serbian; 56 | -------------------------------------------------------------------------------- /src/l10n/sv.ts: -------------------------------------------------------------------------------- 1 | /* Swedish locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Swedish: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | weekAbbreviation: 'v', 7 | 8 | weekdays: { 9 | shorthand: ['Sön', 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör'], 10 | longhand: [ 11 | 'Söndag', 12 | 'Måndag', 13 | 'Tisdag', 14 | 'Onsdag', 15 | 'Torsdag', 16 | 'Fredag', 17 | 'Lördag', 18 | ], 19 | }, 20 | 21 | months: { 22 | shorthand: [ 23 | 'Jan', 24 | 'Feb', 25 | 'Mar', 26 | 'Apr', 27 | 'Maj', 28 | 'Jun', 29 | 'Jul', 30 | 'Aug', 31 | 'Sep', 32 | 'Okt', 33 | 'Nov', 34 | 'Dec', 35 | ], 36 | longhand: [ 37 | 'Januari', 38 | 'Februari', 39 | 'Mars', 40 | 'April', 41 | 'Maj', 42 | 'Juni', 43 | 'Juli', 44 | 'Augusti', 45 | 'September', 46 | 'Oktober', 47 | 'November', 48 | 'December', 49 | ], 50 | }, 51 | time24hr: true, 52 | 53 | ordinal: () => '.', 54 | }; 55 | 56 | export default Swedish; 57 | -------------------------------------------------------------------------------- /src/l10n/th.ts: -------------------------------------------------------------------------------- 1 | /* Thai locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Thai: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['อา', 'จ', 'อ', 'พ', 'พฤ', 'ศ', 'ส'], 7 | longhand: [ 8 | 'อาทิตย์', 9 | 'จันทร์', 10 | 'อังคาร', 11 | 'พุธ', 12 | 'พฤหัสบดี', 13 | 'ศุกร์', 14 | 'เสาร์', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'ม.ค.', 21 | 'ก.พ.', 22 | 'มี.ค.', 23 | 'เม.ย.', 24 | 'พ.ค.', 25 | 'มิ.ย.', 26 | 'ก.ค.', 27 | 'ส.ค.', 28 | 'ก.ย.', 29 | 'ต.ค.', 30 | 'พ.ย.', 31 | 'ธ.ค.', 32 | ], 33 | longhand: [ 34 | 'มกราคม', 35 | 'กุมภาพันธ์', 36 | 'มีนาคม', 37 | 'เมษายน', 38 | 'พฤษภาคม', 39 | 'มิถุนายน', 40 | 'กรกฎาคม', 41 | 'สิงหาคม', 42 | 'กันยายน', 43 | 'ตุลาคม', 44 | 'พฤศจิกายน', 45 | 'ธันวาคม', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | rangeSeparator: ' ถึง ', 51 | time24hr: true, 52 | 53 | ordinal: () => '', 54 | }; 55 | 56 | export default Thai; 57 | -------------------------------------------------------------------------------- /src/l10n/tr.ts: -------------------------------------------------------------------------------- 1 | /* Turkish locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Turkish: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'], 7 | longhand: [ 8 | 'Pazar', 9 | 'Pazartesi', 10 | 'Salı', 11 | 'Çarşamba', 12 | 'Perşembe', 13 | 'Cuma', 14 | 'Cumartesi', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Oca', 21 | 'Şub', 22 | 'Mar', 23 | 'Nis', 24 | 'May', 25 | 'Haz', 26 | 'Tem', 27 | 'Ağu', 28 | 'Eyl', 29 | 'Eki', 30 | 'Kas', 31 | 'Ara', 32 | ], 33 | longhand: [ 34 | 'Ocak', 35 | 'Şubat', 36 | 'Mart', 37 | 'Nisan', 38 | 'Mayıs', 39 | 'Haziran', 40 | 'Temmuz', 41 | 'Ağustos', 42 | 'Eylül', 43 | 'Ekim', 44 | 'Kasım', 45 | 'Aralık', 46 | ], 47 | }, 48 | firstDayOfWeek: 1, 49 | ordinal: () => '.', 50 | rangeSeparator: ' - ', 51 | weekAbbreviation: 'Hf', 52 | amPM: ['ÖÖ', 'ÖS'], 53 | time24hr: true, 54 | }; 55 | 56 | export default Turkish; 57 | -------------------------------------------------------------------------------- /src/l10n/uk.ts: -------------------------------------------------------------------------------- 1 | /* Ukrainian locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Ukrainian: CustomLocale = { 5 | firstDayOfWeek: 1, 6 | 7 | weekdays: { 8 | shorthand: ['Нд', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'], 9 | longhand: [ 10 | 'Неділя', 11 | 'Понеділок', 12 | 'Вівторок', 13 | 'Середа', 14 | 'Четвер', 15 | "П'ятниця", 16 | 'Субота', 17 | ], 18 | }, 19 | 20 | months: { 21 | shorthand: [ 22 | 'Січ', 23 | 'Лют', 24 | 'Бер', 25 | 'Кві', 26 | 'Тра', 27 | 'Чер', 28 | 'Лип', 29 | 'Сер', 30 | 'Вер', 31 | 'Жов', 32 | 'Лис', 33 | 'Гру', 34 | ], 35 | longhand: [ 36 | 'Січень', 37 | 'Лютий', 38 | 'Березень', 39 | 'Квітень', 40 | 'Травень', 41 | 'Червень', 42 | 'Липень', 43 | 'Серпень', 44 | 'Вересень', 45 | 'Жовтень', 46 | 'Листопад', 47 | 'Грудень', 48 | ], 49 | }, 50 | time24hr: true, 51 | }; 52 | 53 | export default Ukrainian; 54 | -------------------------------------------------------------------------------- /src/l10n/uz.ts: -------------------------------------------------------------------------------- 1 | /* Uzbek locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Uzbek: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай', 'Жум', 'Шан'], 7 | longhand: [ 8 | 'Якшанба', 9 | 'Душанба', 10 | 'Сешанба', 11 | 'Чоршанба', 12 | 'Пайшанба', 13 | 'Жума', 14 | 'Шанба', 15 | ], 16 | }, 17 | months: { 18 | shorthand: [ 19 | 'Янв', 20 | 'Фев', 21 | 'Мар', 22 | 'Апр', 23 | 'Май', 24 | 'Июн', 25 | 'Июл', 26 | 'Авг', 27 | 'Сен', 28 | 'Окт', 29 | 'Ноя', 30 | 'Дек', 31 | ], 32 | longhand: [ 33 | 'Январ', 34 | 'Феврал', 35 | 'Март', 36 | 'Апрел', 37 | 'Май', 38 | 'Июн', 39 | 'Июл', 40 | 'Август', 41 | 'Сентябр', 42 | 'Октябр', 43 | 'Ноябр', 44 | 'Декабр', 45 | ], 46 | }, 47 | firstDayOfWeek: 1, 48 | ordinal() { 49 | return ''; 50 | }, 51 | rangeSeparator: ' — ', 52 | weekAbbreviation: 'Ҳафта', 53 | amPM: ['AM', 'PM'], 54 | yearAriaLabel: 'Йил', 55 | time24hr: true, 56 | }; 57 | 58 | export default Uzbek; 59 | -------------------------------------------------------------------------------- /src/l10n/uz_latn.ts: -------------------------------------------------------------------------------- 1 | /* Uzbek locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const UzbekLatin: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['Ya', 'Du', 'Se', 'Cho', 'Pa', 'Ju', 'Sha'], 7 | longhand: [ 8 | 'Yakshanba', 9 | 'Dushanba', 10 | 'Seshanba', 11 | 'Chorshanba', 12 | 'Payshanba', 13 | 'Juma', 14 | 'Shanba', 15 | ], 16 | }, 17 | months: { 18 | shorthand: [ 19 | 'Yan', 20 | 'Fev', 21 | 'Mar', 22 | 'Apr', 23 | 'May', 24 | 'Iyun', 25 | 'Iyul', 26 | 'Avg', 27 | 'Sen', 28 | 'Okt', 29 | 'Noy', 30 | 'Dek', 31 | ], 32 | longhand: [ 33 | 'Yanvar', 34 | 'Fevral', 35 | 'Mart', 36 | 'Aprel', 37 | 'May', 38 | 'Iyun', 39 | 'Iyul', 40 | 'Avgust', 41 | 'Sentabr', 42 | 'Oktabr', 43 | 'Noyabr', 44 | 'Dekabr', 45 | ], 46 | }, 47 | firstDayOfWeek: 1, 48 | ordinal() { 49 | return ''; 50 | }, 51 | rangeSeparator: ' — ', 52 | weekAbbreviation: 'Hafta', 53 | amPM: ['AM', 'PM'], 54 | yearAriaLabel: 'Yil', 55 | time24hr: true, 56 | }; 57 | 58 | export default UzbekLatin; 59 | -------------------------------------------------------------------------------- /src/l10n/vn.ts: -------------------------------------------------------------------------------- 1 | /* Vietnamese locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Vietnamese: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'], 7 | longhand: [ 8 | 'Chủ nhật', 9 | 'Thứ hai', 10 | 'Thứ ba', 11 | 'Thứ tư', 12 | 'Thứ năm', 13 | 'Thứ sáu', 14 | 'Thứ bảy', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | 'Th1', 21 | 'Th2', 22 | 'Th3', 23 | 'Th4', 24 | 'Th5', 25 | 'Th6', 26 | 'Th7', 27 | 'Th8', 28 | 'Th9', 29 | 'Th10', 30 | 'Th11', 31 | 'Th12', 32 | ], 33 | longhand: [ 34 | 'Tháng một', 35 | 'Tháng hai', 36 | 'Tháng ba', 37 | 'Tháng tư', 38 | 'Tháng năm', 39 | 'Tháng sáu', 40 | 'Tháng bảy', 41 | 'Tháng tám', 42 | 'Tháng chín', 43 | 'Tháng mười', 44 | 'Tháng 11', 45 | 'Tháng 12', 46 | ], 47 | }, 48 | 49 | firstDayOfWeek: 1, 50 | rangeSeparator: ' đến ', 51 | }; 52 | 53 | export default Vietnamese; 54 | -------------------------------------------------------------------------------- /src/l10n/zh-tw.ts: -------------------------------------------------------------------------------- 1 | /* Mandarin locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const MandarinTraditional: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['週日', '週一', '週二', '週三', '週四', '週五', '週六'], 7 | longhand: [ 8 | '星期日', 9 | '星期一', 10 | '星期二', 11 | '星期三', 12 | '星期四', 13 | '星期五', 14 | '星期六', 15 | ], 16 | }, 17 | months: { 18 | shorthand: [ 19 | '一月', 20 | '二月', 21 | '三月', 22 | '四月', 23 | '五月', 24 | '六月', 25 | '七月', 26 | '八月', 27 | '九月', 28 | '十月', 29 | '十一月', 30 | '十二月', 31 | ], 32 | longhand: [ 33 | '一月', 34 | '二月', 35 | '三月', 36 | '四月', 37 | '五月', 38 | '六月', 39 | '七月', 40 | '八月', 41 | '九月', 42 | '十月', 43 | '十一月', 44 | '十二月', 45 | ], 46 | }, 47 | rangeSeparator: ' 至 ', 48 | weekAbbreviation: '週', 49 | }; 50 | 51 | export default MandarinTraditional; 52 | -------------------------------------------------------------------------------- /src/l10n/zh.ts: -------------------------------------------------------------------------------- 1 | /* Mandarin locals for vue-tailwind */ 2 | import { CustomLocale } from '../types/locale'; 3 | 4 | export const Mandarin: CustomLocale = { 5 | weekdays: { 6 | shorthand: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'], 7 | longhand: [ 8 | '星期日', 9 | '星期一', 10 | '星期二', 11 | '星期三', 12 | '星期四', 13 | '星期五', 14 | '星期六', 15 | ], 16 | }, 17 | 18 | months: { 19 | shorthand: [ 20 | '一月', 21 | '二月', 22 | '三月', 23 | '四月', 24 | '五月', 25 | '六月', 26 | '七月', 27 | '八月', 28 | '九月', 29 | '十月', 30 | '十一月', 31 | '十二月', 32 | ], 33 | longhand: [ 34 | '一月', 35 | '二月', 36 | '三月', 37 | '四月', 38 | '五月', 39 | '六月', 40 | '七月', 41 | '八月', 42 | '九月', 43 | '十月', 44 | '十一月', 45 | '十二月', 46 | ], 47 | }, 48 | 49 | rangeSeparator: ' 至 ', 50 | weekAbbreviation: '周', 51 | }; 52 | 53 | export default Mandarin; 54 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | 4 | Vue.config.productionTip = false; 5 | 6 | new Vue({ 7 | render: (h) => h(App), 8 | }).$mount('#app'); 9 | -------------------------------------------------------------------------------- /src/t-alert.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TAlert'; 2 | -------------------------------------------------------------------------------- /src/t-button.ts: -------------------------------------------------------------------------------- 1 | export { default } from './inputs/TButton'; 2 | -------------------------------------------------------------------------------- /src/t-card.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TCard'; 2 | -------------------------------------------------------------------------------- /src/t-checkbox-group.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TCheckboxGroup'; 2 | -------------------------------------------------------------------------------- /src/t-checkbox.ts: -------------------------------------------------------------------------------- 1 | export { default } from './inputs/TCheckbox'; 2 | -------------------------------------------------------------------------------- /src/t-datepicker.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TDatepicker'; 2 | -------------------------------------------------------------------------------- /src/t-dialog.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TDialog'; 2 | -------------------------------------------------------------------------------- /src/t-dropdown.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TDropdown'; 2 | -------------------------------------------------------------------------------- /src/t-input-group.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TInputGroup'; 2 | -------------------------------------------------------------------------------- /src/t-input.ts: -------------------------------------------------------------------------------- 1 | export { default } from './inputs/TInput'; 2 | -------------------------------------------------------------------------------- /src/t-modal.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TModal'; 2 | -------------------------------------------------------------------------------- /src/t-pagination.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TPagination'; 2 | -------------------------------------------------------------------------------- /src/t-radio-group.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TRadioGroup'; 2 | -------------------------------------------------------------------------------- /src/t-radio.ts: -------------------------------------------------------------------------------- 1 | export { default } from './inputs/TRadio'; 2 | -------------------------------------------------------------------------------- /src/t-rich-select.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TRichSelect'; 2 | -------------------------------------------------------------------------------- /src/t-select.ts: -------------------------------------------------------------------------------- 1 | export { default } from './inputs/TSelect'; 2 | -------------------------------------------------------------------------------- /src/t-table.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TTable'; 2 | -------------------------------------------------------------------------------- /src/t-tag.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TTag'; 2 | -------------------------------------------------------------------------------- /src/t-textarea.ts: -------------------------------------------------------------------------------- 1 | export { default } from './inputs/TTextarea'; 2 | -------------------------------------------------------------------------------- /src/t-toggle.ts: -------------------------------------------------------------------------------- 1 | export { default } from './components/TToggle'; 2 | -------------------------------------------------------------------------------- /src/types/CheckboxValues.ts: -------------------------------------------------------------------------------- 1 | type CheckboxValue = { 2 | value: null | string | number | symbol | boolean | Array; 3 | } 4 | 5 | export default CheckboxValue; 6 | -------------------------------------------------------------------------------- /src/types/ComponentName.ts: -------------------------------------------------------------------------------- 1 | type ComponentName = 'TInput' 2 | | 'TTextarea' 3 | | 'TSelect' 4 | | 'TRadio' 5 | | 'TCheckbox' 6 | | 'TButton' 7 | | 'TInputGroup' 8 | | 'TCard' 9 | | 'TAlert' 10 | | 'TModal' 11 | | 'TDropdown' 12 | | 'TRichSelect' 13 | | 'TPagination' 14 | | 'TTag' 15 | | 'TRadioGroup' 16 | | 'TCheckboxGroup' 17 | | 'TTable' 18 | | 'TDatepicker' 19 | | 'TToggle' 20 | | 'TDialog' 21 | 22 | export default ComponentName; 23 | -------------------------------------------------------------------------------- /src/types/ComponentSettings.ts: -------------------------------------------------------------------------------- 1 | import Vue, { PropOptions } from 'vue'; 2 | import ComponentName from './ComponentName'; 3 | 4 | export type CustomProp = { 5 | [key: string]: undefined | string | number | boolean | Array | (() => CustomProp) | CustomProp 6 | } 7 | 8 | export type VTComponent = typeof Vue & { 9 | options?: { 10 | props?: { 11 | [key: string]: PropOptions 12 | }, 13 | name: ComponentName 14 | } 15 | } 16 | 17 | type ComponentSettings = { 18 | component: VTComponent, 19 | props: CustomProp 20 | } 21 | 22 | export default ComponentSettings; 23 | -------------------------------------------------------------------------------- /src/types/ComponentVariants.ts: -------------------------------------------------------------------------------- 1 | import CssClasses from './CssClasses'; 2 | import ComponentName from './ComponentName'; 3 | 4 | type ComponentVariants = { 5 | [key in ComponentName]: CssClasses; 6 | } 7 | 8 | export default ComponentVariants; 9 | -------------------------------------------------------------------------------- /src/types/CssClass.ts: -------------------------------------------------------------------------------- 1 | type CssClass = string | { [k: string]: any } | Array 2 | 3 | export default CssClass; 4 | -------------------------------------------------------------------------------- /src/types/CssClasses.ts: -------------------------------------------------------------------------------- 1 | import CssClass from './CssClass'; 2 | 3 | type CssClasses = { [k: string]: CssClass } | CssClass | undefined 4 | 5 | export default CssClasses; 6 | -------------------------------------------------------------------------------- /src/types/CustomProps.ts: -------------------------------------------------------------------------------- 1 | import { PropOptions } from 'vue'; 2 | 3 | type CustomProps = { 4 | [key: string]: PropOptions, 5 | } | undefined 6 | 7 | export default CustomProps; 8 | -------------------------------------------------------------------------------- /src/types/Dialog.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-shadow */ 2 | export enum HideReason { 3 | Outside = 'outside', 4 | Close = 'close', 5 | Esc = 'esc', 6 | Cancel = 'cancel', 7 | Ok = 'ok', 8 | Method = 'method', 9 | Value = 'value', 10 | } 11 | 12 | export enum DialogType { 13 | Alert = 'alert', 14 | Confirm = 'confirm', 15 | Prompt = 'prompt', 16 | } 17 | -------------------------------------------------------------------------------- /src/types/InputOption.ts: -------------------------------------------------------------------------------- 1 | type InputOption = string|number|{ children?: Array, disabled?: 'disabled' | boolean } 2 | 3 | export default InputOption; 4 | -------------------------------------------------------------------------------- /src/types/InputOptions.ts: -------------------------------------------------------------------------------- 1 | import InputOption from './InputOption'; 2 | 3 | type InputOptions = Array | Record | null 4 | 5 | export default InputOptions; 6 | -------------------------------------------------------------------------------- /src/types/Key.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-shadow */ 2 | enum Key { 3 | LEFT = 37, 4 | UP = 38, 5 | RIGHT = 39, 6 | DOWN = 40, 7 | ENTER = 13, 8 | ESC = 27, 9 | SPACE = 32, 10 | BACKSPACE = 8, 11 | } 12 | 13 | export default Key; 14 | -------------------------------------------------------------------------------- /src/types/LibrarySettings.ts: -------------------------------------------------------------------------------- 1 | import ComponentSettings, { VTComponent } from './ComponentSettings'; 2 | 3 | type LibrarySettings = { 4 | [key: string]: ComponentSettings | VTComponent; 5 | } | undefined; 6 | 7 | export default LibrarySettings; 8 | -------------------------------------------------------------------------------- /src/types/NormalizedOption.ts: -------------------------------------------------------------------------------- 1 | import InputOption from './InputOption'; 2 | 3 | type NormalizedOption = { 4 | value: null | string | number | symbol | boolean; 5 | text: string | number | boolean; 6 | children?: Array; 7 | raw?: InputOption; 8 | disabled?: boolean | 'disabled'; 9 | } 10 | 11 | export default NormalizedOption; 12 | -------------------------------------------------------------------------------- /src/types/NormalizedOptions.ts: -------------------------------------------------------------------------------- 1 | 2 | import NormalizedOption from './NormalizedOption'; 3 | 4 | type NormalizedOptions = Array 5 | 6 | export default NormalizedOptions; 7 | -------------------------------------------------------------------------------- /src/types/TRichSelect.ts: -------------------------------------------------------------------------------- 1 | import { CombinedVueInstance } from 'vue/types/vue'; 2 | import CssClass from './CssClass'; 3 | import NormalizedOptions from './NormalizedOptions'; 4 | import NormalizedOption from './NormalizedOption'; 5 | 6 | type TRichSelect = CombinedVueInstance; 19 | nextPage: undefined | number; 20 | }, 21 | { 22 | getElementCssClass: (elementName?: string) => CssClass; 23 | clickHandler: (e: MouseEvent) => void; 24 | focusHandler: (e: FocusEvent) => void; 25 | blurHandler: (e: FocusEvent) => void; 26 | arrowDownHandler: (e: KeyboardEvent) => void; 27 | arrowUpHandler: (e: KeyboardEvent) => void; 28 | enterHandler: (e: KeyboardEvent) => void; 29 | escapeHandler: (e: KeyboardEvent) => void; 30 | listScrollHandler: (e: Event) => void; 31 | // eslint-disable-next-line max-len 32 | optionHasValue(option: NormalizedOption, value: string | number | boolean | symbol | null): boolean; 33 | selectOption(option: NormalizedOption): void; 34 | searchInputHandler(e: Event): void; 35 | clearButtonClickHandler(e: MouseEvent): void; 36 | selectTag(tag: HTMLButtonElement): void; 37 | unselectTag(tag: HTMLButtonElement): void; 38 | unselectOptionAtIndex(index: number): void; 39 | }, { 40 | normalizedHeight: string; 41 | hasMinimumInputLength: boolean; 42 | shouldShowSearchbox: boolean; 43 | }, { 44 | id?: string | null; 45 | name?: string | null; 46 | autofocus?: boolean; 47 | disabled?: boolean; 48 | hideSearchBox?: boolean; 49 | openOnFocus: boolean; 50 | closeOnSelect: boolean; 51 | selectOnClose: boolean; 52 | minimumResultsForSearch?: number; 53 | clearable: boolean; 54 | multiple: boolean; 55 | value: string; 56 | noResultsText: string; 57 | searchingText: string; 58 | loadingMoreResultsText: string; 59 | searchBoxPlaceholder: string; 60 | delay: number; 61 | placeholder: string | undefined; 62 | fetchOptions: Function | undefined; 63 | minimumInputLength: number | undefined; 64 | minimumInputLengthText: Function | string; 65 | valueAttribute: string | undefined; 66 | textAttribute: string | undefined; 67 | tabindex: number | string | undefined; 68 | tagsAreFocusable: boolean; 69 | }> 70 | 71 | export default TRichSelect; 72 | -------------------------------------------------------------------------------- /src/types/locale.ts: -------------------------------------------------------------------------------- 1 | export type Locale = { 2 | weekdays: { 3 | shorthand: [string, string, string, string, string, string, string]; 4 | longhand: [string, string, string, string, string, string, string]; 5 | }; 6 | months: { 7 | shorthand: [ 8 | string, 9 | string, 10 | string, 11 | string, 12 | string, 13 | string, 14 | string, 15 | string, 16 | string, 17 | string, 18 | string, 19 | string 20 | ]; 21 | longhand: [ 22 | string, 23 | string, 24 | string, 25 | string, 26 | string, 27 | string, 28 | string, 29 | string, 30 | string, 31 | string, 32 | string, 33 | string 34 | ]; 35 | }; 36 | daysInMonth: [ 37 | number, 38 | number, 39 | number, 40 | number, 41 | number, 42 | number, 43 | number, 44 | number, 45 | number, 46 | number, 47 | number, 48 | number 49 | ]; 50 | firstDayOfWeek: number; 51 | ordinal: (nth: number) => string; 52 | rangeSeparator: string; 53 | weekAbbreviation: string; 54 | amPM: [string, string]; 55 | yearAriaLabel: string; 56 | monthAriaLabel: string; 57 | hourAriaLabel: string; 58 | minuteAriaLabel: string; 59 | time24hr: boolean; 60 | timeLabel: string; 61 | okLabel: string; 62 | }; 63 | 64 | export type CustomLocale = { 65 | ordinal?: Locale['ordinal']; 66 | daysInMonth?: Locale['daysInMonth']; 67 | firstDayOfWeek?: Locale['firstDayOfWeek']; 68 | rangeSeparator?: Locale['rangeSeparator']; 69 | weekAbbreviation?: Locale['weekAbbreviation']; 70 | yearAriaLabel?: string; 71 | hourAriaLabel?: string; 72 | minuteAriaLabel?: string; 73 | amPM?: Locale['amPM']; 74 | time24hr?: Locale['time24hr']; 75 | timeLabel?: Locale['timeLabel']; 76 | okLabel?: Locale['okLabel']; 77 | weekdays: { 78 | shorthand: [string, string, string, string, string, string, string]; 79 | longhand: [string, string, string, string, string, string, string]; 80 | }; 81 | months: { 82 | shorthand: [ 83 | string, 84 | string, 85 | string, 86 | string, 87 | string, 88 | string, 89 | string, 90 | string, 91 | string, 92 | string, 93 | string, 94 | string 95 | ]; 96 | longhand: [ 97 | string, 98 | string, 99 | string, 100 | string, 101 | string, 102 | string, 103 | string, 104 | string, 105 | string, 106 | string, 107 | string, 108 | string 109 | ]; 110 | }; 111 | }; 112 | 113 | export type LocaleName = 114 | | 'ar' 115 | | 'at' 116 | | 'az' 117 | | 'be' 118 | | 'bg' 119 | | 'bn' 120 | | 'bs' 121 | | 'ca' 122 | | 'cat' 123 | | 'cs' 124 | | 'cy' 125 | | 'da' 126 | | 'de' 127 | | 'default' 128 | | 'en' 129 | | 'eo' 130 | | 'es' 131 | | 'et' 132 | | 'fa' 133 | | 'fi' 134 | | 'fo' 135 | | 'fr' 136 | | 'gr' 137 | | 'he' 138 | | 'hi' 139 | | 'hr' 140 | | 'hu' 141 | | 'id' 142 | | 'is' 143 | | 'it' 144 | | 'ja' 145 | | 'ka' 146 | | 'ko' 147 | | 'km' 148 | | 'kz' 149 | | 'lt' 150 | | 'lv' 151 | | 'mk' 152 | | 'mn' 153 | | 'ms' 154 | | 'my' 155 | | 'nl' 156 | | 'no' 157 | | 'pa' 158 | | 'pl' 159 | | 'pt' 160 | | 'ro' 161 | | 'ru' 162 | | 'si' 163 | | 'sk' 164 | | 'sl' 165 | | 'sq' 166 | | 'sr' 167 | | 'sv' 168 | | 'th' 169 | | 'tr' 170 | | 'uk' 171 | | 'vn' 172 | | 'zh' 173 | | 'uz' 174 | | 'uz_latn' 175 | | 'zh_tw'; 176 | 177 | export type Locales = { 178 | [key in LocaleName]: Locale 179 | } 180 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export const pad = (number: string | number, length = 2) : string => `000${number}`.slice(length * -1); 2 | 3 | export const int = (bool: boolean) : 1 | 0 => (bool === true ? 1 : 0); 4 | -------------------------------------------------------------------------------- /src/utils/inputOptions.ts: -------------------------------------------------------------------------------- 1 | import get from 'lodash.get'; 2 | import map from 'lodash.map'; 3 | import NormalizedOption from '../types/NormalizedOption'; 4 | import InputOptions from '../types/InputOptions'; 5 | import NormalizedOptions from '../types/NormalizedOptions'; 6 | import InputOption from '../types/InputOption'; 7 | 8 | const guessOptionValue = (option: InputOption, valueAttribute?: string): string | symbol | null => { 9 | if (valueAttribute) { 10 | return get(option, valueAttribute); 11 | } 12 | return get(option, 'value', get(option, 'id', get(option, 'text'))); 13 | }; 14 | 15 | const guessOptionText = (option: InputOption, textAttribute?: string): string => { 16 | if (textAttribute) { 17 | return get(option, textAttribute); 18 | } 19 | return get(option, 'text', get(option, 'label')); 20 | }; 21 | 22 | const normalizeOption = (option: InputOption, textAttribute?: string, valueAttribute?: string): NormalizedOption => { 23 | if ( 24 | typeof option === 'string' 25 | || typeof option === 'number' 26 | || typeof option === 'boolean' 27 | ) { 28 | return { 29 | value: option, 30 | text: option, 31 | raw: option, 32 | }; 33 | } 34 | 35 | if (option.children) { 36 | const children = option.children.map((childOption) => normalizeOption(childOption)); 37 | return { 38 | value: guessOptionValue(option, valueAttribute), 39 | text: guessOptionText(option, textAttribute), 40 | children, 41 | }; 42 | } 43 | 44 | const normalizedOption: Partial = { 45 | value: guessOptionValue(option, valueAttribute), 46 | text: guessOptionText(option, textAttribute), 47 | raw: option, 48 | }; 49 | 50 | if (option.disabled !== undefined) { 51 | normalizedOption.disabled = option.disabled; 52 | } 53 | 54 | return normalizedOption as NormalizedOption; 55 | }; 56 | 57 | const normalizeOptions = (options: InputOptions, textAttribute?: string, valueAttribute?: string): NormalizedOptions => { 58 | if (!options) { 59 | return []; 60 | } 61 | 62 | if (Array.isArray(options)) { 63 | return options.map((option) => normalizeOption(option, textAttribute, valueAttribute)); 64 | } 65 | 66 | return map(options, (option, key) => ({ 67 | value: key, 68 | text: option, 69 | })) as NormalizedOptions; 70 | }; 71 | 72 | export { 73 | guessOptionValue, guessOptionText, normalizeOption, normalizeOptions, 74 | }; 75 | -------------------------------------------------------------------------------- /src/utils/isNumeric.ts: -------------------------------------------------------------------------------- 1 | const isNumeric = (char: string | number): boolean => /^\d+$/.test(String(char)); 2 | export default isNumeric; 3 | -------------------------------------------------------------------------------- /src/utils/uniqid.ts: -------------------------------------------------------------------------------- 1 | const uniqid = (): string => Math.random().toString(36).substring(7); 2 | 3 | export default uniqid; 4 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: [], 3 | darkMode: false, // or 'media' or 'class' 4 | theme: { 5 | }, 6 | variants: { 7 | extend: { 8 | opacity: ['disabled'], 9 | cursor: ['disabled'], 10 | }, 11 | }, 12 | plugins: [ 13 | // eslint-disable-next-line global-require 14 | require('@tailwindcss/forms'), 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /tests/unit/TAlert.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from '@vue/test-utils'; 2 | 3 | import TAlert from '../../src/components/TAlert'; 4 | 5 | describe('TAlert', () => { 6 | it('it renders the alert', () => { 7 | const wrapper = shallowMount(TAlert, { 8 | propsData: { 9 | show: true, 10 | }, 11 | }); 12 | 13 | expect(wrapper.get('div')).toBeTruthy(); 14 | }); 15 | 16 | it('it no render the alert by default', () => { 17 | const wrapper = shallowMount(TAlert); 18 | 19 | expect(wrapper.vm.$el.innerHTML).toBe(undefined); 20 | }); 21 | 22 | it('it renders the default slot content', () => { 23 | const wrapper = shallowMount(TAlert, { 24 | propsData: { 25 | show: true, 26 | }, 27 | slots: { 28 | default: 'lorem ipsum', 29 | }, 30 | }); 31 | 32 | expect(wrapper.vm.$el.innerHTML).toContain('lorem ipsum'); 33 | }); 34 | 35 | it('show/hide close button according to dismissible', async () => { 36 | const wrapper = shallowMount(TAlert, { 37 | propsData: { 38 | show: true, 39 | dismissible: true, 40 | }, 41 | }); 42 | 43 | expect(wrapper.vm.$refs.close).toBeTruthy(); 44 | 45 | wrapper.setProps({ dismissible: false }); 46 | 47 | await wrapper.vm.$nextTick(); 48 | 49 | expect(wrapper.vm.$refs.close).toBeUndefined(); 50 | }); 51 | 52 | it('default wrapper tag to div', () => { 53 | const wrapper = shallowMount(TAlert, { 54 | propsData: { 55 | show: true, 56 | }, 57 | }); 58 | 59 | expect(wrapper.vm.$el.tagName).toBe('DIV'); 60 | }); 61 | 62 | it('accepts different wrapper tag', () => { 63 | const wrapper = shallowMount(TAlert, { 64 | propsData: { 65 | show: true, 66 | tagName: 'li', 67 | }, 68 | }); 69 | expect(wrapper.vm.$el.tagName).toBe('LI'); 70 | }); 71 | 72 | it('it call the timeout method when timeout', () => { 73 | const wrapper = shallowMount(TAlert, { 74 | propsData: { 75 | timeout: 1, 76 | show: true, 77 | }, 78 | }); 79 | 80 | expect(wrapper.vm.$refs.close).toBeTruthy(); 81 | 82 | setTimeout(() => { 83 | expect(wrapper.vm.$refs.close).toBeUndefined(); 84 | }, 2); 85 | }); 86 | }); 87 | -------------------------------------------------------------------------------- /tests/unit/TCard.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount, mount } from '@vue/test-utils'; 2 | import TCard from '../../src/components/TCard'; 3 | 4 | describe('TCard', () => { 5 | it('it renders the card', () => { 6 | const wrapper = shallowMount(TCard); 7 | 8 | expect(wrapper.get('div')).toBeTruthy(); 9 | }); 10 | 11 | it('it renders the default slot content', () => { 12 | const wrapper = shallowMount(TCard, { 13 | slots: { 14 | default: 'lorem ipsum', 15 | }, 16 | }); 17 | 18 | expect(wrapper.vm.$el.children[0].innerHTML).toBe('lorem ipsum'); 19 | }); 20 | 21 | it('it render the header', () => { 22 | const header = 'My header'; 23 | const wrapper = mount(TCard, { 24 | propsData: { 25 | header, 26 | }, 27 | }); 28 | expect(wrapper.vm.$refs.header.innerHTML).toBe(header); 29 | }); 30 | 31 | it('it render the header when using props', () => { 32 | const header = '

My header

'; 33 | const wrapper = mount(TCard, { 34 | slots: { 35 | header, 36 | }, 37 | }); 38 | expect(wrapper.vm.$refs.header.innerHTML).toBe(header); 39 | }); 40 | 41 | it('it render the footer', () => { 42 | const footer = 'My footer'; 43 | const wrapper = mount(TCard, { 44 | propsData: { 45 | footer, 46 | }, 47 | }); 48 | expect(wrapper.vm.$refs.footer.innerHTML).toBe(footer); 49 | }); 50 | 51 | it('it render the footer prop', () => { 52 | const footer = '

My footer

'; 53 | const wrapper = mount(TCard, { 54 | slots: { 55 | footer, 56 | }, 57 | }); 58 | expect(wrapper.vm.$refs.footer.innerHTML).toBe(footer); 59 | }); 60 | 61 | it('if no body only renders the wrapper', () => { 62 | const wrapper = mount(TCard, { 63 | propsData: { 64 | noBody: true, 65 | }, 66 | }); 67 | expect(wrapper.vm.$el.innerHTML).toBe(''); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /tests/unit/TInputGroup.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount, mount } from '@vue/test-utils'; 2 | 3 | import TInputGroup from '../../src/components/TInputGroup'; 4 | 5 | describe('TInputGroup', () => { 6 | it('it renders the input group', () => { 7 | const wrapper = shallowMount(TInputGroup, { 8 | propsData: { 9 | show: true, 10 | }, 11 | }); 12 | 13 | expect(wrapper.get('div')).toBeTruthy(); 14 | }); 15 | 16 | it('it render the input group elements according to the order in the props', async () => { 17 | const slots = { 18 | label: 'the label', 19 | default: 'the default', 20 | feedback: 'the feedback', 21 | description: 'the description', 22 | }; 23 | const wrapper = shallowMount(TInputGroup, { 24 | slots, 25 | }); 26 | 27 | const defaultOrder = ['label', 'default', 'feedback', 'description']; 28 | defaultOrder.forEach((slotName, index) => { 29 | expect(wrapper.vm.$el.children[index].innerHTML).toBe(slots[slotName]); 30 | }); 31 | 32 | const otherOrder = ['default', 'description', 'feedback', 'label']; 33 | wrapper.setProps({ sortedElements: otherOrder }); 34 | await wrapper.vm.$nextTick(); 35 | otherOrder.forEach((slotName, index) => { 36 | expect(wrapper.vm.$el.children[index].innerHTML).toBe(slots[slotName]); 37 | }); 38 | }); 39 | 40 | it('only render the input group elements with slots', () => { 41 | const slots = { 42 | label: 'the label', 43 | default: 'the default', 44 | }; 45 | const wrapper = shallowMount(TInputGroup, { 46 | slots, 47 | }); 48 | 49 | expect(wrapper.vm.$refs.label).toBeTruthy(); 50 | expect(wrapper.vm.$refs.default).toBeTruthy(); 51 | expect(wrapper.vm.$refs.feedback).toBeUndefined(); 52 | expect(wrapper.vm.$refs.description).toBeUndefined(); 53 | }); 54 | 55 | it('Accept props instead of slots', () => { 56 | const propsData = { 57 | label: 'the label', 58 | feedback: 'the feedback', 59 | description: 'the description', 60 | }; 61 | const wrapper = mount(TInputGroup, { 62 | propsData, 63 | slots: { 64 | default: 'the default', 65 | }, 66 | }); 67 | 68 | // false is the default slot that we are ignoring in this test 69 | const defaultOrder = ['label', false, 'feedback', 'description']; 70 | defaultOrder.forEach((slotName, index) => { 71 | if (slotName) { 72 | expect(wrapper.vm.$el.children[index].innerHTML.trim()).toBe(propsData[slotName]); 73 | } 74 | }); 75 | }); 76 | }); 77 | -------------------------------------------------------------------------------- /tests/unit/TTag.spec.js: -------------------------------------------------------------------------------- 1 | 2 | import { shallowMount } from '@vue/test-utils'; 3 | 4 | import TTag from '../../src/components/TTag'; 5 | 6 | describe('TTag', () => { 7 | it('renders the tag', () => { 8 | const wrapper = shallowMount(TTag); 9 | 10 | expect(wrapper.get('div')).toBeTruthy(); 11 | }); 12 | 13 | it('renders with a custom tag', () => { 14 | const wrapper = shallowMount(TTag, { 15 | propsData: { 16 | tagName: 'span', 17 | }, 18 | }); 19 | 20 | expect(wrapper.get('span')).toBeTruthy(); 21 | }); 22 | 23 | it('render the default slot', () => { 24 | const wrapper = shallowMount(TTag, { 25 | slots: { 26 | default: 'hello', 27 | }, 28 | }); 29 | 30 | expect(wrapper.vm.$el.innerHTML).toBe('hello'); 31 | }); 32 | 33 | it('render the text used as param', () => { 34 | const wrapper = shallowMount(TTag, { 35 | propsData: { 36 | text: 'hello', 37 | }, 38 | }); 39 | 40 | expect(wrapper.vm.$el.innerHTML).toBe('hello'); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "es2015", 5 | "strict": true, 6 | "declaration": true, 7 | "declarationDir": "dist", 8 | "noUnusedLocals": true, 9 | "noUnusedParameters": true, 10 | "importHelpers": true, 11 | "moduleResolution": "node", 12 | "experimentalDecorators": true, 13 | "esModuleInterop": true, 14 | "allowSyntheticDefaultImports": true, 15 | "sourceMap": true, 16 | "baseUrl": ".", 17 | "types": [ 18 | "node", 19 | "vue" 20 | ], 21 | "lib": [ 22 | "esnext", 23 | "dom", 24 | "dom.iterable", 25 | "scripthost" 26 | ] 27 | }, 28 | "exclude": [ 29 | "node_modules", 30 | "dist" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /vue-tailwind.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, { VueConstructor } from 'vue'; 2 | import { DialogResponse } from './src/components/TDialog'; 3 | import { DialogOptions } from './src/utils/configureDialogGlobals'; 4 | import { InstallFunction } from './src'; 5 | 6 | declare module 'vue/types/vue' { 7 | interface Vue { 8 | $modal: Vue & { 9 | show: (name: string, params?: { [k: string]: string }) => void; 10 | hide: (name: string) => void; 11 | }; 12 | $dialog: Vue & { 13 | show: (name: string) => Promise; 14 | hide: (name: string) => void; 15 | alert: (titleOrDialogOptions: DialogOptions, text?: string, icon?: string) => Promise; 16 | confirm: (titleOrDialogOptions: DialogOptions, text?: string, icon?: string) => Promise; 17 | prompt: (titleOrDialogOptions: DialogOptions, text?: string, icon?: string) => Promise; 18 | }, 19 | $alert: (titleOrDialogOptions: DialogOptions, text?: string, icon?: string) => Promise; 20 | $confirm: (titleOrDialogOptions: DialogOptions, text?: string, icon?: string) => Promise; 21 | $prompt: (titleOrDialogOptions: DialogOptions, text?: string, icon?: string) => Promise; 22 | } 23 | } 24 | 25 | declare const VueTailwind: { install: InstallFunction }; 26 | 27 | export default VueTailwind; 28 | 29 | export const VueTailwindSample: VueConstructor; 30 | 31 | export * from './src/index'; 32 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * These are some necessary steps changing the default webpack config of the Vue CLI 3 | * that need to be changed in order for TypeScript based components to generate their 4 | * declaration (.d.ts) files. 5 | * Code by various users from https://github.com/vuejs/vue-cli/issues/1081 6 | */ 7 | const fixEmitDeclarationFilesForTypeScript = { 8 | chainWebpack: (config) => { 9 | if (process.env.NODE_ENV === 'production') { 10 | config.module.rule('ts').uses.delete('cache-loader'); 11 | config.module 12 | .rule('ts') 13 | .use('ts-loader') 14 | .loader('ts-loader') 15 | .tap((options) => ({ 16 | ...options, 17 | transpileOnly: false, 18 | happyPackMode: false, 19 | })); 20 | } 21 | }, 22 | parallel: false, 23 | }; 24 | 25 | module.exports = { 26 | ...fixEmitDeclarationFilesForTypeScript, 27 | }; 28 | --------------------------------------------------------------------------------