mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-05-07 14:57:12 -04:00
Merge c9dd5b9e11
into 07eea0f484
This commit is contained in:
commit
649bd72f72
19 changed files with 7250 additions and 8482 deletions
|
@ -286,6 +286,9 @@
|
||||||
"watchTriggerable": true,
|
"watchTriggerable": true,
|
||||||
"watchWithFilter": true,
|
"watchWithFilter": true,
|
||||||
"whenever": true,
|
"whenever": true,
|
||||||
"toValue": true
|
"toValue": true,
|
||||||
|
"injectLocal": true,
|
||||||
|
"provideLocal": true,
|
||||||
|
"useClipboardItems": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
auto-imports.d.ts
vendored
9
auto-imports.d.ts
vendored
|
@ -36,6 +36,7 @@ declare global {
|
||||||
const h: typeof import('vue')['h']
|
const h: typeof import('vue')['h']
|
||||||
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
||||||
const inject: typeof import('vue')['inject']
|
const inject: typeof import('vue')['inject']
|
||||||
|
const injectLocal: typeof import('@vueuse/core')['injectLocal']
|
||||||
const isDefined: typeof import('@vueuse/core')['isDefined']
|
const isDefined: typeof import('@vueuse/core')['isDefined']
|
||||||
const isProxy: typeof import('vue')['isProxy']
|
const isProxy: typeof import('vue')['isProxy']
|
||||||
const isReactive: typeof import('vue')['isReactive']
|
const isReactive: typeof import('vue')['isReactive']
|
||||||
|
@ -65,6 +66,7 @@ declare global {
|
||||||
const onUpdated: typeof import('vue')['onUpdated']
|
const onUpdated: typeof import('vue')['onUpdated']
|
||||||
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
|
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
|
||||||
const provide: typeof import('vue')['provide']
|
const provide: typeof import('vue')['provide']
|
||||||
|
const provideLocal: typeof import('@vueuse/core')['provideLocal']
|
||||||
const reactify: typeof import('@vueuse/core')['reactify']
|
const reactify: typeof import('@vueuse/core')['reactify']
|
||||||
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
|
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
|
||||||
const reactive: typeof import('vue')['reactive']
|
const reactive: typeof import('vue')['reactive']
|
||||||
|
@ -128,6 +130,7 @@ declare global {
|
||||||
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
|
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
|
||||||
const useCached: typeof import('@vueuse/core')['useCached']
|
const useCached: typeof import('@vueuse/core')['useCached']
|
||||||
const useClipboard: typeof import('@vueuse/core')['useClipboard']
|
const useClipboard: typeof import('@vueuse/core')['useClipboard']
|
||||||
|
const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems']
|
||||||
const useCloned: typeof import('@vueuse/core')['useCloned']
|
const useCloned: typeof import('@vueuse/core')['useCloned']
|
||||||
const useColorMode: typeof import('@vueuse/core')['useColorMode']
|
const useColorMode: typeof import('@vueuse/core')['useColorMode']
|
||||||
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
|
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
|
||||||
|
@ -326,6 +329,7 @@ declare module 'vue' {
|
||||||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||||
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
||||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||||
|
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
||||||
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
||||||
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
||||||
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
||||||
|
@ -355,6 +359,7 @@ declare module 'vue' {
|
||||||
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
||||||
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
||||||
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
||||||
|
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
|
||||||
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
|
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
|
||||||
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
|
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
|
||||||
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
||||||
|
@ -418,6 +423,7 @@ declare module 'vue' {
|
||||||
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
|
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
|
||||||
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
|
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
|
||||||
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
|
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
|
||||||
|
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
|
||||||
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
|
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
|
||||||
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
|
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
|
||||||
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
|
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
|
||||||
|
@ -610,6 +616,7 @@ declare module '@vue/runtime-core' {
|
||||||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||||
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
||||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||||
|
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
||||||
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
||||||
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
||||||
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
||||||
|
@ -639,6 +646,7 @@ declare module '@vue/runtime-core' {
|
||||||
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
||||||
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
||||||
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
||||||
|
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
|
||||||
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
|
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
|
||||||
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
|
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
|
||||||
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
||||||
|
@ -702,6 +710,7 @@ declare module '@vue/runtime-core' {
|
||||||
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
|
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
|
||||||
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
|
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
|
||||||
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
|
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
|
||||||
|
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
|
||||||
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
|
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
|
||||||
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
|
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
|
||||||
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
|
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
|
||||||
|
|
10
components.d.ts
vendored
10
components.d.ts
vendored
|
@ -23,6 +23,7 @@ declare module '@vue/runtime-core' {
|
||||||
CAlert: typeof import('./src/ui/c-alert/c-alert.vue')['default']
|
CAlert: typeof import('./src/ui/c-alert/c-alert.vue')['default']
|
||||||
'CAlert.demo': typeof import('./src/ui/c-alert/c-alert.demo.vue')['default']
|
'CAlert.demo': typeof import('./src/ui/c-alert/c-alert.demo.vue')['default']
|
||||||
CameraRecorder: typeof import('./src/tools/camera-recorder/camera-recorder.vue')['default']
|
CameraRecorder: typeof import('./src/tools/camera-recorder/camera-recorder.vue')['default']
|
||||||
|
CardPicker: typeof import('./src/tools/card-picker/card-picker.vue')['default']
|
||||||
CaseConverter: typeof import('./src/tools/case-converter/case-converter.vue')['default']
|
CaseConverter: typeof import('./src/tools/case-converter/case-converter.vue')['default']
|
||||||
CButton: typeof import('./src/ui/c-button/c-button.vue')['default']
|
CButton: typeof import('./src/ui/c-button/c-button.vue')['default']
|
||||||
'CButton.demo': typeof import('./src/ui/c-button/c-button.demo.vue')['default']
|
'CButton.demo': typeof import('./src/ui/c-button/c-button.demo.vue')['default']
|
||||||
|
@ -50,6 +51,7 @@ declare module '@vue/runtime-core' {
|
||||||
'CModal.demo': typeof import('./src/ui/c-modal/c-modal.demo.vue')['default']
|
'CModal.demo': typeof import('./src/ui/c-modal/c-modal.demo.vue')['default']
|
||||||
CModalValue: typeof import('./src/ui/c-modal-value/c-modal-value.vue')['default']
|
CModalValue: typeof import('./src/ui/c-modal-value/c-modal-value.vue')['default']
|
||||||
'CModalValue.demo': typeof import('./src/ui/c-modal-value/c-modal-value.demo.vue')['default']
|
'CModalValue.demo': typeof import('./src/ui/c-modal-value/c-modal-value.demo.vue')['default']
|
||||||
|
CoinFlipper: typeof import('./src/tools/coin-flipper/coin-flipper.vue')['default']
|
||||||
CollapsibleToolMenu: typeof import('./src/components/CollapsibleToolMenu.vue')['default']
|
CollapsibleToolMenu: typeof import('./src/components/CollapsibleToolMenu.vue')['default']
|
||||||
ColorConverter: typeof import('./src/tools/color-converter/color-converter.vue')['default']
|
ColorConverter: typeof import('./src/tools/color-converter/color-converter.vue')['default']
|
||||||
ColoredCard: typeof import('./src/components/ColoredCard.vue')['default']
|
ColoredCard: typeof import('./src/components/ColoredCard.vue')['default']
|
||||||
|
@ -68,6 +70,7 @@ declare module '@vue/runtime-core' {
|
||||||
'DemoHome.page': typeof import('./src/ui/demo/demo-home.page.vue')['default']
|
'DemoHome.page': typeof import('./src/ui/demo/demo-home.page.vue')['default']
|
||||||
DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default']
|
DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default']
|
||||||
DeviceInformation: typeof import('./src/tools/device-information/device-information.vue')['default']
|
DeviceInformation: typeof import('./src/tools/device-information/device-information.vue')['default']
|
||||||
|
DiceRoller: typeof import('./src/tools/dice-roller/dice-roller.vue')['default']
|
||||||
DiffViewer: typeof import('./src/tools/json-diff/diff-viewer/diff-viewer.vue')['default']
|
DiffViewer: typeof import('./src/tools/json-diff/diff-viewer/diff-viewer.vue')['default']
|
||||||
DockerRunToDockerComposeConverter: typeof import('./src/tools/docker-run-to-docker-compose-converter/docker-run-to-docker-compose-converter.vue')['default']
|
DockerRunToDockerComposeConverter: typeof import('./src/tools/docker-run-to-docker-compose-converter/docker-run-to-docker-compose-converter.vue')['default']
|
||||||
DynamicValues: typeof import('./src/tools/benchmark-builder/dynamic-values.vue')['default']
|
DynamicValues: typeof import('./src/tools/benchmark-builder/dynamic-values.vue')['default']
|
||||||
|
@ -80,6 +83,7 @@ declare module '@vue/runtime-core' {
|
||||||
EtaCalculator: typeof import('./src/tools/eta-calculator/eta-calculator.vue')['default']
|
EtaCalculator: typeof import('./src/tools/eta-calculator/eta-calculator.vue')['default']
|
||||||
FavoriteButton: typeof import('./src/components/FavoriteButton.vue')['default']
|
FavoriteButton: typeof import('./src/components/FavoriteButton.vue')['default']
|
||||||
FormatTransformer: typeof import('./src/components/FormatTransformer.vue')['default']
|
FormatTransformer: typeof import('./src/components/FormatTransformer.vue')['default']
|
||||||
|
FortuneWheel: typeof import('./src/tools/fortune-wheel/fortune-wheel.vue')['default']
|
||||||
GitMemo: typeof import('./src/tools/git-memo/git-memo.vue')['default']
|
GitMemo: typeof import('./src/tools/git-memo/git-memo.vue')['default']
|
||||||
'GitMemo.content': typeof import('./src/tools/git-memo/git-memo.content.md')['default']
|
'GitMemo.content': typeof import('./src/tools/git-memo/git-memo.content.md')['default']
|
||||||
HashText: typeof import('./src/tools/hash-text/hash-text.vue')['default']
|
HashText: typeof import('./src/tools/hash-text/hash-text.vue')['default']
|
||||||
|
@ -129,18 +133,24 @@ declare module '@vue/runtime-core' {
|
||||||
MenuLayout: typeof import('./src/components/MenuLayout.vue')['default']
|
MenuLayout: typeof import('./src/components/MenuLayout.vue')['default']
|
||||||
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
|
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
|
||||||
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
|
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
|
||||||
|
NA: typeof import('naive-ui')['NA']
|
||||||
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
|
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
|
||||||
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||||
|
NCode: typeof import('naive-ui')['NCode']
|
||||||
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
|
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
|
||||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||||
NDivider: typeof import('naive-ui')['NDivider']
|
NDivider: typeof import('naive-ui')['NDivider']
|
||||||
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
||||||
|
NFormItem: typeof import('naive-ui')['NFormItem']
|
||||||
NH1: typeof import('naive-ui')['NH1']
|
NH1: typeof import('naive-ui')['NH1']
|
||||||
NH3: typeof import('naive-ui')['NH3']
|
NH3: typeof import('naive-ui')['NH3']
|
||||||
NIcon: typeof import('naive-ui')['NIcon']
|
NIcon: typeof import('naive-ui')['NIcon']
|
||||||
|
NInputNumber: typeof import('naive-ui')['NInputNumber']
|
||||||
NLayout: typeof import('naive-ui')['NLayout']
|
NLayout: typeof import('naive-ui')['NLayout']
|
||||||
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
|
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
|
||||||
NMenu: typeof import('naive-ui')['NMenu']
|
NMenu: typeof import('naive-ui')['NMenu']
|
||||||
|
NP: typeof import('naive-ui')['NP']
|
||||||
|
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||||
NSpace: typeof import('naive-ui')['NSpace']
|
NSpace: typeof import('naive-ui')['NSpace']
|
||||||
NTable: typeof import('naive-ui')['NTable']
|
NTable: typeof import('naive-ui')['NTable']
|
||||||
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
|
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
"release": "node ./scripts/release.mjs"
|
"release": "node ./scripts/release.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@dice-roller/rpg-dice-roller": "^5.5.1",
|
||||||
"@it-tools/bip39": "^0.0.4",
|
"@it-tools/bip39": "^0.0.4",
|
||||||
"@it-tools/oggen": "^1.3.0",
|
"@it-tools/oggen": "^1.3.0",
|
||||||
"@regexper/render": "^1.0.0",
|
"@regexper/render": "^1.0.0",
|
||||||
|
@ -52,6 +53,7 @@
|
||||||
"@vueuse/core": "^10.3.0",
|
"@vueuse/core": "^10.3.0",
|
||||||
"@vueuse/head": "^1.0.0",
|
"@vueuse/head": "^1.0.0",
|
||||||
"@vueuse/router": "^10.0.0",
|
"@vueuse/router": "^10.0.0",
|
||||||
|
"@younestouati/playing-cards-standard-deck": "^6.0.1",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"change-case": "^4.1.2",
|
"change-case": "^4.1.2",
|
||||||
"colord": "^2.9.3",
|
"colord": "^2.9.3",
|
||||||
|
@ -100,6 +102,7 @@
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
"vue-shadow-dom": "^4.2.0",
|
"vue-shadow-dom": "^4.2.0",
|
||||||
"vue-tsc": "^1.8.1",
|
"vue-tsc": "^1.8.1",
|
||||||
|
"vue3-fortune-wheel": "^2.0.5",
|
||||||
"vuedraggable": "^4.1.0",
|
"vuedraggable": "^4.1.0",
|
||||||
"xml-formatter": "^3.3.2",
|
"xml-formatter": "^3.3.2",
|
||||||
"xml-js": "^1.6.11",
|
"xml-js": "^1.6.11",
|
||||||
|
|
15366
pnpm-lock.yaml
generated
15366
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
BIN
public/logo.png
Normal file
BIN
public/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
|
@ -128,7 +128,7 @@ function activateOption(option: PaletteOption) {
|
||||||
<c-input-text ref="inputRef" v-model:value="searchPrompt" raw-text placeholder="Type to search a tool or a command..." autofocus clearable />
|
<c-input-text ref="inputRef" v-model:value="searchPrompt" raw-text placeholder="Type to search a tool or a command..." autofocus clearable />
|
||||||
|
|
||||||
<div v-for="(options, category) in filteredSearchResult" :key="category">
|
<div v-for="(options, category) in filteredSearchResult" :key="category">
|
||||||
<div ml-3 mt-3 text-sm font-bold text-primary op-60>
|
<div ml-3 mt-3 text-sm text-primary font-bold op-60>
|
||||||
{{ category }}
|
{{ category }}
|
||||||
</div>
|
</div>
|
||||||
<command-palette-option v-for="option in options" :key="option.name" :option="option" :selected="selectedOptionIndex === getOptionIndex(option)" @activated="activateOption" />
|
<command-palette-option v-for="option in options" :key="option.name" :option="option" :selected="selectedOptionIndex === getOptionIndex(option)" @activated="activateOption" />
|
||||||
|
|
63
src/tools/card-picker/card-picker.vue
Normal file
63
src/tools/card-picker/card-picker.vue
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import cards from '@younestouati/playing-cards-standard-deck';
|
||||||
|
import { computedRefreshable } from '@/composable/computedRefreshable';
|
||||||
|
import { useCopy } from '@/composable/copy';
|
||||||
|
import { useQueryParamOrStorage } from '@/composable/queryParams';
|
||||||
|
import { randIntFromInterval } from '@/utils/random';
|
||||||
|
|
||||||
|
const cardKeys = Object.keys(cards);
|
||||||
|
type CardNames = keyof typeof cards;
|
||||||
|
|
||||||
|
const numberOfCards = useQueryParamOrStorage({ name: 'cards', storageName: 'card-picker:n', defaultValue: 5 });
|
||||||
|
const [cardPicked, refreshCardPicked] = computedRefreshable(() =>
|
||||||
|
Array.from({ length: numberOfCards.value },
|
||||||
|
() => cardKeys[randIntFromInterval(0, 51)]));
|
||||||
|
|
||||||
|
const suitNames = {
|
||||||
|
c: 'clubs (♣)',
|
||||||
|
d: 'diamonds (♦)',
|
||||||
|
h: 'hearts (♥)',
|
||||||
|
s: 'spades (♠)',
|
||||||
|
};
|
||||||
|
const numberNames = {
|
||||||
|
1: 'Ace',
|
||||||
|
11: 'Jack',
|
||||||
|
12: 'Queen',
|
||||||
|
13: 'King',
|
||||||
|
};
|
||||||
|
function translateName(cardId: string) {
|
||||||
|
const [, number, suit] = /(\d+)([cdhs])/.exec(cardId) || [];
|
||||||
|
if (!number && !suit) {
|
||||||
|
return cardId;
|
||||||
|
}
|
||||||
|
return `${numberNames[number as never] || number} of ${suitNames[suit as never] || suit}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cardPickedString = computed(() => cardPicked.value.map(translateName).join(', '));
|
||||||
|
|
||||||
|
const { copy } = useCopy({ source: cardPickedString, text: 'Cards Picked copied to the clipboard' });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<c-card>
|
||||||
|
<div mb-2 flex justify-center>
|
||||||
|
<img v-for="(card, index) in cardPicked" :key="index" style="width:90px" mr-1 :src="`data:image/svg+xml;base64,${cards[card as CardNames]}`">
|
||||||
|
</div>
|
||||||
|
<div mb-2>
|
||||||
|
<textarea-copyable :value="cardPickedString" readonly mb-1 />
|
||||||
|
</div>
|
||||||
|
<div flex justify-center gap-3>
|
||||||
|
<n-form-item label="Number of cards:" label-placement="left">
|
||||||
|
<n-input-number v-model:value="numberOfCards" min="1" placeholder="Width of the text" />
|
||||||
|
</n-form-item>
|
||||||
|
</div>
|
||||||
|
<div flex justify-center gap-3>
|
||||||
|
<c-button @click="copy()">
|
||||||
|
Copy deck
|
||||||
|
</c-button>
|
||||||
|
<c-button @click="refreshCardPicked">
|
||||||
|
Refresh deck
|
||||||
|
</c-button>
|
||||||
|
</div>
|
||||||
|
</c-card>
|
||||||
|
</template>
|
12
src/tools/card-picker/index.ts
Normal file
12
src/tools/card-picker/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { PlayCard } from '@vicons/tabler';
|
||||||
|
import { defineTool } from '../tool';
|
||||||
|
|
||||||
|
export const tool = defineTool({
|
||||||
|
name: 'Card Picker',
|
||||||
|
path: '/card-picker',
|
||||||
|
description: 'Generate a deck of playing cards',
|
||||||
|
keywords: ['card', 'deck', 'picker'],
|
||||||
|
component: () => import('./card-picker.vue'),
|
||||||
|
icon: PlayCard,
|
||||||
|
createdAt: new Date('2025-02-09'),
|
||||||
|
});
|
46
src/tools/coin-flipper/coin-flipper.vue
Normal file
46
src/tools/coin-flipper/coin-flipper.vue
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computedRefreshable } from '@/composable/computedRefreshable';
|
||||||
|
import { randIntFromInterval } from '@/utils/random';
|
||||||
|
|
||||||
|
const [coinFlip, refreshCoinFlip] = computedRefreshable(() => ({
|
||||||
|
coin: randIntFromInterval(0, 10) % 2 === 0 ? 'Heads' : 'Tails',
|
||||||
|
dt: Date.now(),
|
||||||
|
}));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Transition name="bounce" mode="out-in">
|
||||||
|
<div :key="coinFlip.dt" flex items-center justify-center>
|
||||||
|
<div flex items-center justify-center rounded-full outline style="width: 5em; height: 5em">
|
||||||
|
{{ coinFlip.coin }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
<div mt-4 flex justify-center>
|
||||||
|
<c-button @click="refreshCoinFlip">
|
||||||
|
Re flip
|
||||||
|
</c-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.bounce-enter-active {
|
||||||
|
animation: bounce-in 0.5s;
|
||||||
|
}
|
||||||
|
.bounce-leave-active {
|
||||||
|
animation: bounce-in 0.5s reverse;
|
||||||
|
}
|
||||||
|
@keyframes bounce-in {
|
||||||
|
0% {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.25);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
12
src/tools/coin-flipper/index.ts
Normal file
12
src/tools/coin-flipper/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Coin } from '@vicons/tabler';
|
||||||
|
import { defineTool } from '../tool';
|
||||||
|
|
||||||
|
export const tool = defineTool({
|
||||||
|
name: 'Coin Flipper',
|
||||||
|
path: '/coin-flipper',
|
||||||
|
description: 'Flip a coin',
|
||||||
|
keywords: ['coin', 'flipper'],
|
||||||
|
component: () => import('./coin-flipper.vue'),
|
||||||
|
icon: Coin,
|
||||||
|
createdAt: new Date('2025-02-09'),
|
||||||
|
});
|
66
src/tools/dice-roller/dice-roller.vue
Normal file
66
src/tools/dice-roller/dice-roller.vue
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { DiceRoll } from '@dice-roller/rpg-dice-roller';
|
||||||
|
import { computedRefreshable } from '@/composable/computedRefreshable';
|
||||||
|
import { useCopy } from '@/composable/copy';
|
||||||
|
import { useQueryParamOrStorage } from '@/composable/queryParams';
|
||||||
|
|
||||||
|
const dicesNotations = useQueryParamOrStorage({ name: 'dices', storageName: 'dice-roll:dices', defaultValue: '3d6' });
|
||||||
|
const [diceRollResult, refreshDiceRollResult] = computedRefreshable(() => {
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
error: '',
|
||||||
|
roll: new DiceRoll(dicesNotations.value),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (e: any) {
|
||||||
|
return {
|
||||||
|
error: e.toString(),
|
||||||
|
roll: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const diceRollString = computed(() => diceRollResult.value.roll?.output || '');
|
||||||
|
|
||||||
|
const { copy } = useCopy({ source: diceRollString, text: 'Dice Roll copied to the clipboard' });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<c-card>
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="dicesNotations"
|
||||||
|
label="Dice Roll Notations:" label-position="left"
|
||||||
|
placeholder="Dice configuration"
|
||||||
|
mb-2
|
||||||
|
/>
|
||||||
|
<n-p mb-2>
|
||||||
|
For more information about Dice Notation, see <n-a href="https://dice-roller.github.io/documentation/guide/notation/" target="_blank">
|
||||||
|
here
|
||||||
|
</n-a>
|
||||||
|
</n-p>
|
||||||
|
|
||||||
|
<c-alert v-if="diceRollResult.error" mb-2>
|
||||||
|
{{ diceRollResult.error }}
|
||||||
|
</c-alert>
|
||||||
|
|
||||||
|
<c-card v-if="!diceRollResult.error" title="Roll Result" mb-2>
|
||||||
|
<input-copyable :value="diceRollResult.roll?.output" readonly mb-1 />
|
||||||
|
<input-copyable :value="diceRollResult.roll?.total" label="Total" readonly placeholder="Dice Roll total:" label-position="left" mb-1 />
|
||||||
|
</c-card>
|
||||||
|
|
||||||
|
<div mb-2 flex justify-center gap-3>
|
||||||
|
<c-button @click="copy()">
|
||||||
|
Copy roll result
|
||||||
|
</c-button>
|
||||||
|
<c-button @click="refreshDiceRollResult">
|
||||||
|
Refresh roll
|
||||||
|
</c-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<c-card v-if="!diceRollResult.error" title="Dice Notation Stats" mb-2>
|
||||||
|
<input-copyable :value="diceRollResult.roll?.minTotal" readonly label="Min Total:" label-position="left" mb-1 />
|
||||||
|
<input-copyable :value="diceRollResult.roll?.maxTotal" readonly label="Max Total:" label-position="left" mb-1 />
|
||||||
|
<input-copyable :value="diceRollResult.roll?.averageTotal" readonly label="Avg Total:" label-position="left" mb-1 />
|
||||||
|
</c-card>
|
||||||
|
</c-card>
|
||||||
|
</template>
|
12
src/tools/dice-roller/index.ts
Normal file
12
src/tools/dice-roller/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Dice } from '@vicons/tabler';
|
||||||
|
import { defineTool } from '../tool';
|
||||||
|
|
||||||
|
export const tool = defineTool({
|
||||||
|
name: 'Dice Roller',
|
||||||
|
path: '/dice-roller',
|
||||||
|
description: 'RPG Dice Roller using Dice Notation',
|
||||||
|
keywords: ['dice', 'rng', 'rpg', 'roller'],
|
||||||
|
component: () => import('./dice-roller.vue'),
|
||||||
|
icon: Dice,
|
||||||
|
createdAt: new Date('2025-02-09'),
|
||||||
|
});
|
11
src/tools/fortune-wheel/fortune-wheel.e2e.spec.ts
Normal file
11
src/tools/fortune-wheel/fortune-wheel.e2e.spec.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
test.describe('Tool - Fortune wheel', () => {
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await page.goto('/fortune-wheel');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Has correct title', async ({ page }) => {
|
||||||
|
await expect(page).toHaveTitle('Fortune wheel - IT Tools');
|
||||||
|
});
|
||||||
|
});
|
85
src/tools/fortune-wheel/fortune-wheel.vue
Normal file
85
src/tools/fortune-wheel/fortune-wheel.vue
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { FortuneWheel } from 'vue3-fortune-wheel';
|
||||||
|
import type { Data, ImgParams } from 'vue3-fortune-wheel';
|
||||||
|
import { useQueryParamOrStorage } from '@/composable/queryParams';
|
||||||
|
import { computedRefreshable } from '@/composable/computedRefreshable';
|
||||||
|
|
||||||
|
const base = import.meta.env.BASE_URL;
|
||||||
|
|
||||||
|
const choices = useQueryParamOrStorage({ name: 'choices', storageName: 'fortune-wheel:chs', defaultValue: '' });
|
||||||
|
const spinDuration = useQueryParamOrStorage({ name: 'duration', storageName: 'fortune-wheel:dur', defaultValue: 5 });
|
||||||
|
|
||||||
|
const colors = [
|
||||||
|
{ bgColor: '#FF5733', color: '#FFFFFF' },
|
||||||
|
{ bgColor: '#2E86C1', color: '#FFFFFF' },
|
||||||
|
{ bgColor: '#28B463', color: '#FFFFFF' },
|
||||||
|
{ bgColor: '#F1C40F', color: '#000000' },
|
||||||
|
{ bgColor: '#8E44AD', color: '#FFFFFF' },
|
||||||
|
{ bgColor: '#E74C3C', color: '#FFFFFF' },
|
||||||
|
{ bgColor: '#1ABC9C', color: '#000000' },
|
||||||
|
{ bgColor: '#34495E', color: '#FFFFFF' },
|
||||||
|
{ bgColor: '#D35400', color: '#FFFFFF' },
|
||||||
|
{ bgColor: '#2C3E50', color: '#FFFFFF' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const wheel = ref<InstanceType<typeof FortuneWheel> | null>(null);
|
||||||
|
const data = computed(() => {
|
||||||
|
return (choices.value || '').split('\n')
|
||||||
|
.filter(s => s && s !== '')
|
||||||
|
.map((choice, index) => ({ id: index + 1, value: choice, ...colors[index % colors.length] }));
|
||||||
|
});
|
||||||
|
|
||||||
|
const logo: ImgParams = {
|
||||||
|
src: `${base}logo.png`,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
const [randomGift, refreshGift] = computedRefreshable(() => {
|
||||||
|
return Math.floor(Math.random() * data.value.length) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = ref<Data>();
|
||||||
|
function done(wheelResult: Data) {
|
||||||
|
result.value = wheelResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
function restart() {
|
||||||
|
refreshGift();
|
||||||
|
wheel.value?.spin();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<n-form-item label="Spin Duration (seconds):" label-placement="left">
|
||||||
|
<n-input-number v-model:value="spinDuration" :min="1" />
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="choices"
|
||||||
|
label="Wheel choices (one per line):"
|
||||||
|
placeholder="Wheel choices (one per line)"
|
||||||
|
multiline
|
||||||
|
rows="5"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<n-divider />
|
||||||
|
|
||||||
|
<FortuneWheel
|
||||||
|
ref="wheel"
|
||||||
|
v-model="randomGift"
|
||||||
|
middle-circle
|
||||||
|
:img-params="logo"
|
||||||
|
:anim-duration="spinDuration * 1000"
|
||||||
|
:data="data"
|
||||||
|
@done="done"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div flex justify-center>
|
||||||
|
<c-button @click="restart()">
|
||||||
|
Restart
|
||||||
|
</c-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
12
src/tools/fortune-wheel/index.ts
Normal file
12
src/tools/fortune-wheel/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { ArrowsShuffle } from '@vicons/tabler';
|
||||||
|
import { defineTool } from '../tool';
|
||||||
|
|
||||||
|
export const tool = defineTool({
|
||||||
|
name: 'Fortune wheel',
|
||||||
|
path: '/fortune-wheel',
|
||||||
|
description: '',
|
||||||
|
keywords: ['fortune', 'wheel'],
|
||||||
|
component: () => import('./fortune-wheel.vue'),
|
||||||
|
icon: ArrowsShuffle,
|
||||||
|
createdAt: new Date('2025-02-24'),
|
||||||
|
});
|
|
@ -2,6 +2,10 @@ import { tool as base64FileConverter } from './base64-file-converter';
|
||||||
import { tool as base64StringConverter } from './base64-string-converter';
|
import { tool as base64StringConverter } from './base64-string-converter';
|
||||||
import { tool as basicAuthGenerator } from './basic-auth-generator';
|
import { tool as basicAuthGenerator } from './basic-auth-generator';
|
||||||
import { tool as emailNormalizer } from './email-normalizer';
|
import { tool as emailNormalizer } from './email-normalizer';
|
||||||
|
import { tool as fortuneWheel } from './fortune-wheel';
|
||||||
|
import { tool as cardPicker } from './card-picker';
|
||||||
|
import { tool as coinFlipper } from './coin-flipper';
|
||||||
|
import { tool as diceRoller } from './dice-roller';
|
||||||
|
|
||||||
import { tool as asciiTextDrawer } from './ascii-text-drawer';
|
import { tool as asciiTextDrawer } from './ascii-text-drawer';
|
||||||
|
|
||||||
|
@ -168,7 +172,15 @@ export const toolsByCategory: ToolCategory[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Math',
|
name: 'Math',
|
||||||
components: [mathEvaluator, etaCalculator, percentageCalculator],
|
components: [
|
||||||
|
mathEvaluator,
|
||||||
|
etaCalculator,
|
||||||
|
percentageCalculator,
|
||||||
|
diceRoller,
|
||||||
|
coinFlipper,
|
||||||
|
cardPicker,
|
||||||
|
fortuneWheel,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Measurement',
|
name: 'Measurement',
|
||||||
|
|
|
@ -151,7 +151,7 @@ function onSearchInput() {
|
||||||
>
|
>
|
||||||
<div flex-1 truncate>
|
<div flex-1 truncate>
|
||||||
<slot name="displayed-value">
|
<slot name="displayed-value">
|
||||||
<input v-if="searchable && isOpen" ref="searchInputRef" v-model="searchQuery" type="text" placeholder="Search..." class="search-input" w-full lh-normal color-current @input="onSearchInput">
|
<input v-if="searchable && isOpen" ref="searchInputRef" v-model="searchQuery" type="text" placeholder="Search..." class="search-input" w-full color-current lh-normal @input="onSearchInput">
|
||||||
<span v-else-if="selectedOption" lh-normal>
|
<span v-else-if="selectedOption" lh-normal>
|
||||||
{{ selectedOption.label }}
|
{{ selectedOption.label }}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -39,7 +39,7 @@ const headers = computed(() => {
|
||||||
<template>
|
<template>
|
||||||
<div class="relative overflow-x-auto rounded">
|
<div class="relative overflow-x-auto rounded">
|
||||||
<table class="w-full border-collapse text-left text-sm text-gray-500 dark:text-gray-400" role="table" :aria-label="description">
|
<table class="w-full border-collapse text-left text-sm text-gray-500 dark:text-gray-400" role="table" :aria-label="description">
|
||||||
<thead v-if="!hideHeaders" class="bg-#ffffff uppercase text-gray-700 dark:bg-#333333 dark:text-gray-400" border-b="1px solid dark:transparent #efeff5">
|
<thead v-if="!hideHeaders" class="bg-#ffffff text-gray-700 uppercase dark:bg-#333333 dark:text-gray-400" border-b="1px solid dark:transparent #efeff5">
|
||||||
<tr>
|
<tr>
|
||||||
<th v-for="header in headers" :key="header.key" scope="col" class="px-6 py-3 text-xs">
|
<th v-for="header in headers" :key="header.key" scope="col" class="px-6 py-3 text-xs">
|
||||||
{{ header.label }}
|
{{ header.label }}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue