├── .eslintrc.js ├── .github └── workflows │ ├── release.yml │ └── test.yml ├── .gitignore ├── LICENSE ├── NOTICE ├── README.md ├── config └── storybook │ ├── main.js │ └── preview-head.html ├── docgen.config.js ├── docs └── components.md ├── example ├── demo.html └── preview.png ├── package.json ├── src ├── assets │ └── cover.png ├── components │ ├── ActionFetch.vue │ ├── ActionTooltip.vue │ └── index.js ├── index.js ├── install.js ├── store │ ├── actions.js │ ├── getters.js │ ├── index.js │ ├── mutation-types.js │ ├── mutations.js │ └── plugins.js └── stories │ └── ActionTooltip.stories.js └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "node": true, 6 | }, 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:vue/essential", 10 | 'plugin:vue/vue3-recommended' 11 | ], 12 | "globals": { 13 | "Atomics": "readonly", 14 | "SharedArrayBuffer": "readonly" 15 | }, 16 | "parserOptions": { 17 | "ecmaVersion": 2018, 18 | "sourceType": "module" 19 | }, 20 | "plugins": [ 21 | "vue" 22 | ], 23 | "rules": { 24 | "vue/html-indent": ["warn", 4] 25 | } 26 | }; -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | tags: 5 | - 'v*-release' 6 | 7 | jobs: 8 | release: 9 | name: build 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - uses: actions/setup-node@v1 16 | with: 17 | node-version: '14' 18 | registry-url: 'https://registry.npmjs.org' 19 | 20 | - uses: actions/cache@v2 21 | id: yarn-cache 22 | with: 23 | path: '**/node_modules' 24 | key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} 25 | restore-keys: | 26 | ${{ runner.os }}-modules- 27 | 28 | - name: Install Dependencies 29 | if: steps.yarn-cache.outputs.cache-hit != 'true' 30 | run: yarn install --frozen-lockfile 31 | 32 | - name: Build 33 | run: yarn build 34 | 35 | - name: Upload 36 | run: yarn publish --access public 37 | env: 38 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 39 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: [push, pull_request] 3 | jobs: 4 | lint: 5 | name: Lint 6 | runs-on: ubuntu-latest 7 | 8 | steps: 9 | - uses: actions/checkout@v2 10 | 11 | - uses: actions/setup-node@v1 12 | with: 13 | node-version: '14' 14 | 15 | - uses: actions/cache@v2 16 | id: yarn-cache 17 | with: 18 | path: '**/node_modules' 19 | key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} 20 | restore-keys: | 21 | ${{ runner.os }}-modules- 22 | 23 | - name: Install Dependencies 24 | if: steps.yarn-cache.outputs.cache-hit != 'true' 25 | run: yarn install --frozen-lockfile 26 | 27 | - name: Lint 28 | run: yarn lint 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node,vuejs 3 | # Edit at https://www.gitignore.io/?templates=node,vuejs 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Optional REPL history 62 | .node_repl_history 63 | 64 | # Output of 'npm pack' 65 | *.tgz 66 | 67 | # Yarn Integrity file 68 | .yarn-integrity 69 | 70 | # dotenv environment variables file 71 | .env 72 | .env.test 73 | 74 | # parcel-bundler cache (https://parceljs.org/) 75 | .cache 76 | 77 | # next.js build output 78 | .next 79 | 80 | # nuxt.js build output 81 | .nuxt 82 | 83 | # rollup.js default build output 84 | dist/ 85 | 86 | # Uncomment the public line if your project uses Gatsby 87 | # https://nextjs.org/blog/next-9-1#public-directory-support 88 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav 89 | # public 90 | 91 | # Storybook build outputs 92 | .out 93 | .storybook-out 94 | storybook-static 95 | 96 | # vuepress build output 97 | .vuepress/dist 98 | 99 | # Serverless directories 100 | .serverless/ 101 | 102 | # FuseBox cache 103 | .fusebox/ 104 | 105 | # DynamoDB Local files 106 | .dynamodb/ 107 | 108 | # Temporary folders 109 | tmp/ 110 | temp/ 111 | 112 | ### Vuejs ### 113 | # Recommended template: Node.gitignore 114 | 115 | npm-debug.log 116 | yarn-error.log 117 | 118 | # End of https://www.gitignore.io/api/node,vuejs 119 | 120 | .DS_Store 121 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2021 XIVAPI 2 | Copyright 2020 Oowazu Nonowazu 3 | Copyright 2020 SaltedLevity "Levi" 4 | Copyright 2020 ArcaneDisgea "Dis" 5 | Copyright 2020 Ay'yaruq Dotharl 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Latest Version](https://img.shields.io/github/package-json/v/xivapi/vue-xivtooltips) 2 | [![CDN](https://data.jsdelivr.com/v1/package/npm/@xivapi/vue-xivtooltips/badge?style=rounded)](https://www.jsdelivr.com/package/npm/@xivapi/vue-xivtooltips) 3 | ![Test](https://img.shields.io/github/workflow/status/xivapi/vue-xivtooltips/Test) 4 | [![Open Pull Requests](https://img.shields.io/github/issues-pr/xivapi/vue-xivtooltips)](https://github.com/xivapi/vue-xivtooltips/pulls) 5 | [![Open Issues](https://img.shields.io/github/issues/xivapi/vue-xivtooltips)](https://github.com/xivapi/vue-xivtooltips/issues) 6 | [![Licence](https://img.shields.io/github/license/xivapi/vue-xivtooltips)](https://github.com/xivapi/vue-xivtooltips/blob/master/LICENSE) 7 | 8 | # Vue-XIVTooltips 9 | 10 | ## Introduction 11 | 12 | Vue-XIVTooltips is a project with the goal of providing a concise and straightforward way of visualizing data from [XIVAPI](https://xivapi.com/) as easily readable tooltips that are modeled after the in-game tooltips of Final Fantasy XIV. 13 | It's built on the foundations of [Vue](https://vuejs.org/) and [Vuex](https://vuex.vuejs.org/) and can be used to provide tooltips for a website in html. 14 | 15 | ## Installation 16 | **Requirements** 17 | 18 | Both nodejs and yarnpkg are required to build the application: 19 | * [nodejs](https://nodejs.org/en/) 20 | * [yarnpkg](https://yarnpkg.com/) 21 | 22 | Further installation: 23 | 24 | If all requirements are installed, you can proceed. To build XIVTooltips, open the command line of your choice, navigate to the XIVTooltips directory and execute `yarn build` for production usage or `yarn build:dev` for developer usage. 25 | 26 | After a successful build, you can proceed. 27 | 28 | ## How to use 29 | 30 | **In a website** 31 | 32 | First of all you need to include the following .css files into the head of the html: 33 | 34 | ```html 35 | 36 | 37 | 38 | ``` 39 | And the following scripts into the body: 40 | 41 | ```html 42 | 43 | 44 | 45 | 46 | ``` 47 | In addition, this script is required: 48 | 49 | ```html 50 | 59 | ``` 60 | The ID `#content` can be modified to any ID or an existing ID. The ID must be on an element that wraps the area where you want the tooltips to render. 61 | 62 | The general structure of calling tooltips in html is as follows: 63 | ```html 64 | 65 | ``` 66 | `` with xxx being the ID of the tooltip/skill being called, and yyy being the full and correctly capitalized name. Those two arguments can be swapped at will. 67 | 68 | Another example: 69 | ```html 70 |

ActionFetch (with lookup)

71 | 72 | 73 | ``` 74 | would end up looking like this (mousing over Jugular Rip): 75 | 76 | ![Mouseover Example Picture](https://raw.githubusercontent.com/xivapi/vue-xivtooltips/master/example/preview.png) 77 | 78 | To get the Standalone Icon with no text somewhat visible at the bottom of the above picture, the name is simply omitted like follows: 79 | ```html 80 |

Standalone Icon (with lookup)

81 | 82 | ``` 83 | 84 | The third option is embedding the tooltip itself, which is done via: 85 | 86 | ```html 87 |

Embedded (with lookup)

88 | 89 | ``` 90 | 91 | Additional optional attributes can be found in the docs folder under components.md. 92 | 93 | An example html-script can be found under /examples/demo.html . 94 | 95 | ## Further documentation 96 | 97 | * [GitHub of Vue-XIVTooltips](https://github.com/xivapi/vue-xivtooltips) 98 | -------------------------------------------------------------------------------- /config/storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'], 3 | addons: ['@storybook/addon-essentials', '@storybook/addon-links'] 4 | } 5 | -------------------------------------------------------------------------------- /config/storybook/preview-head.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docgen.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | outDir: 'docs', 3 | outFile: 'components.md' 4 | } -------------------------------------------------------------------------------- /docs/components.md: -------------------------------------------------------------------------------- 1 | # ActionTooltip 2 | 3 | ## Props 4 | 5 | | Prop name | Description | Type | Values | Default | 6 | | ---------------- | -------------------------------------------------------------------------------- | ------ | ------------------------------ | ------------------------------------------------------------------------- | 7 | | lang | The language to display the tooltip in. | string | `'en'`, `'de'`, `'fr'`, `'ja'` | 'en' | 8 | | Icon | The icon of the action. | string | - | '' | 9 | | Name | The name of the action. | string | - | '' | 10 | | Cast100ms | The number of 100ms intervals it takes to cast | number | - | 0 | 11 | | Recast100ms | The number of 100ms intervals it takes to recast the spell | number | - | 0 | 12 | | Name_en | The name of the tooltip in English | string | - | '' | 13 | | Name_fr | The name of the tooltip in French | string | - | '' | 14 | | Name_ja | The name of the tooltip in Japanese | string | - | '' | 15 | | Name_de | The name of the tooltip in German | string | - | '' | 16 | | Description_en | The description of the tooltip (using html) in English. | string | - | '' | 17 | | Description_fr | The description of the tooltip (using html) in French. | string | - | '' | 18 | | Description_ja | The description of the tooltip (using html) in Japanese. | string | - | '' | 19 | | Description_de | The description of the tooltip (using html) in German. | string | - | '' | 20 | | Range | The range of the action. | number | - | 0 | 21 | | ClassJobLevel | The level at which the Class/Job obtains the action | number | - | 0 | 22 | | EffectRange | The range that the action has once used | number | - | 0 | 23 | | PrimaryCostValue | The MP cost of the action | number | - | 0 | 24 | | ActionCategory | The category the action falls under | object | - | {
Name_en: '',
Name_fr: '',
Name_de: '',
Name_ja: ''
} | 25 | | ClassJobCategory | The name of the Class/Job that gets the ability | object | - | {
Name_en: '',
Name_fr: '',
Name_de: '',
Name_ja: ''
} | 26 | | PrimaryCostType | The primary cost type; 0 is no cost, 2 is HP, 3 is MP, 5 is TP, 7 is GP, 8 is CP | number | - | 0 | 27 | # ActionFetch 28 | 29 | ## Props 30 | 31 | | Prop name | Description | Type | Values | Default | 32 | | --------- | --------------------------------------------- | ------- | ------------------------------ | ------- | 33 | | name | Name to display | string | - | '' | 34 | | id | Id to fetch from xivapi | number | - | 0 | 35 | | lang | Lang to display the tooltip in | string | `'en'`, `'de'`, `'fr'`, `'ja'` | 'en' | 36 | | embedded | Whether to embed the tooltips directly or not | boolean | - | false | 37 | # components 38 | -------------------------------------------------------------------------------- /example/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Inline template test 6 | 7 | 8 | 9 | 10 |
11 |

ActionTooltip with manual values in html (no AJAX)

12 | 25 | 26 |
27 | 40 | 41 |
42 | 43 |

ActionFetch (with lookup)

44 | 45 | 46 |

ActionFetch (with lookup; alternative languages)

47 | 48 | 49 | 50 |
51 | 52 |

Standalone Icon (with lookup)

53 | 54 |
55 | 56 |

Embedded (with lookup)

57 | 58 |
59 | 60 |

Crafting and Gatherering Actions (with lookup)

61 | 62 |
63 | 64 |
65 | 66 | 67 | 68 | 69 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /example/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xivapi/vue-xivtooltips/94972f3af23d831f74502344c8fb8ef2b77c4578/example/preview.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@xivapi/vue-xivtooltips", 3 | "version": "0.1.10", 4 | "description": "A simple library to display tooltips for Final Fantasy XIV data", 5 | "author": "xivapi ", 6 | "license": "Apache-2.0", 7 | "homepage": "https://github.com/xivapi/vue-xivtooltips", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/xivapi/vue-xivtooltips.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/xivapi/vue-xivtooltips/issues" 14 | }, 15 | "keywords": [ 16 | "ffxiv", 17 | "xivapi" 18 | ], 19 | "scripts": { 20 | "build": "vue-cli-service build --target lib --formats umd-min --name VueXIVTooltips --filename vue-xivtooltips src/index.js", 21 | "lint": "eslint --ext .js --ext .vue src", 22 | "build-storybook": "build-storybook", 23 | "build:dev": "vue-cli-service build --mode development --target lib --formats umd --name VueXIVTooltips --filename vue-xivtooltips src/index.js", 24 | "docs": "vue-docgen -c docgen.config.js", 25 | "storybook:build": "vue-cli-service storybook:build -c config/storybook", 26 | "storybook": "vue-cli-service storybook:serve -p 6006 -c config/storybook" 27 | }, 28 | "main": "dist/vue-xivtooltips.umd.min.js", 29 | "files": [ 30 | "dist", 31 | "NOTICE" 32 | ], 33 | "dependencies": { 34 | "lodash-es": "^4.17.15", 35 | "lodash.debounce": "^4.0.8", 36 | "vue-popperjs": "^2.3.0", 37 | "vuex-persist": "^2.2.0" 38 | }, 39 | "devDependencies": { 40 | "@babel/core": "^7.12.7", 41 | "@storybook/addon-essentials": "^6.0.26", 42 | "@storybook/addon-links": "^6.0.26", 43 | "@storybook/vue": "^6.0.26", 44 | "@vue/cli-plugin-babel": "^4.5.9", 45 | "@vue/cli-plugin-eslint": "^4.5.9", 46 | "@vue/cli-plugin-vuex": "^4.5.9", 47 | "@vue/cli-service": "^4.5.9", 48 | "@vue/compiler-sfc": "^3.0.0-beta.9", 49 | "axios": "^0.21.1", 50 | "babel-loader": "^8.2.2", 51 | "eslint": "^6.8.0", 52 | "eslint-plugin-vue": "^7.0.0-alpha.1", 53 | "postcss": "^7.0.29", 54 | "vue": "^2.6.11", 55 | "vue-cli-plugin-storybook": "~2.0.0", 56 | "vue-docgen-cli": "^4.21.0", 57 | "vue-template-compiler": "^2.6.11", 58 | "vuex": "^3.3.0" 59 | }, 60 | "peerDependencies": {} 61 | } 62 | -------------------------------------------------------------------------------- /src/assets/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xivapi/vue-xivtooltips/94972f3af23d831f74502344c8fb8ef2b77c4578/src/assets/cover.png -------------------------------------------------------------------------------- /src/components/ActionFetch.vue: -------------------------------------------------------------------------------- 1 | 61 | 62 | 111 | 112 | -------------------------------------------------------------------------------- /src/components/ActionTooltip.vue: -------------------------------------------------------------------------------- 1 | 190 | 191 | 289 | 290 | 291 | 292 | 503 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | import ActionFetch from './ActionFetch.vue' 2 | import ActionTooltip from './ActionTooltip.vue' 3 | 4 | export default { 5 | ActionFetch, 6 | ActionTooltip, 7 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import ActionFetch from './components/ActionFetch.vue' 2 | import ActionTooltip from './components/ActionTooltip.vue' 3 | import Store from './store' 4 | import install from './install' 5 | 6 | export { 7 | ActionFetch, 8 | ActionTooltip, 9 | Store, 10 | install, 11 | } -------------------------------------------------------------------------------- /src/install.js: -------------------------------------------------------------------------------- 1 | import components from './components' 2 | import Store from './store' 3 | 4 | export default function install(Vue, options) { 5 | if(install.installed) return 6 | 7 | // Levi-specific requirement 8 | // She's embedding in a page instead of a vue-generated template 9 | // Thus, the browser lowercases all html elements, ruining things 10 | // like 'ActionTooltip' -> 'actiontooltip' 11 | const webTemplateOnly = options.webTemplateOnly || false 12 | 13 | for (const key in components) { 14 | const keystr = webTemplateOnly ? key.toLowerCase() : key 15 | Vue.component(keystr, components[key]) 16 | } 17 | 18 | // add the store in as a custom name 19 | Vue.prototype.$TTStore = Store 20 | 21 | // Set timeout in seconds defaults to 6 hours 22 | const cacheTimeout = options.cacheTimeout || 21600 23 | Vue.prototype.$TTStore.dispatch('setDefaultTimeout', cacheTimeout) 24 | } -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | import debounce from 'lodash.debounce' 2 | import axios from 'axios' 3 | 4 | import {ADD_MULTIPLE_ACTIONS, ADD_PENDING_ACTION, CLEAR_PENDING_ACTIONS, ADD_ACTION, SET_TIMEOUT} from './mutation-types' 5 | 6 | const COLUMNS = [ 7 | 'Icon', 8 | 'Name_en', 9 | 'Name_de', 10 | 'Name_fr', 11 | 'Name_ja', 12 | 'Cast100ms', 13 | 'Recast100ms', 14 | 'Description_en', 15 | 'Description_de', 16 | 'Description_fr', 17 | 'Description_ja', 18 | 'Range', 19 | 'ClassJobLevel', 20 | 'EffectRange', 21 | 'PrimaryCostValue', 22 | 'PrimaryCostType', 23 | 'ActionCategory', 24 | 'ClassJobCategory', 25 | 'ID', 26 | ] 27 | 28 | export const xivapi = axios.create({ 29 | baseURL: 'https://xivapi.com' 30 | }) 31 | /* 32 | * https://xivapi.com/Action?ids=3569,16550,63&columns=Icon,Name_en,Cast100ms,Description_en,Range,ClassJobLevel,EffectRange,PrimaryCostValue,ActionCategory,ClassJobCategory,ID 33 | */ 34 | const fetchIds = debounce((ids, cb) => { 35 | xivapi.get('Action', { 36 | params: { 37 | ids: ids.join(','), 38 | columns: COLUMNS.join(','), 39 | } 40 | }).then(data => cb(data)) 41 | }, 20) 42 | 43 | export default { 44 | fetchActionId({commit, getters, state}, id) { 45 | const action = getters.getActionById(id) 46 | const cacheTimeoutSec = getters.getTimeout() 47 | if (action) { 48 | const now = new Date().getTime() / 1000 49 | const actionCacheTime = new Date(action.cacheTime).getTime() / 1000 50 | if ((now - actionCacheTime) <= cacheTimeoutSec) { 51 | return 52 | } 53 | } 54 | 55 | const newCacheTime = new Date() 56 | commit(ADD_PENDING_ACTION, id) 57 | fetchIds(state.pendingActionIds, (data) => { 58 | if (data.data.Results.length == 1) { 59 | let one = data.data.Results[0] 60 | one.cacheTime = newCacheTime 61 | commit(ADD_ACTION, {[one.ID]: one}) 62 | } else { 63 | const reducedData = data.data.Results.reduce( (acc, value, index) => { 64 | value.cacheTime = newCacheTime 65 | if (index > 1) { 66 | const range = value.Range 67 | if (typeof range === 'string' || range instanceof String) { 68 | value.Range = parseInt(range) 69 | } 70 | acc[value.ID] = value 71 | return acc 72 | } 73 | acc.cacheTime = newCacheTime 74 | return {[acc.ID]: acc, [value.ID]: value} 75 | }) 76 | commit(ADD_MULTIPLE_ACTIONS, reducedData) 77 | } 78 | 79 | commit(CLEAR_PENDING_ACTIONS) 80 | }) 81 | }, 82 | setDefaultTimeout({commit}, timeout) { 83 | commit(SET_TIMEOUT, timeout) 84 | } 85 | } -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | export default { 2 | getActionById: (state) => (id) => { 3 | return state.actions[id] 4 | }, 5 | getIconById: (state) => (id) => { 6 | return state.actions[id] && state.actions[id].Icon ? `https://xivapi.com${state.actions[id].Icon}` : '' 7 | }, 8 | getTimeout: (state) => () => state.defaultTimeout, 9 | } -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vuex from 'vuex' 2 | import {mutations} from './mutations' 3 | import actions from './actions' 4 | import getters from './getters' 5 | import plugins from './plugins' 6 | 7 | 8 | export default new Vuex.Store({ 9 | state: { 10 | actions: {}, 11 | pendingActionIds: [], 12 | defaultTimeout: 21600, 13 | }, 14 | mutations, 15 | actions, 16 | getters, 17 | plugins, 18 | }) -------------------------------------------------------------------------------- /src/store/mutation-types.js: -------------------------------------------------------------------------------- 1 | export const ADD_ACTION = 'addAction' 2 | export const ADD_MULTIPLE_ACTIONS = 'addActions' 3 | export const ADD_PENDING_ACTION = 'addPendingAction' 4 | export const CLEAR_PENDING_ACTIONS = 'clearPendingActions' 5 | export const SET_TIMEOUT = 'setTimeout' -------------------------------------------------------------------------------- /src/store/mutations.js: -------------------------------------------------------------------------------- 1 | import { 2 | ADD_ACTION, 3 | ADD_MULTIPLE_ACTIONS, 4 | ADD_PENDING_ACTION, 5 | CLEAR_PENDING_ACTIONS, 6 | SET_TIMEOUT, 7 | } from './mutation-types' 8 | 9 | export const LOCAL_STORAGE_KEY = 'xivtooltips' 10 | 11 | export const mutations = { 12 | [ADD_ACTION] (state, action) { 13 | state.actions = {...state.actions, ...action} 14 | }, 15 | [ADD_MULTIPLE_ACTIONS] (state, actions) { 16 | state.actions = {...state.actions, ...actions} 17 | }, 18 | [ADD_PENDING_ACTION] (state, id) { 19 | if (! state.pendingActionIds.includes(id)) { 20 | state.pendingActionIds.push(id) 21 | } 22 | }, 23 | [CLEAR_PENDING_ACTIONS] (state) { 24 | state.pendingActionIds = [] 25 | }, 26 | [SET_TIMEOUT] (state, timeout) { 27 | state.defaultTimeout = timeout 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /src/store/plugins.js: -------------------------------------------------------------------------------- 1 | import VuexPersistence from 'vuex-persist' 2 | import { LOCAL_STORAGE_KEY } from "./mutations"; 3 | 4 | const LocalStore = new VuexPersistence({ 5 | storage: window.localStorage, 6 | key: LOCAL_STORAGE_KEY, 7 | }) 8 | 9 | export default [LocalStore.plugin] -------------------------------------------------------------------------------- /src/stories/ActionTooltip.stories.js: -------------------------------------------------------------------------------- 1 | import ActionTooltip from '../components/ActionTooltip.vue'; 2 | 3 | export default { 4 | title: 'Example/ActionTooltip', 5 | component: ActionTooltip, 6 | argTypes: { 7 | lang: { control: { type: 'select', options: ['en', 'de', 'fr', 'ja'] } }, 8 | } 9 | }; 10 | 11 | const Template = (args, { argTypes }) => ({ 12 | props: Object.keys(argTypes), 13 | components: { ActionTooltip }, 14 | template: '', 15 | }); 16 | 17 | export const Tooltip = Template.bind({}); 18 | Tooltip.args = { 19 | lang: 'en', 20 | Icon: '/i/002000/002801.png', 21 | Name: 'Adloquium', 22 | Name_en: 'Adloquium', 23 | Name_de: 'Adloquium', 24 | Name_fr: 'Traité du réconfort', 25 | Name_ja: '鼓舞激励の策', 26 | Cast100ms: 20, 27 | Recast100ms: 25, 28 | Description_en: "Restores target's HP.\n\nCure Potency: 300\n\nAdditional Effect: Grants Galvanize to target, nullifying damage equaling 125% of the amount of HP restored. When critical HP is restored, also grants Catalyze, nullifying damage equaling 125% the amount of HP restored.\n\nDuration: 30s\n\nEffect cannot be stacked with astrologian's Nocturnal Field.", 29 | Description_fr: "Restaure les PV de la cible.\n\nPuissance: 300\n\nEffet additionnel: octroie Réconfort, une barrière annulant un montant de dégâts égal à 125% des PV restaurés. Octroie Exhortation, une deuxième barrière identique, si le sort est critique.\n\nDurée: 30s\n\nNe peut être cumulé avec l'effet Champ nocturne.", 30 | Description_de: "Du regenerierst LP des Ziels.\n\nHeilpotenzial: 300\n\nZusatzeffekt: Errichtet eine Barriere um das Ziel, die Schaden in der Höhe von 125 % der Heilwirkung absorbiert (Dynamisierung).\n\nDauer: 30 Sekunden\n\nZusatzeffekt bei kritischem Heilerfolg: Zusätzliche Barriere absorbiert 125 % der Heilwirkung (Katalyse).\n\nDauer: 30 Sekunden\n\nKann nicht zugleich mit der Nocturnal-Barriere des Astrologen aktiv sein.", 31 | Description_ja: "対象のHPを回復する。 回復力:300\n\n追加効果:対象に一定量のダメージを防ぐバリアである「鼓舞」を付与する。\n\n鼓舞効果:回復量の125%分のダメージを軽減する。\n\n効果時間:30秒\n\n占星術師のノクターナルフィールド効果とは同時に付与されない。\n\n追加効果(クリティカル時):対象に一定量のダメージを防ぐバリアである「激励」を付与する。\n\n激励効果:回復量の125%分のダメージを軽減する。\n\n効果時間:30秒", 32 | Range: 30, 33 | ClassJobLevel: 30, 34 | PrimaryCostValue: 10, 35 | PrimaryCostType: 3, 36 | EffectRange: 0, 37 | ActionCategory: {ID:2,Name:"Spell",Name_de:"Zauber",Name_en:"Spell",Name_fr:"Sort",Name_ja:"魔法"}, 38 | ClassJobCategory: { 39 | ACN: 0, 40 | ADV: 0, 41 | ALC: 0, 42 | ARC: 0, 43 | ARM: 0, 44 | AST: 0, 45 | BLM: 0, 46 | BLU: 0, 47 | BRD: 0, 48 | BSM: 0, 49 | BTN: 0, 50 | CNJ: 0, 51 | CRP: 0, 52 | CUL: 0, 53 | DNC: 0, 54 | DRG: 0, 55 | DRK: 0, 56 | FSH: 0, 57 | GLA: 0, 58 | GNB: 0, 59 | GSM: 0, 60 | ID: 29, 61 | LNC: 0, 62 | LTW: 0, 63 | MCH: 0, 64 | MIN: 0, 65 | MNK: 0, 66 | MRD: 0, 67 | NIN: 0, 68 | Name: "SCH", 69 | Name_de: "GLT", 70 | Name_en: "SCH", 71 | Name_fr: "ÉRU", 72 | Name_ja: "学者", 73 | PGL: 0, 74 | PLD: 0, 75 | RDM: 0, 76 | ROG: 0, 77 | SAM: 0, 78 | SCH: 1, 79 | SMN: 0, 80 | THM: 0, 81 | WAR: 0, 82 | WHM: 0, 83 | WVR: 0, 84 | } 85 | } 86 | 87 | // export const Primary = Template.bind({}); 88 | // Primary.args = { 89 | // primary: true, 90 | // label: 'Button', 91 | // }; 92 | 93 | // export const Secondary = Template.bind({}); 94 | // Secondary.args = { 95 | // label: 'Button', 96 | // }; 97 | 98 | // export const Large = Template.bind({}); 99 | // Large.args = { 100 | // size: 'large', 101 | // label: 'Button', 102 | // }; 103 | 104 | // export const Small = Template.bind({}); 105 | // Small.args = { 106 | // size: 'small', 107 | // label: 'Button', 108 | // }; 109 | --------------------------------------------------------------------------------