Skip to content

Commit 8e66ea8

Browse files
committed
chore: add google map components
1 parent 41b7ce4 commit 8e66ea8

19 files changed

+481
-47
lines changed

bun.lock

+5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
"packages/vue": {
2828
"name": "ts-inputs-vue",
2929
"version": "0.0.1",
30+
"dependencies": {
31+
"@types/google.maps": "^3.58.1",
32+
},
3033
"devDependencies": {
3134
"@microsoft/api-extractor": "^7.52.2",
3235
"@stacksjs/docs": "^0.70.10",
@@ -544,6 +547,8 @@
544547

545548
"@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
546549

550+
"@types/google.maps": ["@types/google.maps@3.58.1", "", {}, "sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ=="],
551+
547552
"@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
548553

549554
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],

docs/.vitepress/components.d.ts

+6
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,17 @@ export {}
88
/* prettier-ignore */
99
declare module 'vue' {
1010
export interface GlobalComponents {
11+
copy: typeof import('./theme/components/CreditCardDemo copy.vue')['default']
1112
CreditCardDemo: typeof import('./theme/components/CreditCardDemo.vue')['default']
13+
DateInput: typeof import('./theme/components/DateInput.vue')['default']
14+
DateInputDemo: typeof import('./theme/components/DateInputDemo.vue')['default']
15+
GooglePlacesInputDemo: typeof import('./theme/components/GooglePlacesInputDemo.vue')['default']
1216
Home: typeof import('./theme/components/Home.vue')['default']
1317
HomeContributors: typeof import('./theme/components/HomeContributors.vue')['default']
1418
HomeSponsors: typeof import('./theme/components/HomeSponsors.vue')['default']
1519
HomeTeam: typeof import('./theme/components/HomeTeam.vue')['default']
20+
NumeralInputDemo: typeof import('./theme/components/NumeralInputDemo.vue')['default']
1621
TeamMember: typeof import('./theme/components/TeamMember.vue')['default']
22+
TimeInputDemo: typeof import('./theme/components/TimeInputDemo.vue')['default']
1723
}
1824
}

docs/.vitepress/config.ts

+17-6
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,24 @@ const sidebar = [
7171
{
7272
text: 'Advanced',
7373
items: [
74-
{ text: 'Overview', link: '/vue/' },
75-
{ text: 'Credit Card Input', link: '/vue/credit-card' },
76-
{ text: 'Date Input', link: '/vue/date' },
77-
{ text: 'Time Input', link: '/vue/time' },
78-
{ text: 'Numeral Input', link: '/vue/numeral' },
74+
{
75+
text: 'Vue ',
76+
items: [
77+
{ text: 'Overview', link: '/vue/' },
78+
{ text: 'Credit Card Input', link: '/vue/credit-card' },
79+
{ text: 'Date Input', link: '/vue/date' },
80+
{ text: 'Time Input', link: '/vue/time' },
81+
{ text: 'Numeral Input', link: '/vue/numeral' },
82+
{ text: 'Google Places Autocomplete', link: '/vue/google-places' },
83+
],
84+
},
85+
{
86+
text: 'React',
87+
items: [
88+
{ text: 'Coming Soon' },
89+
],
90+
},
7991
],
80-
8192
},
8293
{ text: 'Showcase', link: '/Showcase' },
8394
]

docs/.vitepress/theme/components/CreditCardDemo.vue

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ function handleCardTypeChange(type: CreditCardType) {
1313
<template>
1414
<CreditCardInput
1515
v-model="cardNumber"
16+
class="block w-1/3 rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6"
1617
placeholder="Enter card number"
1718
@card-type-change="handleCardTypeChange"
1819
/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script setup lang="ts">
2+
import { DateInput } from 'ts-inputs-vue'
3+
import { ref } from 'vue'
4+
5+
const date = ref('')
6+
</script>
7+
8+
<template>
9+
<DateInput
10+
v-model="date"
11+
class="block w-1/3 rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6"
12+
pattern="YYYY-MM-DD"
13+
placeholder="Enter date"
14+
/>
15+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<script setup lang="ts">
2+
import { GooglePlacesInput } from 'ts-inputs-vue'
3+
import { ref } from 'vue'
4+
5+
const location = ref('')
6+
const apiKey = 'AIzaSyCtD4sE0Pvyy6Ey1GSAneSFQIVJA0aBjxE'
7+
8+
function handlePlaceSelected(place: google.maps.places.PlaceResult) {
9+
console.log('Selected place:', place)
10+
// Access place.geometry.location for coordinates
11+
// Access place.formatted_address for the full address
12+
}
13+
</script>
14+
15+
<template>
16+
<GooglePlacesInput
17+
v-model="location"
18+
class="block w-1/3 rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6 "
19+
:api-key="apiKey"
20+
@place-selected="handlePlaceSelected"
21+
/>
22+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script setup lang="ts">
2+
import { NumeralInput } from 'ts-inputs-vue'
3+
import { ref } from 'vue'
4+
5+
const number = ref('')
6+
</script>
7+
8+
<template>
9+
<NumeralInput
10+
v-model="number"
11+
class="block w-1/3 rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6"
12+
thousand-group-style="thousand"
13+
placeholder="Enter number"
14+
/>
15+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script setup lang="ts">
2+
import { TimeInput } from 'ts-inputs-vue'
3+
import { ref } from 'vue'
4+
5+
const time = ref('')
6+
</script>
7+
8+
<template>
9+
<TimeInput
10+
v-model="time"
11+
class="block w-1/3 rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6"
12+
format="24h"
13+
placeholder="Enter time"
14+
/>
15+
</template>

docs/vue/credit-card.md

+12-7
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,18 @@ function handleCardTypeChange(type: CreditCardType) {
3131

3232
## Props
3333

34-
- `modelValue` (required): The v-model value
35-
- `delimiter` (optional): Custom delimiter (defaults to space)
36-
- `className` (optional): Additional CSS classes
37-
- `placeholder` (optional): Input placeholder text
38-
- `options` (optional): Additional formatting options
34+
| Prop | Type | Default | Description |
35+
|------|------|---------|-------------|
36+
| `modelValue` | `string` | `''` | The v-model binding value |
37+
| `delimiter` | `string` | `' '` | Custom delimiter for card number formatting |
38+
| `className` | `string` | - | Additional CSS classes |
39+
| `placeholder` | `string` | - | Input placeholder text |
40+
| `options` | `object` | - | Additional formatting options |
3941

4042
## Events
4143

42-
- `update:modelValue`: Emitted when the value changes
43-
- `cardTypeChange`: Emitted when the card type is detected
44+
| Event | Payload | Description |
45+
|-------|---------|-------------|
46+
| `update:modelValue` | `string` | Emitted when the input value changes |
47+
| `cardTypeChange` | `CreditCardType` | Emitted when the card type is detected |
48+
| `blur` | `Event` | Emitted when the input loses focus |

docs/vue/date.md

+15-6
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,23 @@ const date = ref('')
2020
</template>
2121
```
2222

23+
## Demo
24+
25+
<DateInputDemo />
26+
2327
## Props
2428

25-
- `modelValue` (required): The v-model value
26-
- `pattern` (optional): Date format pattern (defaults to 'YYYY-MM-DD')
27-
- `className` (optional): Additional CSS classes
28-
- `placeholder` (optional): Input placeholder text
29-
- `options` (optional): Additional formatting options
29+
| Prop | Type | Default | Description |
30+
|------|------|---------|-------------|
31+
| `modelValue` | `string` | `''` | The v-model binding value |
32+
| `pattern` | `string` | `'YYYY-MM-DD'` | Date format pattern |
33+
| `className` | `string` | - | Additional CSS classes |
34+
| `placeholder` | `string` | - | Input placeholder text |
35+
| `options` | `object` | - | Additional formatting options |
3036

3137
## Events
3238

33-
- `update:modelValue`: Emitted when the value changes
39+
| Event | Payload | Description |
40+
|-------|---------|-------------|
41+
| `update:modelValue` | `string` | Emitted when the input value changes |
42+
| `blur` | `Event` | Emitted when the input loses focus |

docs/vue/google-places.md

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Google Places Autocomplete
2+
3+
A Vue component that provides Google Places Autocomplete functionality with a clean and customizable interface.
4+
5+
## Usage
6+
7+
```vue
8+
<script setup lang="ts">
9+
import { GooglePlacesInputDemo } from 'ts-inputs-vue'
10+
import { ref } from 'vue'
11+
12+
const location = ref('')
13+
14+
function handlePlaceChanged(place: google.maps.places.PlaceResult) {
15+
console.log('Selected place:', place)
16+
// Access place.geometry.location for coordinates
17+
// Access place.formatted_address for the full address
18+
}
19+
</script>
20+
21+
<template>
22+
<GooglePlacesInputDemo
23+
v-model="location"
24+
api-key="YOUR_GOOGLE_MAPS_API_KEY"
25+
placeholder="Enter a location"
26+
@place-changed="handlePlaceChanged"
27+
/>
28+
</template>
29+
```
30+
31+
## Demo
32+
33+
<GooglePlacesInputDemo />
34+
35+
## Props
36+
37+
| Prop | Type | Default | Description |
38+
|------|------|---------|-------------|
39+
| `modelValue` | `string` | `''` | The v-model binding value |
40+
| `apiKey` | `string` | - | Your Google Maps API key (required) |
41+
| `placeholder` | `string` | `'Enter a location'` | Input placeholder text |
42+
| `disabled` | `boolean` | `false` | Whether the input is disabled |
43+
| `error` | `boolean` | `false` | Whether to show error state |
44+
| `types` | `string[]` | `['address']` | Array of place types to search for |
45+
| `componentRestrictions` | `{ country: string \| string[] }` | `{ country: 'us' }` | Country restrictions for search results |
46+
47+
## Events
48+
49+
| Event | Payload | Description |
50+
|-------|---------|-------------|
51+
| `update:modelValue` | `string` | Emitted when the input value changes |
52+
| `placeChanged` | `google.maps.places.PlaceResult` | Emitted when a place is selected, returns the full place details |
53+
| `blur` | `Event` | Emitted when the input loses focus |
54+
55+
## Place Types
56+
57+
You can specify different types of places to search for using the `types` prop. Common types include:
58+
59+
- `'address'` - Addresses only
60+
- `'establishment'` - Business locations
61+
- `'geocode'` - Geocoded locations
62+
- `'(regions)'` - Cities, states, countries
63+
- `'(cities)'` - Cities only
64+
65+
Example with multiple types:
66+
67+
```vue
68+
<GooglePlacesInputDemo
69+
:types="['address', 'establishment']"
70+
api-key="YOUR_API_KEY"
71+
/>
72+
```
73+
74+
## Country Restrictions
75+
76+
You can restrict results to specific countries using the `componentRestrictions` prop:
77+
78+
```vue
79+
<GooglePlacesInputDemo
80+
:component-restrictions="{ country: ['us', 'ca'] }"
81+
api-key="YOUR_API_KEY"
82+
/>
83+
```
84+
85+
## Styling
86+
87+
The component comes with default styling but can be customized using CSS. The following classes are available:
88+
89+
- `.google-places-autocomplete` - The main container
90+
- `.suggestions` - The dropdown container
91+
- `.suggestion-item` - Individual suggestion items
92+
- `.suggestion-item--active` - Active/hovered suggestion item
93+
94+
Example custom styling:
95+
96+
```css
97+
.google-places-autocomplete {
98+
/* Custom styles */
99+
}
100+
101+
.suggestions {
102+
/* Custom dropdown styles */
103+
}
104+
105+
.suggestion-item {
106+
/* Custom suggestion item styles */
107+
}
108+
```
109+
110+
## Google Maps API Setup
111+
112+
1. Get a Google Maps API key from the [Google Cloud Console](https://console.cloud.google.com/)
113+
2. Enable the Places API for your project
114+
3. Add the API key to your component
115+
116+
## Error Handling
117+
118+
The component includes basic error handling for API requests. You can listen for errors in the console or implement your own error handling:
119+
120+
```vue
121+
<script setup lang="ts">
122+
function handleError(error: Error) {
123+
// Handle the error
124+
console.error('Google Places error:', error)
125+
}
126+
</script>
127+
128+
<template>
129+
<GooglePlacesInputDemo
130+
api-key="YOUR_API_KEY"
131+
@error="handleError"
132+
/>
133+
</template>
134+
```
135+
136+
## TypeScript Support
137+
138+
The component is fully typed with TypeScript. You can import the types from the package:
139+
140+
```typescript
141+
import type { AutocompletePrediction } from '@types/google.maps'
142+
```

docs/vue/index.md

+24-10
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
11
# Vue Components
22

3-
`ts-inputs` provides a set of pre-built Vue components that make it easy to integrate formatted inputs into your Vue applications. These components handle all the formatting logic internally while providing a familiar Vue interface.
3+
The Vue package provides a set of input components that are built on top of the core `ts-inputs` package. These components are designed to be easy to use and highly customizable.
4+
5+
## Available Components
6+
7+
- [Credit Card Input](/vue/credit-card) - Input component for credit card numbers with automatic formatting
8+
- [Date Input](/vue/date) - Input component for dates with various formatting options
9+
- [Time Input](/vue/time) - Input component for time values with 12/24 hour format support
10+
- [Numeral Input](/vue/numeral) - Input component for numerical values with formatting options
11+
- [Google Places Autocomplete](/vue/google-places) - Input component for Google Places Autocomplete with address suggestions
412

513
## Installation
614

715
Make sure you have `ts-inputs` installed in your project:
816

9-
```bash
10-
# using bun
11-
bun add ts-inputs
17+
::: code-group
1218

13-
# using npm
14-
npm install ts-inputs
19+
```sh [npm]
20+
npm install --save-dev ts-inputs-vue
21+
```
1522

16-
# using yarn
17-
yarn add ts-inputs
23+
```sh [bun]
24+
bun add --dev ts-inputs-vue
25+
```
1826

19-
# using pnpm
20-
pnpm add ts-inputs
27+
```sh [pnpm]
28+
pnpm add --save-dev ts-inputs-vue
2129
```
2230

31+
```sh [yarn]
32+
yarn add --dev ts-inputs-vue
33+
```
34+
35+
:::
36+
2337
## Common Features
2438

2539
All input components share these common features:

0 commit comments

Comments
 (0)