Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions docs/components/ContentSearchButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script setup lang="ts">
import { ref } from 'vue'
import SearchIcon from './icon/search.icon.vue'
import SearchModal from './SearchModal.vue'
const showSearchModal = ref(false)
const toggleSearch = () => {
showSearchModal.value = !showSearchModal.value
}
const handleKeydown = (event: KeyboardEvent) => {
if (event.ctrlKey && event.key === 'k') {
event.preventDefault()
toggleSearch()
}
}
onMounted(() => {
window.addEventListener('keydown', handleKeydown)
})
onBeforeUnmount(() => {
window.removeEventListener('keydown', handleKeydown)
})
</script>

<template>
<button class="border border-gray-300 rounded-md w-96 flex items-center px-2 gap-x-2 text-left hover:bg-gray-300/20" @click="toggleSearch">
<span>
<search-icon class="w-5 stroke-gray-400" />
</span>
<div
class="text-sm outline-none w-full py-1.5 text-gray-700/50"
>
Search...
</div>
<div class="flex gap-x-1">
<span
class="text-xs text-gray-600 rounded font-medium px-1 py-[1px] border bg-gray-100 cursor-pointer"
>Ctrl</span>
<span class="text-xs text-gray-600 rounded font-medium px-1 py-[1px] border bg-gray-100 cursor-pointer">K</span>
</div>
</button>

<SearchModal v-if="showSearchModal" @close="toggleSearch" />
</template>
5 changes: 2 additions & 3 deletions docs/components/Header.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import SunIcon from "./icon/sun.icon.vue";
import GithubIcon from "./icon/github.icon.vue";
import SearchIcon from "./icon/search.icon.vue";
import ContentSearchButton from './ContentSearchButton.vue'
</script>

<template>
Expand All @@ -17,8 +16,8 @@ import SearchIcon from "./icon/search.icon.vue";
class="px-2 ms-1.5 ring-1 ring-inset rounded-md text-xs py-1 text-center ring-green-300 bg-green-50 text-green-500 font-medium"
>Docs</span
>

</div>
<ContentSearchButton />
<div class="space-x-5 flex items-center">
<span>
<a href="https://github.com/nattyjs/tidy" target="_blank"> <github-icon class="w-5 fill-gray-700 cursor-pointer" /></a>
Expand Down
73 changes: 73 additions & 0 deletions docs/components/SearchModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useFetch } from '#app'
import SearchIcon from './icon/search.icon.vue'
import DocumentIcon from './icon/document.icon.vue'
import { DEFAULT_SEARCH_DATA } from '~/consts/DefaultSearchData'
const query = ref('')
const searchResults = ref<any[] | null>(DEFAULT_SEARCH_DATA)
const inputRef = ref<HTMLInputElement | null>(null)
const onSearch = async () => {
if (query.value != '') {
const { data } = await useFetch('/api/search.json', {
params: { q: query.value },
})
searchResults.value = data.value
} else {
searchResults.value = DEFAULT_SEARCH_DATA
}
}
onMounted(() => {
inputRef.value?.focus()
})
</script>

<template>
<div class="fixed z-50 inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center">
<div class="w-[40vw] h-[50vh] flex flex-col bg-white rounded-lg shadow-lg">
<header class="flex items-center pt-2 px-4 border-b">
<span>
<search-icon class="w-5 stroke-gray-400" />
</span>
<input
ref="inputRef" v-model="query" type="text" class="w-full p-2 rounded-md border-none outline-none"
placeholder="Type to search..." @input="onSearch"
>
<button class="text-gray-400 hover:text-gray-600 text-xl font-semibold" @click="$emit('close')">
</button>
</header>

<ul v-if="searchResults && searchResults.length" class="space-y-2 max-h-[44vh] overflow-y-scroll pl-4">
<li v-for="(result, idx) in searchResults" :key="idx">
<div v-if="result.name" class="my-2">
<span class="text-black font-medium">{{ result.name }}</span>
</div>
<NuxtLink
v-for="link in result.items" :key="link.link" :to="link.link"
class="flex items-center space-x-2 overflow-hidden text-ellipsis p-1 rounded-md hover:bg-gray-200/50 group"
@click="$emit('close')"
>
<document-icon class="w-4 h-4 stroke-gray-400 text-gray-500 group-hover:text-gray-800 bg-transparent fill-transparent" />
<div class="flex-1 min-w-0 flex items-center space-x-1 text-sm">
<span class="text-gray-700 group-hover:text-black whitespace-nowrap">{{ link.title }}</span>
<span v-if="link.description" class="text-slate-400 truncate">- {{ link.description }}</span>
</div>
</NuxtLink>
</li>
</ul>
<p v-else class="h-full text-gray-500 flex justify-center items-center">
We couldn't find any items with that term. Please try again.
</p>
</div>
</div>
</template>

<style scoped>
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
}
</style>
13 changes: 13 additions & 0 deletions docs/components/icon/document.icon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path
fill-opacity="0.3"
d="M13.5 3l5.5 5.5v11.5c0 0.55 -0.45 1 -1 1h-12c-0.55 0 -1 -0.45 -1 -1v-16c0 -0.55 0.45 -1 1 -1Z"
/>
<path d="M14.5 3.5l0 4.5l4.5 0z" />
<path d="M9 13h6" />
<path d="M9 17h3" />
</g>
</svg>
</template>
213 changes: 213 additions & 0 deletions docs/consts/DefaultSearchData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
// To get this just hit search.json.get.ts in the search bar with '' as the query
export const DEFAULT_SEARCH_DATA = [
{
name: 'What is @tidy',
items: [
{
title: 'What is @tidy?',
description: 'Say goodbye to messy templates and complex validation rules! @tidy empowers you to build robust forms with clear, maintainable validation in your prefered Single Page Application Framework (Vue.js, Sevlte, etc.) based applications.',
link: '/getting-started'
}
]
},
{
name: 'Getting Started',
items: [
{
title: 'Installation',
description: 'Get started with @tidy, Effortless Form Validation for Popular Single Page Application Frameworks (Vue.js, Sevlte, etc.)',
link: '/getting-started/installation'
},
{
title: 'Quick Start',
description: 'Build a simple form with clear validation using @tidy\'s core features in this quick guide.',
link: '/getting-started/building-your-first-form'
}
]
},
{
name: 'Core Concepts',
items: [
{
title: 'Global Configuration',
description: 'Configure error messages, date format, & validation strategy globally.',
link: '/core-concepts/global-configuration'
},
{
title: 'useForm',
description: 'Effortlessly manage and validate forms in Vue.js or Sevlte with the useForm composition API function and built-in validation from "@tidy".',
link: '/core-concepts/use-form'
},
{
title: 'Validators',
description: 'Effortlessly manage and validate forms in Vue.js with the useForm composition API function and built-in validation from "@tidy".',
link: '/core-concepts/validators'
}
]
},
{
name: 'How To',
items: [
{
title: 'Create Simple Form',
description: 'This page introduces form validation concepts by creating a simple form with basic validation rules for user input.',
link: '/how-to/create-simple-form'
},
{
title: 'Create Nested Forms',
description: 'This page dives into nested forms, a method for structuring complex data and independent validation within forms.',
link: '/how-to/create-nested-form'
},
{
title: 'Create Nested Form Arrays',
description: 'This page introduces form validation concepts through creating a simple form with basic validation rules for user input.',
link: '/how-to/create-nested-form-array'
},
{
title: 'Validate Form on Submit',
description: 'This page explains how to validate a form when the submit button is clicked using @tidy. Here, validation occurs only when the user attempts to submit the form, ensuring a smoother user experience.',
link: '/how-to/validate-form-on-submit'
},
{
title: 'Cross Field Validation (Compare Password)',
description: 'This page explains cross-field validation, ensuring form data consistency by checking fields against each other.',
link: '/how-to/cross-field-validation'
},
{
title: 'Conditional Validation',
description: 'This page unveils conditional validation in @nattyjs/tidy forms, validation rules adapt to user input for a flexible experience.',
link: '/how-to/conditional-validation'
},
{
title: 'Async Validation',
description: 'Leverage asynchronous validation in your forms. Ensure real-time data checks and enhance user experience with instant feedback.',
link: '/how-to/async-validation'
},
{
title: 'Custom Validation',
description: 'This page empowers you to craft custom validation rules for your forms, going beyond built-in options.',
link: '/how-to/custom-validation'
},
{
title: 'Validate Checkbox or Radio Button',
description: 'Validate checkboxes & radio buttons, Ensure user choices in your forms!.',
link: '/how-to/validate-checkbox-and-radiobutton'
}
]
},
{
name: 'Api Reference',
items: [
{
title: 'AlphaConfig',
description: 'Configure validation for alphabetic input, allowing customization of whitespace, locale, and additional valid characters..',
link: '/api-reference/alpha-config'
},
{
title: 'ArrayConfig',
description: 'Configure array-based validations (like allOf, noneOf, oneOf), specifying expected values and potentially customizing error messages.',
link: '/api-reference/array-config'
},
{
title: 'BaseValidatorConfig',
description: 'This interface defines a set of configuration options that can be applied to various validators.',
link: '/api-reference/base-validator-config'
},
{
title: 'CreditCardConfig',
description: 'Configure credit card validation, allowing specification of accepted types.',
link: '/api-reference/credit-card-config'
},
{
title: 'DefaultConfig',
description: 'Configure to restrict the user input with the defined value.',
link: '/api-reference/default-config'
},
{
title: 'DifferentConfig',
description: 'Configure to provide a way to associate a field name with a validator.',
link: '/api-reference/different-config'
},
{
title: 'ExtensionConfig',
description: 'Configuration options for validating file extensions.',
link: '/api-reference/extension-config'
},
{
title: 'FactorConfig',
description: 'Configuration options for validators that perform comparison-based validation.',
link: '/api-reference/factor-config'
},
{
title: 'HexColorConfig',
description: 'Configuration options for validators that perform comparison-based validation.',
link: '/api-reference/hex-color-config'
},
{
title: 'IpConfig',
description: 'Configure IP address validation with version and CIDR notation options.',
link: '/api-reference/ip-config'
},
{
title: 'MaxDateConfig',
description: 'Configure date validation (optional value, field name, ISO format), with adding support for maximum date comparison operators (< or <=).',
link: '/api-reference/max-date-config'
},
{
title: 'MaxTimeConfig',
description: 'Configure maximum allowed time validation with comparison operators (<, <=), optional time value, field name, and allowing seconds in the format.',
link: '/api-reference/max-time-config'
},
{
title: 'MinDateConfig',
description: 'Configure minimum date validation with optional value, field name, ISO format support, and comparison operators (\'>\' or \'>=\').',
link: '/api-reference/min-date-config'
},
{
title: 'MinTimeConfig',
description: 'Define minimum allowed time validation with comparison operators (\'>\', \'>=\') along with optional time value, field name, and allowing seconds in the format.',
link: '/api-reference/min-time-config'
},
{
title: 'NumberConfig',
description: 'Configure basic number validation.',
link: '/api-reference/number-config'
},
{
title: 'PasswordConfig',
description: 'Configures password validation rules (min length, character types), conditional enforcement, and custom error messages.',
link: '/api-reference/password-config'
},
{
title: 'PatternConfig',
description: 'Configure validation based on regular expressions for different keys within a provided expression object.',
link: '/api-reference/pattern-config'
},
{
title: 'RangeConfig',
description: 'Define a range validation for numbers with optional minimum and maximum allowed values.',
link: '/api-reference/range-config'
},
{
title: 'RelationalOperatorConfig',
description: 'Configure validation based on relational operators (likely used with other configs), with optional field name, value, and flag for array control.',
link: '/api-reference/relational-operator-config'
},
{
title: 'TimeConfig',
description: 'Configure validation based on relational operators (likely used with other configs), with optional field name, value, and flag for array control.',
link: '/api-reference/time-config'
},
{
title: 'DateConfig',
description: 'This configuration interface enables date-based validation customization, providing options for setting minimum and maximum date ranges.',
link: '/api-reference/date-config'
},
{
title: 'JsonConfig',
description: 'This configuration interface supports JSON structure validation, with options for defining required properties and valid JSON paths.',
link: '/api-reference/json-config'
}
]
}
]
Loading