refactor(ui): getting ride of naive ui buttons
This commit is contained in:
		
							parent
							
								
									df989e24b3
								
							
						
					
					
						commit
						510fa8d0c3
					
				
							
								
								
									
										72
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										72
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -9,13 +9,62 @@ export {} | ||||
| 
 | ||||
| declare module '@vue/runtime-core' { | ||||
|   export interface GlobalComponents { | ||||
|     '404.page': typeof import('./src/pages/404.page.vue')['default'] | ||||
|     About: typeof import('./src/pages/About.vue')['default'] | ||||
|     App: typeof import('./src/App.vue')['default'] | ||||
|     'Base.layout': typeof import('./src/layouts/base.layout.vue')['default'] | ||||
|     Base64FileConverter: typeof import('./src/tools/base64-file-converter/base64-file-converter.vue')['default'] | ||||
|     Base64StringConverter: typeof import('./src/tools/base64-string-converter/base64-string-converter.vue')['default'] | ||||
|     BasicAuthGenerator: typeof import('./src/tools/basic-auth-generator/basic-auth-generator.vue')['default'] | ||||
|     Bcrypt: typeof import('./src/tools/bcrypt/bcrypt.vue')['default'] | ||||
|     BenchmarkBuilder: typeof import('./src/tools/benchmark-builder/benchmark-builder.vue')['default'] | ||||
|     Bip39Generator: typeof import('./src/tools/bip39-generator/bip39-generator.vue')['default'] | ||||
|     CaseConverter: typeof import('./src/tools/case-converter/case-converter.vue')['default'] | ||||
|     CButton: typeof import('./src/ui/c-button/c-button.vue')['default'] | ||||
|     ChmodCalculator: typeof import('./src/tools/chmod-calculator/chmod-calculator.vue')['default'] | ||||
|     Chronometer: typeof import('./src/tools/chronometer/chronometer.vue')['default'] | ||||
|     CLink: typeof import('./src/ui/c-link/c-link.vue')['default'] | ||||
|     CollapsibleToolMenu: typeof import('./src/components/CollapsibleToolMenu.vue')['default'] | ||||
|     ColorConverter: typeof import('./src/tools/color-converter/color-converter.vue')['default'] | ||||
|     ColoredCard: typeof import('./src/components/ColoredCard.vue')['default'] | ||||
|     CopyableIpLike: typeof import('./src/tools/ipv4-subnet-calculator/copyable-ip-like.vue')['default'] | ||||
|     CrontabGenerator: typeof import('./src/tools/crontab-generator/crontab-generator.vue')['default'] | ||||
|     DateTimeConverter: typeof import('./src/tools/date-time-converter/date-time-converter.vue')['default'] | ||||
|     DeviceInformation: typeof import('./src/tools/device-information/device-information.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'] | ||||
|     Editor: typeof import('./src/tools/html-wysiwyg-editor/editor/editor.vue')['default'] | ||||
|     Encryption: typeof import('./src/tools/encryption/encryption.vue')['default'] | ||||
|     EtaCalculator: typeof import('./src/tools/eta-calculator/eta-calculator.vue')['default'] | ||||
|     FavoriteButton: typeof import('./src/components/FavoriteButton.vue')['default'] | ||||
|     FormatTransformer: typeof import('./src/components/FormatTransformer.vue')['default'] | ||||
|     GitMemo: typeof import('./src/tools/git-memo/git-memo.md')['default'] | ||||
|     HashText: typeof import('./src/tools/hash-text/hash-text.vue')['default'] | ||||
|     HmacGenerator: typeof import('./src/tools/hmac-generator/hmac-generator.vue')['default'] | ||||
|     'Home.page': typeof import('./src/pages/Home.page.vue')['default'] | ||||
|     HtmlEntities: typeof import('./src/tools/html-entities/html-entities.vue')['default'] | ||||
|     HtmlWysiwygEditor: typeof import('./src/tools/html-wysiwyg-editor/html-wysiwyg-editor.vue')['default'] | ||||
|     HttpStatusCodes: typeof import('./src/tools/http-status-codes/http-status-codes.vue')['default'] | ||||
|     InputCopyable: typeof import('./src/components/InputCopyable.vue')['default'] | ||||
|     IntegerBaseConverter: typeof import('./src/tools/integer-base-converter/integer-base-converter.vue')['default'] | ||||
|     Ipv4AddressConverter: typeof import('./src/tools/ipv4-address-converter/ipv4-address-converter.vue')['default'] | ||||
|     Ipv4RangeExpander: typeof import('./src/tools/ipv4-range-expander/ipv4-range-expander.vue')['default'] | ||||
|     Ipv4SubnetCalculator: typeof import('./src/tools/ipv4-subnet-calculator/ipv4-subnet-calculator.vue')['default'] | ||||
|     Ipv6UlaGenerator: typeof import('./src/tools/ipv6-ula-generator/ipv6-ula-generator.vue')['default'] | ||||
|     JsonMinify: typeof import('./src/tools/json-minify/json-minify.vue')['default'] | ||||
|     JsonToYaml: typeof import('./src/tools/json-to-yaml-converter/json-to-yaml.vue')['default'] | ||||
|     JsonViewer: typeof import('./src/tools/json-viewer/json-viewer.vue')['default'] | ||||
|     JwtParser: typeof import('./src/tools/jwt-parser/jwt-parser.vue')['default'] | ||||
|     KeycodeInfo: typeof import('./src/tools/keycode-info/keycode-info.vue')['default'] | ||||
|     LoremIpsumGenerator: typeof import('./src/tools/lorem-ipsum-generator/lorem-ipsum-generator.vue')['default'] | ||||
|     MacAddressLookup: typeof import('./src/tools/mac-address-lookup/mac-address-lookup.vue')['default'] | ||||
|     MathEvaluator: typeof import('./src/tools/math-evaluator/math-evaluator.vue')['default'] | ||||
|     MenuBar: typeof import('./src/tools/html-wysiwyg-editor/editor/menu-bar.vue')['default'] | ||||
|     MenuBarItem: typeof import('./src/tools/html-wysiwyg-editor/editor/menu-bar-item.vue')['default'] | ||||
|     MenuIconItem: typeof import('./src/components/MenuIconItem.vue')['default'] | ||||
|     MenuLayout: typeof import('./src/components/MenuLayout.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'] | ||||
|     NAlert: typeof import('naive-ui')['NAlert'] | ||||
|     NAutoComplete: typeof import('naive-ui')['NAutoComplete'] | ||||
|     NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] | ||||
| @ -37,7 +86,6 @@ declare module '@vue/runtime-core' { | ||||
|     NH1: typeof import('naive-ui')['NH1'] | ||||
|     NH2: typeof import('naive-ui')['NH2'] | ||||
|     NH3: typeof import('naive-ui')['NH3'] | ||||
|     NH4: typeof import('naive-ui')['NH4'] | ||||
|     NIcon: typeof import('naive-ui')['NIcon'] | ||||
|     NImage: typeof import('naive-ui')['NImage'] | ||||
|     NInput: typeof import('naive-ui')['NInput'] | ||||
| @ -50,7 +98,6 @@ declare module '@vue/runtime-core' { | ||||
|     NP: typeof import('naive-ui')['NP'] | ||||
|     NPageHeader: typeof import('naive-ui')['NPageHeader'] | ||||
|     NProgress: typeof import('naive-ui')['NProgress'] | ||||
|     NResult: typeof import('naive-ui')['NResult'] | ||||
|     NScrollbar: typeof import('naive-ui')['NScrollbar'] | ||||
|     NSelect: typeof import('naive-ui')['NSelect'] | ||||
|     NSlider: typeof import('naive-ui')['NSlider'] | ||||
| @ -63,12 +110,33 @@ declare module '@vue/runtime-core' { | ||||
|     NTooltip: typeof import('naive-ui')['NTooltip'] | ||||
|     NUpload: typeof import('naive-ui')['NUpload'] | ||||
|     NUploadDragger: typeof import('naive-ui')['NUploadDragger'] | ||||
|     OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] | ||||
|     QrCodeGenerator: typeof import('./src/tools/qr-code-generator/qr-code-generator.vue')['default'] | ||||
|     RandomPortGenerator: typeof import('./src/tools/random-port-generator/random-port-generator.vue')['default'] | ||||
|     ResultRow: typeof import('./src/tools/ipv4-range-expander/result-row.vue')['default'] | ||||
|     RomanNumeralConverter: typeof import('./src/tools/roman-numeral-converter/roman-numeral-converter.vue')['default'] | ||||
|     RouterLink: typeof import('vue-router')['RouterLink'] | ||||
|     RouterView: typeof import('vue-router')['RouterView'] | ||||
|     RsaKeyPairGenerator: typeof import('./src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue')['default'] | ||||
|     SearchBar: typeof import('./src/components/SearchBar.vue')['default'] | ||||
|     SearchBarItem: typeof import('./src/components/SearchBarItem.vue')['default'] | ||||
|     SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default'] | ||||
|     SpanCopyable: typeof import('./src/components/SpanCopyable.vue')['default'] | ||||
|     SqlPrettify: typeof import('./src/tools/sql-prettify/sql-prettify.vue')['default'] | ||||
|     SvgPlaceholderGenerator: typeof import('./src/tools/svg-placeholder-generator/svg-placeholder-generator.vue')['default'] | ||||
|     TemperatureConverter: typeof import('./src/tools/temperature-converter/temperature-converter.vue')['default'] | ||||
|     TextareaCopyable: typeof import('./src/components/TextareaCopyable.vue')['default'] | ||||
|     TextStatistics: typeof import('./src/tools/text-statistics/text-statistics.vue')['default'] | ||||
|     TextToNatoAlphabet: typeof import('./src/tools/text-to-nato-alphabet/text-to-nato-alphabet.vue')['default'] | ||||
|     TokenDisplay: typeof import('./src/tools/otp-code-generator-and-validator/token-display.vue')['default'] | ||||
|     'TokenGenerator.tool': typeof import('./src/tools/token-generator/token-generator.tool.vue')['default'] | ||||
|     'Tool.layout': typeof import('./src/layouts/tool.layout.vue')['default'] | ||||
|     ToolCard: typeof import('./src/components/ToolCard.vue')['default'] | ||||
|     UrlEncoder: typeof import('./src/tools/url-encoder/url-encoder.vue')['default'] | ||||
|     UrlParser: typeof import('./src/tools/url-parser/url-parser.vue')['default'] | ||||
|     UserAgentParser: typeof import('./src/tools/user-agent-parser/user-agent-parser.vue')['default'] | ||||
|     UserAgentResultCards: typeof import('./src/tools/user-agent-parser/user-agent-result-cards.vue')['default'] | ||||
|     UuidGenerator: typeof import('./src/tools/uuid-generator/uuid-generator.vue')['default'] | ||||
|     YamlToJson: typeof import('./src/tools/yaml-to-json-converter/yaml-to-json.vue')['default'] | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -1,11 +1,15 @@ | ||||
| <template> | ||||
|   <n-tooltip trigger="hover"> | ||||
|     <template #trigger> | ||||
|       <n-button circle quaternary :type="buttonType" :style="{ opacity: isFavorite ? 1 : 0.2 }" @click="toggleFavorite"> | ||||
|         <template #icon> | ||||
|           <n-icon :component="FavoriteFilled" /> | ||||
|         </template> | ||||
|       </n-button> | ||||
|       <c-button | ||||
|         variant="text" | ||||
|         circle | ||||
|         :type="buttonType" | ||||
|         :style="{ opacity: isFavorite ? 1 : 0.2 }" | ||||
|         @click="toggleFavorite" | ||||
|       > | ||||
|         <n-icon :component="FavoriteFilled" /> | ||||
|       </c-button> | ||||
|     </template> | ||||
|     {{ isFavorite ? 'Remove from favorites' : 'Add to favorites' }} | ||||
|   </n-tooltip> | ||||
|  | ||||
| @ -3,9 +3,9 @@ | ||||
|     <template #suffix> | ||||
|       <n-tooltip trigger="hover"> | ||||
|         <template #trigger> | ||||
|           <n-button quaternary circle @click="onCopyClicked"> | ||||
|           <c-button circle variant="text" @click="onCopyClicked"> | ||||
|             <n-icon :component="ContentCopyFilled" /> | ||||
|           </n-button> | ||||
|           </c-button> | ||||
|         </template> | ||||
|         {{ tooltipText }} | ||||
|       </n-tooltip> | ||||
|  | ||||
| @ -1,56 +1,50 @@ | ||||
| <template> | ||||
|   <n-tooltip trigger="hover"> | ||||
|     <template #trigger> | ||||
|       <n-button | ||||
|         size="large" | ||||
|       <c-button | ||||
|         circle | ||||
|         quaternary | ||||
|         tag="a" | ||||
|         variant="text" | ||||
|         href="https://github.com/CorentinTh/it-tools" | ||||
|         rel="noopener" | ||||
|         target="_blank" | ||||
|         rel="noopener noreferrer" | ||||
|         aria-label="IT-Tools' GitHub repository" | ||||
|       > | ||||
|         <n-icon size="25" :component="BrandGithub" /> | ||||
|       </n-button> | ||||
|       </c-button> | ||||
|     </template> | ||||
|     Github repository | ||||
|   </n-tooltip> | ||||
| 
 | ||||
|   <n-tooltip trigger="hover"> | ||||
|     <template #trigger> | ||||
|       <n-button | ||||
|         size="large" | ||||
|       <c-button | ||||
|         circle | ||||
|         quaternary | ||||
|         tag="a" | ||||
|         variant="text" | ||||
|         href="https://twitter.com/ittoolsdottech" | ||||
|         rel="noopener" | ||||
|         target="_blank" | ||||
|         aria-label="IT Tools' Twitter account" | ||||
|       > | ||||
|         <n-icon size="25" :component="BrandTwitter" /> | ||||
|       </n-button> | ||||
|       </c-button> | ||||
|     </template> | ||||
|     IT Tools' Twitter account | ||||
|   </n-tooltip> | ||||
| 
 | ||||
|   <router-link to="/about" #="{ navigate, href }" custom> | ||||
|     <n-tooltip trigger="hover"> | ||||
|       <template #trigger> | ||||
|         <n-button tag="a" :href="href" circle quaternary size="large" aria-label="About" @click="navigate"> | ||||
|           <n-icon size="25" :component="InfoCircle" /> | ||||
|         </n-button> | ||||
|       </template> | ||||
|       About | ||||
|     </n-tooltip> | ||||
|   </router-link> | ||||
|   <n-tooltip trigger="hover"> | ||||
|     <template #trigger> | ||||
|       <n-button size="large" circle quaternary aria-label="Toggle dark/light mode" @click="isDarkTheme = !isDarkTheme"> | ||||
|       <c-button circle variant="text" to="/about" aria-label="About"> | ||||
|         <n-icon size="25" :component="InfoCircle" /> | ||||
|       </c-button> | ||||
|     </template> | ||||
|     About | ||||
|   </n-tooltip> | ||||
|   <n-tooltip trigger="hover"> | ||||
|     <template #trigger> | ||||
|       <c-button circle variant="text" aria-label="Toggle dark/light mode" @click="toggleDarkTheme"> | ||||
|         <n-icon v-if="isDarkTheme" size="25" :component="Sun" /> | ||||
|         <n-icon v-else size="25" :component="Moon" /> | ||||
|       </n-button> | ||||
|       </c-button> | ||||
|     </template> | ||||
|     <span v-if="isDarkTheme">Light mode</span> | ||||
|     <span v-else>Dark mode</span> | ||||
| @ -59,11 +53,20 @@ | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { useStyleStore } from '@/stores/style.store'; | ||||
| import { useThemeStore } from '@/ui/theme/theme.store'; | ||||
| import { BrandGithub, BrandTwitter, InfoCircle, Moon, Sun } from '@vicons/tabler'; | ||||
| import { toRefs } from 'vue'; | ||||
| 
 | ||||
| const styleStore = useStyleStore(); | ||||
| const { isDarkTheme } = toRefs(styleStore); | ||||
| 
 | ||||
| const themeStore = useThemeStore(); | ||||
| 
 | ||||
| function toggleDarkTheme() { | ||||
|   isDarkTheme.value = !isDarkTheme.value; | ||||
| 
 | ||||
|   themeStore.toggleTheme(); | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style lang="less" scoped> | ||||
|  | ||||
| @ -13,16 +13,16 @@ | ||||
|       <n-tooltip v-if="value" trigger="hover"> | ||||
|         <template #trigger> | ||||
|           <div class="copy-button" :class="[copyPlacement]"> | ||||
|             <n-button circle secondary size="large" @click="onCopyClicked"> | ||||
|             <c-button circle important:h-10 important:w-10 @click="onCopyClicked"> | ||||
|               <n-icon size="22" :component="Copy" /> | ||||
|             </n-button> | ||||
|             </c-button> | ||||
|           </div> | ||||
|         </template> | ||||
|         <span>{{ tooltipText }}</span> | ||||
|       </n-tooltip> | ||||
|     </n-card> | ||||
|     <n-space v-if="copyPlacement === 'outside'" justify="center" mt-4> | ||||
|       <n-button secondary @click="onCopyClicked"> {{ tooltipText }} </n-button> | ||||
|       <c-button @click="onCopyClicked"> {{ tooltipText }} </c-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -53,38 +53,25 @@ const tools = computed<ToolCategory[]>(() => [ | ||||
|           <div> | ||||
|             IT-Tools | ||||
| 
 | ||||
|             <n-button | ||||
|               text | ||||
|               tag="a" | ||||
|               target="_blank" | ||||
|               rel="noopener" | ||||
|               type="primary" | ||||
|               depth="3" | ||||
|               :href="`https://github.com/CorentinTh/it-tools/tree/v${version}`" | ||||
|             > | ||||
|             <c-link target="_blank" rel="noopener" :href="`https://github.com/CorentinTh/it-tools/tree/v${version}`"> | ||||
|               v{{ version }} | ||||
|             </n-button> | ||||
|             </c-link> | ||||
| 
 | ||||
|             <template v-if="commitSha && commitSha.length > 0"> | ||||
|               - | ||||
|               <n-button | ||||
|                 text | ||||
|                 tag="a" | ||||
|               <c-link | ||||
|                 target="_blank" | ||||
|                 rel="noopener" | ||||
|                 type="primary" | ||||
|                 depth="3" | ||||
|                 :href="`https://github.com/CorentinTh/it-tools/tree/${commitSha}`" | ||||
|               > | ||||
|                 {{ commitSha }} | ||||
|               </n-button> | ||||
|               </c-link> | ||||
|             </template> | ||||
|           </div> | ||||
|           <div> | ||||
|             © {{ new Date().getFullYear() }} | ||||
|             <n-button text tag="a" target="_blank" rel="noopener" type="primary" href="https://github.com/CorentinTh"> | ||||
|               Corentin Thomasset | ||||
|             </n-button> | ||||
|             <c-link target="_blank" rel="noopener" href="https://github.com/CorentinTh"> Corentin Thomasset </c-link> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
| @ -92,34 +79,24 @@ const tools = computed<ToolCategory[]>(() => [ | ||||
| 
 | ||||
|     <template #content> | ||||
|       <div class="navigation"> | ||||
|         <n-button | ||||
|         <c-button | ||||
|           :size="styleStore.isSmallScreen ? 'medium' : 'large'" | ||||
|           circle | ||||
|           quaternary | ||||
|           variant="text" | ||||
|           aria-label="Toggle menu" | ||||
|           @click="styleStore.isMenuCollapsed = !styleStore.isMenuCollapsed" | ||||
|         > | ||||
|           <n-icon size="25" :component="Menu2" /> | ||||
|         </n-button> | ||||
|         </c-button> | ||||
| 
 | ||||
|         <router-link to="/" #="{ navigate, href }" custom> | ||||
|           <n-tooltip trigger="hover"> | ||||
|             <template #trigger> | ||||
|               <n-button | ||||
|                 tag="a" | ||||
|                 :href="href" | ||||
|                 :size="styleStore.isSmallScreen ? 'medium' : 'large'" | ||||
|                 circle | ||||
|                 quaternary | ||||
|                 aria-label="Home" | ||||
|                 @click="navigate" | ||||
|               > | ||||
|                 <n-icon size="25" :component="Home2" /> | ||||
|               </n-button> | ||||
|             </template> | ||||
|             Home | ||||
|           </n-tooltip> | ||||
|         </router-link> | ||||
|         <n-tooltip trigger="hover"> | ||||
|           <template #trigger> | ||||
|             <c-button to="/" circle variant="text" aria-label="Home"> | ||||
|               <n-icon size="25" :component="Home2" /> | ||||
|             </c-button> | ||||
|           </template> | ||||
|           Home | ||||
|         </n-tooltip> | ||||
| 
 | ||||
|         <search-bar /> | ||||
| 
 | ||||
| @ -127,10 +104,8 @@ const tools = computed<ToolCategory[]>(() => [ | ||||
| 
 | ||||
|         <n-tooltip trigger="hover"> | ||||
|           <template #trigger> | ||||
|             <n-button | ||||
|             <c-button | ||||
|               round | ||||
|               type="primary" | ||||
|               tag="a" | ||||
|               href="https://www.buymeacoffee.com/cthmsst" | ||||
|               rel="noopener" | ||||
|               target="_blank" | ||||
| @ -140,7 +115,7 @@ const tools = computed<ToolCategory[]>(() => [ | ||||
|             > | ||||
|               Buy me a coffee | ||||
|               <n-icon v-if="!styleStore.isSmallScreen" :component="Heart" ml-2 /> | ||||
|             </n-button> | ||||
|             </c-button> | ||||
|           </template> | ||||
|           ❤ Support IT Tools development ! | ||||
|         </n-tooltip> | ||||
| @ -165,8 +140,8 @@ const tools = computed<ToolCategory[]>(() => [ | ||||
| .support-button { | ||||
|   background: rgb(37, 99, 108); | ||||
|   background: linear-gradient(48deg, rgba(37, 99, 108, 1) 0%, rgba(59, 149, 111, 1) 60%, rgba(20, 160, 88, 1) 100%); | ||||
|   color: #fff; | ||||
|   transition: all ease 0.2s; | ||||
|   color: #fff !important; | ||||
|   transition: padding ease 0.2s !important; | ||||
| 
 | ||||
|   &:hover { | ||||
|     color: #fff; | ||||
|  | ||||
| @ -13,8 +13,6 @@ useHead({ title: 'Page not found - IT Tools' }); | ||||
|     <n-text mt-4 block depth="3">Sorry, this page does not seem to exist</n-text> | ||||
|     <n-text mb-8 block depth="3">Maybe the cache is doing tricky things, try force-refreshing?</n-text> | ||||
| 
 | ||||
|     <router-link to="/" #="{ navigate, href }" custom> | ||||
|       <n-button tag="a" :href="href" secondary @click="navigate"> Back home </n-button> | ||||
|     </router-link> | ||||
|     <c-button to="/"> Back home </c-button> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -11,25 +11,21 @@ const { tracker } = useTracker(); | ||||
|     <n-h1>About</n-h1> | ||||
|     <n-p> | ||||
|       This wonderful website, made with ❤ by | ||||
|       <n-button text tag="a" href="https://github.com/CorentinTh" target="_blank" rel="noopener" type="primary"> | ||||
|         Corentin Thomasset </n-button | ||||
|       >, aggregates useful tools for developer and people working in IT. If you find it useful, please fell free to | ||||
|       share it to people you think may find it useful too and don't forget to pin it in your shortcut bar ! | ||||
|       <c-link href="https://github.com/CorentinTh" target="_blank" rel="noopener"> Corentin Thomasset </c-link>, | ||||
|       aggregates useful tools for developer and people working in IT. If you find it useful, please fell free to share | ||||
|       it to people you think may find it useful too and don't forget to pin it in your shortcut bar ! | ||||
|     </n-p> | ||||
|     <n-p> | ||||
|       IT Tools is open-source (under the MIT license) and free, and will always be, but it cost me money to host and | ||||
|       renew the domain name, if you want to support my work, and encourage me to add more tools, please consider | ||||
|       supporting by | ||||
|       <n-button | ||||
|         type="primary" | ||||
|         tag="a" | ||||
|         text | ||||
|       <c-link | ||||
|         href="https://www.buymeacoffee.com/cthmsst" | ||||
|         rel="noopener" | ||||
|         target="_blank" | ||||
|         @click="() => tracker.trackEvent({ eventName: 'Support button clicked' })" | ||||
|       > | ||||
|         sponsoring me </n-button | ||||
|         sponsoring me </c-link | ||||
|       >. | ||||
|     </n-p> | ||||
| 
 | ||||
| @ -37,16 +33,9 @@ const { tracker } = useTracker(); | ||||
|     <n-p> | ||||
|       IT Tools is made in Vue JS (vue 3) with the the naive-ui component library and is hosted and continuously deployed | ||||
|       by Vercel. Third party open-source libraries are used in some tools, you may find the complete list in the | ||||
|       <n-button | ||||
|         type="primary" | ||||
|         tag="a" | ||||
|         text | ||||
|         href="https://github.com/CorentinTh/it-tools/blob/main/package.json" | ||||
|         rel="noopener" | ||||
|         target="_blank" | ||||
|       > | ||||
|       <c-link href="https://github.com/CorentinTh/it-tools/blob/main/package.json" rel="noopener" target="_blank"> | ||||
|         package.json | ||||
|       </n-button> | ||||
|       </c-link> | ||||
|       file of the repository. | ||||
|     </n-p> | ||||
| 
 | ||||
| @ -54,30 +43,24 @@ const { tracker } = useTracker(); | ||||
|     <n-p> | ||||
|       If you need a tool that is currently not present here, and you think can be relevant, you are welcome to submit a | ||||
|       feature request in the | ||||
|       <n-button | ||||
|         type="primary" | ||||
|         tag="a" | ||||
|         text | ||||
|       <c-link | ||||
|         href="https://github.com/CorentinTh/it-tools/issues/new?assignees=CorentinTh&labels=enhancement&template=feature_request.md&title=%5BFEAT%5D%20My%20feature" | ||||
|         rel="noopener" | ||||
|         target="_blank" | ||||
|       > | ||||
|         issues section | ||||
|       </n-button> | ||||
|       </c-link> | ||||
|       in the GitHub repository. | ||||
|     </n-p> | ||||
|     <n-p> | ||||
|       And if you found a bug, or something broken that doesn't work as expected, please fill a bug report in the | ||||
|       <n-button | ||||
|         type="primary" | ||||
|         tag="a" | ||||
|         text | ||||
|       <c-link | ||||
|         href="https://github.com/CorentinTh/it-tools/issues/new?assignees=CorentinTh&labels=bug&template=bug_report.md&title=%5BBUG%5D%20My%20bug" | ||||
|         rel="noopener" | ||||
|         target="_blank" | ||||
|       > | ||||
|         issues section | ||||
|       </n-button> | ||||
|       </c-link> | ||||
|       in the GitHub repository. | ||||
|     </n-p> | ||||
|   </div> | ||||
|  | ||||
| @ -8,9 +8,9 @@ | ||||
|       <n-input v-model:value="base64Input" type="textarea" placeholder="Put your base64 file string here..." rows="5" /> | ||||
|     </n-form-item> | ||||
|     <n-space justify="center"> | ||||
|       <n-button :disabled="base64Input === '' || !base64InputValidation.isValid" secondary @click="downloadFile()"> | ||||
|       <c-button :disabled="base64Input === '' || !base64InputValidation.isValid" @click="downloadFile()"> | ||||
|         Download file | ||||
|       </n-button> | ||||
|       </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
| 
 | ||||
| @ -26,7 +26,7 @@ | ||||
| 
 | ||||
|     <n-input :value="fileBase64" type="textarea" readonly placeholder="File in base64 will be here" /> | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copyFileBase64()"> Copy </n-button> | ||||
|       <c-button @click="copyFileBase64()"> Copy </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
| </template> | ||||
|  | ||||
| @ -15,7 +15,7 @@ | ||||
|     </n-form-item> | ||||
| 
 | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copyTextBase64()"> Copy base64 </n-button> | ||||
|       <c-button @click="copyTextBase64()"> Copy base64 </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
| 
 | ||||
| @ -29,7 +29,7 @@ | ||||
|     </n-form-item> | ||||
| 
 | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copyText()"> Copy decoded string </n-button> | ||||
|       <c-button @click="copyText()"> Copy decoded string </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
| </template> | ||||
|  | ||||
| @ -23,7 +23,7 @@ | ||||
|     </n-card> | ||||
|     <br /> | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copy">Copy header</n-button> | ||||
|       <c-button @click="copy">Copy header</c-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -18,7 +18,7 @@ | ||||
|     </n-form> | ||||
|     <br /> | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copy"> Copy hash </n-button> | ||||
|       <c-button @click="copy"> Copy hash </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
| 
 | ||||
|  | ||||
| @ -14,18 +14,17 @@ | ||||
|         </n-card> | ||||
| 
 | ||||
|         <n-space justify="center"> | ||||
|           <n-button v-if="suites.length > 1" quaternary @click="suites.splice(index, 1)"> | ||||
|             <template #icon> | ||||
|               <n-icon :component="Trash" depth="3" /> | ||||
|             </template> | ||||
|           <c-button v-if="suites.length > 1" variant="text" @click="suites.splice(index, 1)"> | ||||
|             <n-icon :component="Trash" depth="3" mr-2 size="18" /> | ||||
|             Delete suite | ||||
|           </n-button> | ||||
|           <n-button quaternary @click="suites.splice(index + 1, 0, { data: [0], title: `Suite ${suites.length + 1}` })"> | ||||
|             <template #icon> | ||||
|               <n-icon :component="Plus" depth="3" /> | ||||
|             </template> | ||||
|           </c-button> | ||||
|           <c-button | ||||
|             variant="text" | ||||
|             @click="suites.splice(index + 1, 0, { data: [0], title: `Suite ${suites.length + 1}` })" | ||||
|           > | ||||
|             <n-icon :component="Plus" depth="3" mr-2 size="18" /> | ||||
|             Add suite | ||||
|           </n-button> | ||||
|           </c-button> | ||||
|         </n-space> | ||||
|       </div> | ||||
|     </n-space> | ||||
| @ -39,15 +38,14 @@ | ||||
|           <n-input v-model:value="unit" placeholder="Unit (eg: ms)" /> | ||||
|         </n-form-item> | ||||
| 
 | ||||
|         <n-button | ||||
|           tertiary | ||||
|         <c-button | ||||
|           @click=" | ||||
|             suites = [ | ||||
|               { title: 'Suite 1', data: [] }, | ||||
|               { title: 'Suite 2', data: [] }, | ||||
|             ] | ||||
|           " | ||||
|           >Reset suites</n-button | ||||
|           >Reset suites</c-button | ||||
|         > | ||||
|       </n-space> | ||||
| 
 | ||||
| @ -73,8 +71,8 @@ | ||||
|       </n-table> | ||||
|       <br /> | ||||
|       <n-space justify="center"> | ||||
|         <n-button tertiary @click="copyAsMarkdown">Copy as markdown table</n-button> | ||||
|         <n-button tertiary @click="copyAsBulletList">Copy as bullet list</n-button> | ||||
|         <c-button @click="copyAsMarkdown">Copy as markdown table</c-button> | ||||
|         <c-button @click="copyAsBulletList">Copy as bullet list</c-button> | ||||
|       </n-space> | ||||
|     </div> | ||||
|   </div> | ||||
|  | ||||
| @ -11,22 +11,18 @@ | ||||
|       /> | ||||
|       <n-tooltip> | ||||
|         <template #trigger> | ||||
|           <n-button circle quaternary @click="values.splice(index, 1)"> | ||||
|             <template #icon> | ||||
|               <n-icon :component="Trash" depth="3" /> | ||||
|             </template> | ||||
|           </n-button> | ||||
|           <c-button circle variant="text" @click="values.splice(index, 1)"> | ||||
|             <n-icon :component="Trash" depth="3" size="18" /> | ||||
|           </c-button> | ||||
|         </template> | ||||
|         Delete value | ||||
|       </n-tooltip> | ||||
|     </n-space> | ||||
| 
 | ||||
|     <n-button tertiary @click="addValue"> | ||||
|       <template #icon> | ||||
|         <n-icon :component="Plus" /> | ||||
|       </template> | ||||
|     <c-button @click="addValue"> | ||||
|       <n-icon :component="Plus" depth="3" mr-2 size="18" /> | ||||
|       Add a measure | ||||
|     </n-button> | ||||
|     </c-button> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
|  | ||||
| @ -18,16 +18,16 @@ | ||||
|           > | ||||
|             <n-input-group> | ||||
|               <n-input v-model:value="entropy" placeholder="Your string..." /> | ||||
|               <n-button @click="refreshEntropy"> | ||||
|               <c-button @click="refreshEntropy"> | ||||
|                 <n-icon size="22"> | ||||
|                   <Refresh /> | ||||
|                 </n-icon> | ||||
|               </n-button> | ||||
|               <n-button @click="copyEntropy"> | ||||
|               </c-button> | ||||
|               <c-button @click="copyEntropy"> | ||||
|                 <n-icon size="22"> | ||||
|                   <Copy /> | ||||
|                 </n-icon> | ||||
|               </n-button> | ||||
|               </c-button> | ||||
|             </n-input-group> | ||||
|           </n-form-item> | ||||
|         </n-gi> | ||||
| @ -48,9 +48,9 @@ | ||||
|             spellcheck="false" | ||||
|           /> | ||||
| 
 | ||||
|           <n-button @click="copyPassphrase"> | ||||
|           <c-button @click="copyPassphrase"> | ||||
|             <n-icon size="22" :component="Copy" /> | ||||
|           </n-button> | ||||
|           </c-button> | ||||
|         </n-input-group> | ||||
|       </n-form-item> | ||||
|     </n-card> | ||||
|  | ||||
| @ -5,10 +5,10 @@ | ||||
|     </n-card> | ||||
|     <br /> | ||||
|     <n-space justify="center"> | ||||
|       <n-button v-if="!isRunning" secondary type="primary" @click="resume">Start</n-button> | ||||
|       <n-button v-else secondary type="warning" @click="pause">Stop</n-button> | ||||
|       <c-button v-if="!isRunning" secondary type="primary" @click="resume">Start</c-button> | ||||
|       <c-button v-else secondary type="warning" @click="pause">Stop</c-button> | ||||
| 
 | ||||
|       <n-button secondary @click="counter = 0">Reset</n-button> | ||||
|       <c-button @click="counter = 0">Reset</c-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -16,7 +16,7 @@ | ||||
|     <br /> | ||||
|     <br /> | ||||
|     <n-space justify="center"> | ||||
|       <n-button :disabled="dockerCompose === ''" secondary @click="download"> Download docker-compose.yml </n-button> | ||||
|       <c-button :disabled="dockerCompose === ''" secondary @click="download"> Download docker-compose.yml </c-button> | ||||
|     </n-space> | ||||
| 
 | ||||
|     <div v-if="notComposable.length > 0"> | ||||
|  | ||||
| @ -43,7 +43,7 @@ | ||||
|       <n-input readonly :value="hmac" type="textarea" placeholder="The result of the HMAC..." /> | ||||
|     </n-form-item> | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copy()">Copy HMAC</n-button> | ||||
|       <c-button @click="copy()">Copy HMAC</c-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -20,7 +20,7 @@ | ||||
|     </n-form-item> | ||||
| 
 | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copyEscaped"> Copy </n-button> | ||||
|       <c-button @click="copyEscaped"> Copy </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
|   <n-card title="Unescape html entities"> | ||||
| @ -44,7 +44,7 @@ | ||||
|     </n-form-item> | ||||
| 
 | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copyUnescaped"> Copy </n-button> | ||||
|       <c-button @click="copyUnescaped"> Copy </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
| </template> | ||||
|  | ||||
| @ -1,11 +1,9 @@ | ||||
| <template> | ||||
|   <n-tooltip trigger="hover"> | ||||
|     <template #trigger> | ||||
|       <n-button circle quaternary :type="isActive?.() ? 'primary' : 'default'" @click="action"> | ||||
|         <template #icon> | ||||
|           <n-icon :component="icon" /> | ||||
|         </template> | ||||
|       </n-button> | ||||
|       <c-button circle variant="text" :type="isActive?.() ? 'primary' : 'default'" @click="action"> | ||||
|         <n-icon :component="icon" /> | ||||
|       </c-button> | ||||
|     </template> | ||||
| 
 | ||||
|     {{ title }} | ||||
|  | ||||
| @ -39,10 +39,10 @@ | ||||
|               The end IPv4 address is lower than the start IPv4 address. This is not valid and no result could be | ||||
|               calculated. In the most cases the solution to solve this problem is to change start and end address. | ||||
|             </n-text> | ||||
|             <n-button quaternary @click="onSwitchStartEndClicked"> | ||||
|               <n-icon :component="ChangeCircleOutlined" /> | ||||
|                 Switch start and end IPv4 address | ||||
|             </n-button> | ||||
|             <c-button @click="onSwitchStartEndClicked"> | ||||
|               <n-icon mr-2 :component="Exchange" depth="3" size="22" /> | ||||
|               Switch start and end IPv4 address | ||||
|             </c-button> | ||||
|           </n-space> | ||||
|         </n-alert> | ||||
|       </div> | ||||
| @ -52,7 +52,7 @@ | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { useValidation } from '@/composable/validation'; | ||||
| import { ChangeCircleOutlined } from '@vicons/material'; | ||||
| import { Exchange } from '@vicons/tabler'; | ||||
| import { isValidIpv4 } from '../ipv4-address-converter/ipv4-address-converter.service'; | ||||
| import type { Ipv4RangeExpanderResult } from './ipv4-range-expander.types'; | ||||
| import { calculateCidr } from './ipv4-range-expander.service'; | ||||
|  | ||||
| @ -20,14 +20,14 @@ | ||||
|       </n-table> | ||||
| 
 | ||||
|       <n-space style="margin-top: 14px" justify="space-between"> | ||||
|         <n-button tertiary @click="switchToBlock({ count: -1 })"> | ||||
|         <c-button @click="switchToBlock({ count: -1 })"> | ||||
|           <n-icon :component="ArrowLeft" /> | ||||
|           Previous block | ||||
|         </n-button> | ||||
|         <n-button tertiary @click="switchToBlock({ count: 1 })"> | ||||
|         </c-button> | ||||
|         <c-button @click="switchToBlock({ count: 1 })"> | ||||
|           Next block | ||||
|           <n-icon :component="ArrowRight" /> | ||||
|         </n-button> | ||||
|         </c-button> | ||||
|       </n-space> | ||||
|     </div> | ||||
|   </div> | ||||
|  | ||||
| @ -22,7 +22,7 @@ | ||||
|     <br /> | ||||
|     <br /> | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary autofocus @click="copy"> Copy </n-button> | ||||
|       <c-button autofocus @click="copy"> Copy </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
| </template> | ||||
|  | ||||
| @ -24,7 +24,7 @@ | ||||
|     </n-form-item> | ||||
| 
 | ||||
|     <n-space justify="center"> | ||||
|       <n-button :disabled="!details" tertiary> Copy vendor info </n-button> | ||||
|       <c-button :disabled="!details"> Copy vendor info </c-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -5,9 +5,9 @@ | ||||
|         <template #suffix> | ||||
|           <n-tooltip trigger="hover"> | ||||
|             <template #trigger> | ||||
|               <n-button quaternary circle @click="refreshSecret"> | ||||
|               <c-button circle variant="text" @click="refreshSecret"> | ||||
|                 <n-icon :component="Refresh" /> | ||||
|               </n-button> | ||||
|               </c-button> | ||||
|             </template> | ||||
|             Generate secret token | ||||
|           </n-tooltip> | ||||
| @ -23,7 +23,7 @@ | ||||
|     </div> | ||||
|     <n-space justify="center" vertical align="center" style="margin-top: 10px"> | ||||
|       <n-image :src="qrcode"></n-image> | ||||
|       <n-button secondary tag="a" :href="keyUri" target="_blank">Open Key URI in new tab</n-button> | ||||
|       <c-button :href="keyUri" target="_blank">Open Key URI in new tab</c-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
|   <div style="max-width: 350px"> | ||||
|  | ||||
| @ -8,31 +8,30 @@ | ||||
|     <n-input-group> | ||||
|       <n-tooltip trigger="hover" placement="bottom"> | ||||
|         <template #trigger> | ||||
|           <n-button data-test-id="previous-otp" secondary @click.prevent="copyPrevious(tokens.previous)">{{ | ||||
|             tokens.previous | ||||
|           }}</n-button> | ||||
|           <c-button important:h-12 data-test-id="previous-otp" @click.prevent="copyPrevious(tokens.previous)"> | ||||
|             {{ tokens.previous }} | ||||
|           </c-button> | ||||
|         </template> | ||||
|         <div>{{ previousCopied ? 'Copied !' : 'Copy previous OTP' }}</div> | ||||
|       </n-tooltip> | ||||
|       <n-tooltip trigger="hover" placement="bottom"> | ||||
|         <template #trigger> | ||||
|           <n-button | ||||
|             tertiary | ||||
|             type="primary" | ||||
|           <c-button | ||||
|             data-test-id="current-otp" | ||||
|             class="current-otp" | ||||
|             important:h-12 | ||||
|             @click.prevent="copyCurrent(tokens.current)" | ||||
|           > | ||||
|             {{ tokens.current }} | ||||
|           </n-button> | ||||
|           </c-button> | ||||
|         </template> | ||||
|         <div>{{ currentCopied ? 'Copied !' : 'Copy current OTP' }}</div> | ||||
|       </n-tooltip> | ||||
|       <n-tooltip trigger="hover" placement="bottom"> | ||||
|         <template #trigger> | ||||
|           <n-button secondary data-test-id="next-otp" @click.prevent="copyNext(tokens.next)">{{ | ||||
|           <c-button important:h-12 data-test-id="next-otp" @click.prevent="copyNext(tokens.next)">{{ | ||||
|             tokens.next | ||||
|           }}</n-button> | ||||
|           }}</c-button> | ||||
|         </template> | ||||
|         <div>{{ nextCopied ? 'Copied !' : 'Copy next OTP' }}</div> | ||||
|       </n-tooltip> | ||||
|  | ||||
| @ -28,7 +28,7 @@ | ||||
|       <n-gi> | ||||
|         <n-space justify="center" align="center" vertical> | ||||
|           <n-image :src="qrcode" width="200" /> | ||||
|           <n-button secondary @click="download"> Download qr-code </n-button> | ||||
|           <c-button @click="download"> Download qr-code </c-button> | ||||
|         </n-space> | ||||
|       </n-gi> | ||||
|     </n-grid> | ||||
|  | ||||
| @ -4,8 +4,8 @@ | ||||
|       {{ port }} | ||||
|     </div> | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copy"> Copy </n-button> | ||||
|       <n-button secondary @click="refreshPort"> Refresh </n-button> | ||||
|       <c-button @click="copy"> Copy </c-button> | ||||
|       <c-button @click="refreshPort"> Refresh </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
| </template> | ||||
|  | ||||
| @ -8,9 +8,9 @@ | ||||
|         <div class="result"> | ||||
|           {{ outputRoman }} | ||||
|         </div> | ||||
|         <n-button secondary autofocus :disabled="validationNumeral.validationStatus === 'error'" @click="copyRoman"> | ||||
|         <c-button autofocus :disabled="validationNumeral.validationStatus === 'error'" @click="copyRoman"> | ||||
|           Copy | ||||
|         </n-button> | ||||
|         </c-button> | ||||
|       </n-space> | ||||
|     </n-card> | ||||
|     <br /> | ||||
| @ -22,9 +22,7 @@ | ||||
|         <div class="result"> | ||||
|           {{ outputNumeral }} | ||||
|         </div> | ||||
|         <n-button secondary autofocus :disabled="validationRoman.validationStatus === 'error'" @click="copyArabic"> | ||||
|           Copy | ||||
|         </n-button> | ||||
|         <c-button :disabled="validationRoman.validationStatus === 'error'" @click="copyArabic"> Copy </c-button> | ||||
|       </n-space> | ||||
|     </n-card> | ||||
|   </div> | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
|         <n-input-number v-model:value="bits" min="256" max="16384" step="8" /> | ||||
|       </n-form-item> | ||||
| 
 | ||||
|       <n-button tertiary @click="refreshCerts">Refresh key-pair</n-button> | ||||
|       <c-button @click="refreshCerts">Refresh key-pair</c-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
| 
 | ||||
|  | ||||
| @ -14,7 +14,7 @@ | ||||
|     </n-form-item> | ||||
| 
 | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary :disabled="slug.length === 0" @click="copy">Copy slug</n-button> | ||||
|       <c-button :disabled="slug.length === 0" @click="copy">Copy slug</c-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -38,9 +38,9 @@ | ||||
|     </n-form-item> | ||||
| 
 | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copySVG()">Copy svg</n-button> | ||||
|       <n-button secondary @click="copyBase64()">Copy base64</n-button> | ||||
|       <n-button secondary @click="download()">Download svg</n-button> | ||||
|       <c-button @click="copySVG()">Copy svg</c-button> | ||||
|       <c-button @click="copyBase64()">Copy base64</c-button> | ||||
|       <c-button @click="download()">Download svg</c-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
| 
 | ||||
|  | ||||
| @ -11,7 +11,7 @@ | ||||
|       </n-card> | ||||
| 
 | ||||
|       <n-space justify="center"> | ||||
|         <n-button secondary autofocus @click="copy"> Copy NATO string </n-button> | ||||
|         <c-button autofocus @click="copy"> Copy NATO string </c-button> | ||||
|       </n-space> | ||||
|     </n-space> | ||||
|   </div> | ||||
|  | ||||
| @ -44,8 +44,8 @@ | ||||
|       <br /> | ||||
|       <br /> | ||||
|       <n-space justify="center"> | ||||
|         <n-button secondary autofocus @click="copy"> Copy </n-button> | ||||
|         <n-button secondary @click="refreshToken"> Refresh </n-button> | ||||
|         <c-button @click="copy"> Copy </c-button> | ||||
|         <c-button @click="refreshToken"> Refresh </c-button> | ||||
|       </n-space> | ||||
|     </n-card> | ||||
|   </div> | ||||
|  | ||||
| @ -24,7 +24,7 @@ | ||||
|     </n-form-item> | ||||
| 
 | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copyEncoded"> Copy </n-button> | ||||
|       <c-button @click="copyEncoded"> Copy </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
|   <n-card title="Decode"> | ||||
| @ -52,7 +52,7 @@ | ||||
|     </n-form-item> | ||||
| 
 | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary @click="copyDecoded"> Copy </n-button> | ||||
|       <c-button @click="copyDecoded"> Copy </c-button> | ||||
|     </n-space> | ||||
|   </n-card> | ||||
| </template> | ||||
|  | ||||
| @ -19,8 +19,8 @@ | ||||
|     /> | ||||
| 
 | ||||
|     <n-space justify="center"> | ||||
|       <n-button secondary autofocus @click="copy"> Copy </n-button> | ||||
|       <n-button secondary @click="refreshUUIDs"> Refresh </n-button> | ||||
|       <c-button autofocus @click="copy"> Copy </c-button> | ||||
|       <c-button @click="refreshUUIDs"> Refresh </c-button> | ||||
|     </n-space> | ||||
|   </n-space> | ||||
| </template> | ||||
|  | ||||
							
								
								
									
										240
									
								
								src/ui/c-button/c-button.theme.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								src/ui/c-button/c-button.theme.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,240 @@ | ||||
| import { defineThemes } from '../theme/theme.models'; | ||||
| import { appThemes } from '../theme/themes'; | ||||
| 
 | ||||
| export const { useTheme } = defineThemes({ | ||||
|   dark: { | ||||
|     basic: { | ||||
|       default: { | ||||
|         textColor: appThemes.dark.text.baseColor, | ||||
|         backgroundColor: 'rgba(255, 255, 255, 0.08)', | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: 'rgba(255, 255, 255, 0.12)', | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: 'rgba(255, 255, 255, 0.24)', | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.dark.primary.color, | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       primary: { | ||||
|         textColor: appThemes.dark.text.baseColor, | ||||
|         backgroundColor: appThemes.dark.primary.color, | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.dark.primary.colorHover, | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.dark.primary.colorPressed, | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.dark.primary.color, | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       warning: { | ||||
|         textColor: appThemes.dark.text.baseColor, | ||||
|         backgroundColor: appThemes.dark.warning.color, | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.dark.warning.colorHover, | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.dark.warning.colorPressed, | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.dark.warning.color, | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
| 
 | ||||
|     text: { | ||||
|       default: { | ||||
|         textColor: appThemes.dark.text.baseColor, | ||||
|         backgroundColor: 'transparent', | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: 'rgba(255, 255, 255, 0.12)', | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: 'rgba(255, 255, 255, 0.82)', | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.dark.primary.color, | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       primary: { | ||||
|         textColor: appThemes.dark.text.baseColor, | ||||
|         backgroundColor: appThemes.dark.primary.color, | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.dark.primary.colorHover, | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.dark.primary.colorPressed, | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.dark.primary.color, | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       warning: { | ||||
|         textColor: appThemes.dark.text.baseColor, | ||||
|         backgroundColor: appThemes.dark.warning.color, | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.dark.warning.colorHover, | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.dark.warning.colorPressed, | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.dark.warning.color, | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   light: { | ||||
|     basic: { | ||||
|       default: { | ||||
|         textColor: appThemes.light.text.baseColor, | ||||
|         backgroundColor: 'rgba(46, 51, 56, 0.05)', | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.light.text.baseColor, | ||||
|           backgroundColor: 'rgba(46, 51, 56, 0.09)', | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.light.text.baseColor, | ||||
|           backgroundColor: 'rgba(46, 51, 56, 0.22)', | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.light.primary.color, | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       primary: { | ||||
|         textColor: appThemes.dark.text.baseColor, | ||||
|         backgroundColor: appThemes.light.primary.color, | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.light.primary.colorHover, | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.light.primary.colorPressed, | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.light.primary.color, | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
|       warning: { | ||||
|         textColor: appThemes.dark.text.baseColor, | ||||
|         backgroundColor: appThemes.light.warning.color, | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.light.warning.colorHover, | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.dark.text.baseColor, | ||||
|           backgroundColor: appThemes.light.warning.colorPressed, | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.light.warning.color, | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|     text: { | ||||
|       default: { | ||||
|         textColor: appThemes.light.text.baseColor, | ||||
|         backgroundColor: 'transparent', | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.light.text.baseColor, | ||||
|           backgroundColor: 'rgba(46, 51, 56, 0.09)', | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.light.text.baseColor, | ||||
|           backgroundColor: 'rgba(46, 51, 56, 0.13)', | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.light.primary.color, | ||||
|         }, | ||||
|       }, | ||||
|       primary: { | ||||
|         textColor: appThemes.light.primary.color, | ||||
|         backgroundColor: 'transparent', | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.light.primary.colorHover, | ||||
|           backgroundColor: 'rgba(46, 51, 56, 0.09)', | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.light.primary.colorPressed, | ||||
|           backgroundColor: 'rgba(46, 51, 56, 0.13)', | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.light.primary.color, | ||||
|         }, | ||||
|       }, | ||||
|       warning: { | ||||
|         textColor: appThemes.light.warning.color, | ||||
|         backgroundColor: 'transparent', | ||||
| 
 | ||||
|         hover: { | ||||
|           textColor: appThemes.light.warning.colorHover, | ||||
|           backgroundColor: 'rgba(46, 51, 56, 0.09)', | ||||
|         }, | ||||
| 
 | ||||
|         pressed: { | ||||
|           textColor: appThemes.light.warning.colorPressed, | ||||
|           backgroundColor: 'rgba(46, 51, 56, 0.13)', | ||||
|         }, | ||||
| 
 | ||||
|         outline: { | ||||
|           color: appThemes.light.warning.color, | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
| }); | ||||
							
								
								
									
										113
									
								
								src/ui/c-button/c-button.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								src/ui/c-button/c-button.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,113 @@ | ||||
| <template> | ||||
|   <component | ||||
|     :is="tag" | ||||
|     :href="href ?? to" | ||||
|     class="c-button" | ||||
|     :class="{ disabled, round, circle }" | ||||
|     :to="to" | ||||
|     @click="handleClick" | ||||
|   > | ||||
|     <slot /> | ||||
|   </component> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
| import type { RouteLocationRaw } from 'vue-router'; | ||||
| import { useTheme } from './c-button.theme'; | ||||
| 
 | ||||
| const props = withDefaults( | ||||
|   defineProps<{ | ||||
|     type?: 'default' | 'primary'; | ||||
|     variant?: 'basic' | 'text'; | ||||
|     disabled?: boolean; | ||||
|     round?: boolean; | ||||
|     circle?: boolean; | ||||
|     href?: string; | ||||
|     to?: RouteLocationRaw; | ||||
|   }>(), | ||||
|   { | ||||
|     type: 'default', | ||||
|     variant: 'basic', | ||||
|     disabled: false, | ||||
|     round: false, | ||||
|     circle: false, | ||||
|     href: undefined, | ||||
|     to: undefined, | ||||
|   }, | ||||
| ); | ||||
| const { variant, disabled, round, circle, href, type, to } = toRefs(props); | ||||
| 
 | ||||
| const emits = defineEmits(['click']); | ||||
| 
 | ||||
| function handleClick(event: MouseEvent) { | ||||
|   if (!disabled.value) { | ||||
|     emits('click', event); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| const theme = useTheme(); | ||||
| const variantTheme = computed(() => theme.value[variant.value][type.value]); | ||||
| const tag = computed(() => { | ||||
|   if (href.value) { | ||||
|     return 'a'; | ||||
|   } | ||||
|   if (to.value) { | ||||
|     return 'router-link'; | ||||
|   } | ||||
|   return 'button'; | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="less" scoped> | ||||
| .c-button { | ||||
|   margin: 0; | ||||
|   line-height: 1; | ||||
|   font-family: inherit; | ||||
|   font-size: inherit; | ||||
|   border: none; | ||||
|   text-align: center; | ||||
|   cursor: pointer; | ||||
|   text-decoration: none; | ||||
|   height: 34px; | ||||
|   font-weight: 400; | ||||
|   color: v-bind('variantTheme.textColor'); | ||||
|   padding: 0 14px; | ||||
|   border-radius: 4px; | ||||
|   transition: background-color cubic-bezier(0.4, 0, 0.2, 1) 0.3s; | ||||
| 
 | ||||
|   background-color: v-bind('variantTheme.backgroundColor'); | ||||
|   display: inline-flex; | ||||
|   flex-direction: row; | ||||
|   align-items: center; | ||||
|   justify-content: center; | ||||
| 
 | ||||
|   // outline-offset: 1px; | ||||
|   &.round { | ||||
|     border-radius: 100px; | ||||
|   } | ||||
| 
 | ||||
|   &.circle { | ||||
|     border-radius: 40px; | ||||
|     width: 34px; | ||||
|   } | ||||
| 
 | ||||
|   &:not(.disabled) { | ||||
|     &:hover { | ||||
|       background-color: v-bind('variantTheme.hover.backgroundColor'); | ||||
|     } | ||||
| 
 | ||||
|     &:active { | ||||
|       background-color: v-bind('variantTheme.pressed.backgroundColor'); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &:focus { | ||||
|     outline: 2px solid v-bind('variantTheme.outline.color'); | ||||
|   } | ||||
| 
 | ||||
|   &.disabled { | ||||
|     opacity: 0.5; | ||||
|     cursor: not-allowed; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										39
									
								
								src/ui/c-link/c-link.theme.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/ui/c-link/c-link.theme.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| import { defineThemes } from '../theme/theme.models'; | ||||
| import { appThemes } from '../theme/themes'; | ||||
| 
 | ||||
| export const { useTheme } = defineThemes({ | ||||
|   dark: { | ||||
|     default: { | ||||
|       textColor: appThemes.dark.primary.color, | ||||
| 
 | ||||
|       hover: { | ||||
|         textColor: appThemes.dark.primary.colorHover, | ||||
|       }, | ||||
| 
 | ||||
|       pressed: { | ||||
|         textColor: appThemes.dark.primary.colorPressed, | ||||
|       }, | ||||
| 
 | ||||
|       outline: { | ||||
|         color: appThemes.dark.primary.color, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   light: { | ||||
|     default: { | ||||
|       textColor: appThemes.light.primary.color, | ||||
| 
 | ||||
|       hover: { | ||||
|         textColor: appThemes.light.primary.colorHover, | ||||
|       }, | ||||
| 
 | ||||
|       pressed: { | ||||
|         textColor: appThemes.light.primary.colorPressed, | ||||
|       }, | ||||
| 
 | ||||
|       outline: { | ||||
|         color: appThemes.light.primary.color, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
| }); | ||||
							
								
								
									
										49
									
								
								src/ui/c-link/c-link.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/ui/c-link/c-link.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| <template> | ||||
|   <component :is="tag" :href="href ?? to" class="c-link" :to="to"> | ||||
|     <slot /> | ||||
|   </component> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
| import { RouterLink, type RouteLocationRaw } from 'vue-router'; | ||||
| import { useTheme } from './c-link.theme'; | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|   href?: string; | ||||
|   to?: RouteLocationRaw; | ||||
| }>(); | ||||
| 
 | ||||
| const { href, to } = toRefs(props); | ||||
| 
 | ||||
| const theme = useTheme(); | ||||
| const tag = computed(() => (href?.value ? 'a' : RouterLink)); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="less" scoped> | ||||
| .c-link { | ||||
|   line-height: inherit; | ||||
|   font-family: inherit; | ||||
|   font-size: inherit; | ||||
|   border: none; | ||||
|   cursor: pointer; | ||||
|   text-decoration: none; | ||||
|   font-weight: 400; | ||||
|   color: v-bind('theme.default.textColor'); | ||||
|   border-radius: 4px; | ||||
|   transition: color cubic-bezier(0.4, 0, 0.2, 1) 0.3s; | ||||
| 
 | ||||
|   outline-offset: 1px; | ||||
| 
 | ||||
|   &:hover { | ||||
|     color: v-bind('theme.default.hover.textColor'); | ||||
|   } | ||||
| 
 | ||||
|   &:active { | ||||
|     color: v-bind('theme.default.textColor'); | ||||
|   } | ||||
| 
 | ||||
|   &:focus { | ||||
|     color: v-bind('theme.default.outline.color'); | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										13
									
								
								src/ui/theme/theme.models.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/ui/theme/theme.models.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| import { useThemeStore } from './theme.store'; | ||||
| 
 | ||||
| export { defineThemes }; | ||||
| 
 | ||||
| function defineThemes<Theme>(themes: { light: Theme; dark: Theme }) { | ||||
|   return { | ||||
|     themes, | ||||
|     useTheme() { | ||||
|       const themeStore = useThemeStore(); | ||||
|       return computed(() => themes[themeStore.themeType]); | ||||
|     }, | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										20
									
								
								src/ui/theme/theme.store.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/ui/theme/theme.store.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| import { defineStore } from 'pinia'; | ||||
| 
 | ||||
| export const useThemeStore = defineStore('ui-theme', { | ||||
|   state: () => ({ | ||||
|     themeType: useStorage<'dark' | 'light'>('ui-store:theme-type', 'dark') as Ref<'dark' | 'light'>, | ||||
|   }), | ||||
|   getters: { | ||||
|     isDarkTheme(): boolean { | ||||
|       return this.themeType === 'dark'; | ||||
|     }, | ||||
|     isLightTheme(): boolean { | ||||
|       return this.themeType === 'light'; | ||||
|     }, | ||||
|   }, | ||||
|   actions: { | ||||
|     toggleTheme() { | ||||
|       this.themeType = this.isDarkTheme ? 'light' : 'dark'; | ||||
|     }, | ||||
|   }, | ||||
| }); | ||||
							
								
								
									
										37
									
								
								src/ui/theme/themes.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/ui/theme/themes.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| import { defineThemes } from './theme.models'; | ||||
| 
 | ||||
| export const { themes: appThemes, useTheme: useAppTheme } = defineThemes({ | ||||
|   light: { | ||||
|     text: { | ||||
|       baseColor: 'rgb(51, 54, 57)', | ||||
|     }, | ||||
| 
 | ||||
|     primary: { | ||||
|       color: '#18a058', | ||||
|       colorHover: '#1ea54c', | ||||
|       colorPressed: '#0C7A43', | ||||
|     }, | ||||
| 
 | ||||
|     warning: { | ||||
|       color: '#f59e0b', | ||||
|       colorHover: '#f59e0b', | ||||
|       colorPressed: '#f59e0b', | ||||
|     }, | ||||
|   }, | ||||
|   dark: { | ||||
|     text: { | ||||
|       baseColor: 'rgba(255, 255, 255, 0.82)', | ||||
|     }, | ||||
| 
 | ||||
|     primary: { | ||||
|       color: '#1ea54c', | ||||
|       colorHover: '#36AD6A', | ||||
|       colorPressed: '#0C7A43', | ||||
|     }, | ||||
|     warning: { | ||||
|       color: '#f59e0b', | ||||
|       colorHover: '#f59e0b', | ||||
|       colorPressed: '#f59e0b', | ||||
|     }, | ||||
|   }, | ||||
| }); | ||||
| @ -73,6 +73,9 @@ export default defineConfig({ | ||||
|       }, | ||||
|     }), | ||||
|     Components({ | ||||
|       dirs: ['src/'], | ||||
|       extensions: ['vue', 'md'], | ||||
|       include: [/\.vue$/, /\.vue\?vue/, /\.md$/], | ||||
|       resolvers: [NaiveUiResolver()], | ||||
|     }), | ||||
|     Unocss(), | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user