feature: add border generator module.
This commit is contained in:
		
							parent
							
								
									87984e2081
								
							
						
					
					
						commit
						52df553294
					
				
							
								
								
									
										15
									
								
								src/tools/border-generator/border-generator.e2e.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/tools/border-generator/border-generator.e2e.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| import { test, expect } from '@playwright/test'; | ||||
| 
 | ||||
| test.describe('Tool - Border generator', () => { | ||||
|   test.beforeEach(async ({ page }) => { | ||||
|     await page.goto('/border-generator'); | ||||
|   }); | ||||
| 
 | ||||
|   test('Has correct title', async ({ page }) => { | ||||
|     await expect(page).toHaveTitle('Border generator - IT Tools'); | ||||
|   }); | ||||
| 
 | ||||
|   test('', async ({ page }) => { | ||||
| 
 | ||||
|   }); | ||||
| }); | ||||
| @ -0,0 +1,6 @@ | ||||
| import { expect, describe, it } from 'vitest'; | ||||
| // import { } from './border-generator.service';
 | ||||
| //
 | ||||
| // describe('border-generator', () => {
 | ||||
| //
 | ||||
| // })
 | ||||
							
								
								
									
										15
									
								
								src/tools/border-generator/border-generator.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/tools/border-generator/border-generator.service.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| export interface Border { | ||||
|   label: string; | ||||
|   value: number; | ||||
|   max: number; | ||||
| } | ||||
| 
 | ||||
| export interface Borders { | ||||
|   [key: string]: Border; | ||||
| } | ||||
| 
 | ||||
| // Asegúrate de que esta función esté correctamente exportada
 | ||||
| export function generateCSSOutput(borders: Borders, borderWidth: number, borderStyle: string, unit: string): string { | ||||
|   const { topLeft, topRight, bottomRight, bottomLeft } = borders; | ||||
|   return `border: ${borderWidth}px ${borderStyle} #000000; border-radius: ${topLeft.value}${unit} ${topRight.value}${unit} ${bottomRight.value}${unit} ${bottomLeft.value}${unit};`; | ||||
| } | ||||
							
								
								
									
										214
									
								
								src/tools/border-generator/border-generator.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								src/tools/border-generator/border-generator.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,214 @@ | ||||
| <template> | ||||
|   <div class="container"> | ||||
|     <div class="square" :style="styleObject"></div> | ||||
| 
 | ||||
|     <n-card title="Border Radius and Style Editor" class="controls"> | ||||
|       <n-form> | ||||
|         <n-form-item label="Units"> | ||||
|           <n-select v-model:value="unit" :options="unitOptions" @update:value="updateCSSOutput" /> | ||||
|         </n-form-item> | ||||
| 
 | ||||
|         <div class="radius-controls"> | ||||
|           <n-form-item label="Top Left" class="half-slider"> | ||||
|             <n-slider | ||||
|               :min="0" | ||||
|               :max="borders.topLeft.max" | ||||
|               v-model:value="borders.topLeft.value" | ||||
|               @update:value="updateCSSOutput" | ||||
|               :step="1" | ||||
|             /> | ||||
|             <span>{{ borders.topLeft.value + unit }}</span> | ||||
|           </n-form-item> | ||||
|           <n-form-item label="Top Right" class="half-slider"> | ||||
|             <n-slider | ||||
|               :min="0" | ||||
|               :max="borders.topRight.max" | ||||
|               v-model:value="borders.topRight.value" | ||||
|               @update:value="updateCSSOutput" | ||||
|               :step="1" | ||||
|             /> | ||||
|             <span>{{ borders.topRight.value + unit }}</span> | ||||
|           </n-form-item> | ||||
|         </div> | ||||
|         <div class="radius-controls"> | ||||
|           <n-form-item label="Bottom Left" class="half-slider"> | ||||
|             <n-slider | ||||
|               :min="0" | ||||
|               :max="borders.bottomLeft.max" | ||||
|               v-model:value="borders.bottomLeft.value" | ||||
|               @update:value="updateCSSOutput" | ||||
|               :step="1" | ||||
|             /> | ||||
|             <span>{{ borders.bottomLeft.value + unit }}</span> | ||||
|           </n-form-item> | ||||
|           <n-form-item label="Bottom Right" class="half-slider"> | ||||
|             <n-slider | ||||
|               :min="0" | ||||
|               :max="borders.bottomRight.max" | ||||
|               v-model:value="borders.bottomRight.value" | ||||
|               @update:value="updateCSSOutput" | ||||
|               :step="1" | ||||
|             /> | ||||
|             <span>{{ borders.bottomRight.value + unit }}</span> | ||||
|           </n-form-item> | ||||
|         </div> | ||||
|         <div class="border-controls"> | ||||
|           <n-form-item label="Border Width" class="border-width-slider"> | ||||
|             <n-slider :min="0" :max="100" v-model:value="borderWidth" @update:value="updateCSSOutput" :step="1" /> | ||||
|             <span>{{ borderWidth + 'px' }}</span> | ||||
|           </n-form-item> | ||||
|           <n-form-item label="Border Style" class="border-style-select"> | ||||
|             <n-select v-model:value="borderStyle" :options="borderStyles" @update:value="updateCSSOutput" /> | ||||
|           </n-form-item> | ||||
|         </div> | ||||
| 
 | ||||
|         <n-form-item label="Border Color"> | ||||
|           <n-color-picker v-model:value="borderColor" @update:value="updateCSSOutput" /> | ||||
|         </n-form-item> | ||||
| 
 | ||||
|         <n-form-item label="CSS Properties"> | ||||
|           <TextareaCopyable :value="cssOutput" language="css" /> | ||||
|         </n-form-item> | ||||
|       </n-form> | ||||
|     </n-card> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, ref, computed } from 'vue'; | ||||
| import { NSlider, NForm, NFormItem, NSelect, NCard, NColorPicker } from 'naive-ui'; | ||||
| import TextareaCopyable from '@/components/TextareaCopyable.vue'; | ||||
| import { Borders } from './border-radius-viewer.service'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   name: 'BorderRadiusViewer', | ||||
|   components: { | ||||
|     NSlider, | ||||
|     NForm, | ||||
|     NFormItem, | ||||
|     NSelect, | ||||
|     NCard, | ||||
|     NColorPicker, | ||||
|     TextareaCopyable, | ||||
|   }, | ||||
|   setup() { | ||||
|     const borders = ref<Borders>({ | ||||
|       topLeft: { label: 'Top Left', value: 0, max: 100 }, | ||||
|       topRight: { label: 'Top Right', value: 0, max: 100 }, | ||||
|       bottomLeft: { label: 'Bottom Left', value: 0, max: 100 }, | ||||
|       bottomRight: { label: 'Bottom Right', value: 0, max: 100 }, | ||||
|     }); | ||||
|     const unit = ref('px'); | ||||
|     const borderWidth = ref<number>(0); | ||||
|     const borderStyle = ref('solid'); | ||||
|     const borderColor = ref('#000000'); | ||||
|     const unitOptions = [ | ||||
|       { label: 'Pixels (px)', value: 'px' }, | ||||
|       { label: 'Percentage (%)', value: '%' }, | ||||
|     ]; | ||||
|     const borderStyles = [ | ||||
|       { label: 'Solid', value: 'solid' }, | ||||
|       { label: 'Dashed', value: 'dashed' }, | ||||
|       { label: 'Dotted', value: 'dotted' }, | ||||
|       { label: 'Double', value: 'double' }, | ||||
|       { label: 'Groove', value: 'groove' }, | ||||
|       { label: 'Ridge', value: 'ridge' }, | ||||
|       { label: 'Inset', value: 'inset' }, | ||||
|       { label: 'Outset', value: 'outset' }, | ||||
|       { label: 'None', value: 'none' }, | ||||
|     ]; | ||||
| 
 | ||||
|     const styleObject = computed(() => ({ | ||||
|       border: `${borderWidth.value}px ${borderStyle.value} ${borderColor.value}`, | ||||
|       borderRadius: `${borders.value.topLeft.value}${unit.value} ${borders.value.topRight.value}${unit.value} ${borders.value.bottomRight.value}${unit.value} ${borders.value.bottomLeft.value}${unit.value}`, | ||||
|     })); | ||||
| 
 | ||||
|     const cssOutput = computed( | ||||
|       () => | ||||
|         `border: ${borderWidth.value}px ${borderStyle.value} ${borderColor.value};\nborder-radius: ${borders.value.topLeft.value}${unit.value} ${borders.value.topRight.value}${unit.value} ${borders.value.bottomRight.value}${unit.value} ${borders.value.bottomLeft.value}${unit.value};`, | ||||
|     ); | ||||
| 
 | ||||
|     function updateCSSOutput() { | ||||
|       // Forces update computed properties | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|       borders, | ||||
|       unit, | ||||
|       borderWidth, | ||||
|       borderStyle, | ||||
|       borderColor, | ||||
|       unitOptions, | ||||
|       borderStyles, | ||||
|       cssOutput, | ||||
|       updateCSSOutput, | ||||
|       styleObject, | ||||
|     }; | ||||
|   }, | ||||
| }); | ||||
| </script> | ||||
| <style scoped> | ||||
| .container { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   align-items: center; | ||||
|   justify-content: center; | ||||
|   gap: 10px; | ||||
| } | ||||
| 
 | ||||
| .square { | ||||
|   width: 250px; | ||||
|   height: 250px; | ||||
|   background-color: #f3f3f3; | ||||
| } | ||||
| 
 | ||||
| .controls { | ||||
|   width: 100%; | ||||
| } | ||||
| 
 | ||||
| .radius-controls, | ||||
| .border-controls { | ||||
|   display: flex; | ||||
|   justify-content: space-around; | ||||
|   align-items: center; | ||||
|   gap: 20px; | ||||
| } | ||||
| 
 | ||||
| .half-slider, | ||||
| .border-width-slider { | ||||
|   position: relative; | ||||
|   padding: 10px 0; | ||||
|   width: 60%; | ||||
| } | ||||
| 
 | ||||
| .half-slider span, | ||||
| .border-width-slider span { | ||||
|   position: absolute; | ||||
|   right: 0; | ||||
|   top: 30px; | ||||
|   background-color: #fff; | ||||
|   padding: 2px 6px; | ||||
|   border-radius: 5px; | ||||
|   font-size: 0.9em; | ||||
|   color: #333; | ||||
| } | ||||
| 
 | ||||
| .border-style-select { | ||||
|   width: 30%; | ||||
| } | ||||
| 
 | ||||
| n-slider { | ||||
|   width: calc(100% - 60px); | ||||
| } | ||||
| 
 | ||||
| .controls .n-form-item__label { | ||||
|   min-width: 70px; | ||||
|   text-align: right; | ||||
| } | ||||
| 
 | ||||
| n-select, | ||||
| n-color-picker { | ||||
|   width: 100%; | ||||
| } | ||||
| </style> | ||||
| 
 | ||||
							
								
								
									
										13
									
								
								src/tools/border-generator/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/tools/border-generator/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| import { Square } from '@vicons/tabler'; | ||||
| import { defineTool } from '../tool'; | ||||
| 
 | ||||
| export const tool = defineTool({ | ||||
|   name: 'Border Generator', | ||||
|   path: '/border-radius-viewer', | ||||
|   description: 'Generate a complete CSS border properties.', | ||||
|   keywords: ['border', 'radius', 'viewer'], | ||||
|   component: () => import('./border-radius-viewer.vue'), | ||||
|   icon: Square, | ||||
|   createdAt: new Date('2024-09-06'), | ||||
| }); | ||||
| 
 | ||||
| @ -1,6 +1,7 @@ | ||||
| import { tool as base64FileConverter } from './base64-file-converter'; | ||||
| import { tool as base64StringConverter } from './base64-string-converter'; | ||||
| import { tool as basicAuthGenerator } from './basic-auth-generator'; | ||||
| import { tool as borderGenerator } from './border-generator'; | ||||
| import { tool as emailNormalizer } from './email-normalizer'; | ||||
| 
 | ||||
| import { tool as asciiTextDrawer } from './ascii-text-drawer'; | ||||
| @ -89,7 +90,19 @@ import { tool as yamlViewer } from './yaml-viewer'; | ||||
| export const toolsByCategory: ToolCategory[] = [ | ||||
|   { | ||||
|     name: 'Crypto', | ||||
|     components: [tokenGenerator, hashText, bcrypt, uuidGenerator, ulidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator, passwordStrengthAnalyser, pdfSignatureChecker], | ||||
|     components: [ | ||||
|       tokenGenerator, | ||||
|       hashText, | ||||
|       bcrypt, | ||||
|       uuidGenerator, | ||||
|       ulidGenerator, | ||||
|       cypher, | ||||
|       bip39, | ||||
|       hmacGenerator, | ||||
|       rsaKeyPairGenerator, | ||||
|       passwordStrengthAnalyser, | ||||
|       pdfSignatureChecker, | ||||
|     ], | ||||
|   }, | ||||
|   { | ||||
|     name: 'Converter', | ||||
| @ -135,6 +148,7 @@ export const toolsByCategory: ToolCategory[] = [ | ||||
|       httpStatusCodes, | ||||
|       jsonDiff, | ||||
|       safelinkDecoder, | ||||
|       borderGenerator, | ||||
|     ], | ||||
|   }, | ||||
|   { | ||||
| @ -160,7 +174,14 @@ export const toolsByCategory: ToolCategory[] = [ | ||||
|   }, | ||||
|   { | ||||
|     name: 'Network', | ||||
|     components: [ipv4SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator], | ||||
|     components: [ | ||||
|       ipv4SubnetCalculator, | ||||
|       ipv4AddressConverter, | ||||
|       ipv4RangeExpander, | ||||
|       macAddressLookup, | ||||
|       macAddressGenerator, | ||||
|       ipv6UlaGenerator, | ||||
|     ], | ||||
|   }, | ||||
|   { | ||||
|     name: 'Math', | ||||
| @ -190,5 +211,5 @@ export const toolsByCategory: ToolCategory[] = [ | ||||
| 
 | ||||
| export const tools = toolsByCategory.flatMap(({ components }) => components); | ||||
| export const toolsWithCategory = toolsByCategory.flatMap(({ components, name }) => | ||||
|   components.map(tool => ({ category: name, ...tool })), | ||||
|   components.map((tool) => ({ category: name, ...tool })), | ||||
| ); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user