kennzeichen 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -82
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,38 +18,28 @@ npm install kennzeichen
|
|
|
18
18
|
|
|
19
19
|
## Usage
|
|
20
20
|
|
|
21
|
-
###
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
import { parseLicensePlate, isValidLicensePlate } from "kennzeichen";
|
|
25
|
-
|
|
26
|
-
// Parse a license plate
|
|
27
|
-
parseLicensePlate("M-AB 1234");
|
|
28
|
-
// { type: 'unambiguous', plate: { part1: 'M', part2: 'AB', part3: '1234' } }
|
|
29
|
-
|
|
30
|
-
// Ambiguous input returns multiple options
|
|
31
|
-
parseLicensePlate("CEE1234");
|
|
32
|
-
// { type: 'ambiguous', options: [...] }
|
|
33
|
-
|
|
34
|
-
// Validate
|
|
35
|
-
isValidLicensePlate("M-AB 1234"); // true
|
|
36
|
-
isValidLicensePlate("XX-AB 1234"); // false
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Parse Result Types
|
|
21
|
+
### React Headless Component
|
|
40
22
|
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
| { type: "unambiguous"; plate: ParsedPlate } // Single valid interpretation
|
|
44
|
-
| { type: "ambiguous"; options: ParsedPlate[] } // Multiple valid interpretations
|
|
45
|
-
| { type: "partial"; plate: Partial<ParsedPlate> } // Incomplete but valid so far
|
|
46
|
-
| { type: "invalid" }; // Cannot be parsed
|
|
23
|
+
```tsx
|
|
24
|
+
import { LicensePlateInput } from "kennzeichen/react";
|
|
47
25
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
26
|
+
function MyInput({ value, onChange }) {
|
|
27
|
+
return (
|
|
28
|
+
<LicensePlateInput value={value} onChange={onChange}>
|
|
29
|
+
{({ inputProps, isOpen, options }) => (
|
|
30
|
+
<div>
|
|
31
|
+
<input {...inputProps} />
|
|
32
|
+
{isOpen &&
|
|
33
|
+
options?.map((opt) => (
|
|
34
|
+
<button key={opt.formatted} {...opt.getProps()}>
|
|
35
|
+
{opt.formatted}
|
|
36
|
+
</button>
|
|
37
|
+
))}
|
|
38
|
+
</div>
|
|
39
|
+
)}
|
|
40
|
+
</LicensePlateInput>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
53
43
|
```
|
|
54
44
|
|
|
55
45
|
### React Hook
|
|
@@ -75,28 +65,77 @@ function LicensePlateInput({ value, onChange }) {
|
|
|
75
65
|
}
|
|
76
66
|
```
|
|
77
67
|
|
|
78
|
-
###
|
|
68
|
+
### Vanilla HTML + JavaScript
|
|
79
69
|
|
|
80
|
-
|
|
81
|
-
import { LicensePlateInput } from "kennzeichen/react";
|
|
70
|
+
Use via CDN - no build step required:
|
|
82
71
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
72
|
+
```html
|
|
73
|
+
<input type="text" id="plate-input" placeholder="Enter license plate...">
|
|
74
|
+
<div id="result"></div>
|
|
75
|
+
|
|
76
|
+
<script type="module" src="app.js"></script>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
// app.js
|
|
81
|
+
import { parseLicensePlate, formatParsedPlate } from
|
|
82
|
+
"https://cdn.jsdelivr.net/npm/kennzeichen/+esm"
|
|
83
|
+
|
|
84
|
+
const input = document.getElementById("plate-input")
|
|
85
|
+
const result = document.getElementById("result")
|
|
86
|
+
|
|
87
|
+
input.addEventListener("input", (e) => {
|
|
88
|
+
const parsed = parseLicensePlate(e.target.value)
|
|
89
|
+
|
|
90
|
+
if (parsed.type === "unambiguous") {
|
|
91
|
+
result.textContent = formatParsedPlate(parsed.plate)
|
|
92
|
+
} else if (parsed.type === "ambiguous") {
|
|
93
|
+
result.textContent = "Did you mean: " +
|
|
94
|
+
parsed.options.map(formatParsedPlate).join(" or ")
|
|
95
|
+
} else if (parsed.type === "invalid") {
|
|
96
|
+
result.textContent = "Invalid plate"
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Core API
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { parseLicensePlate } from "kennzeichen"
|
|
105
|
+
|
|
106
|
+
const result = parseLicensePlate("M-AB 1234")
|
|
107
|
+
|
|
108
|
+
if (result.type === "unambiguous") {
|
|
109
|
+
console.log(result.plate)
|
|
110
|
+
// { part1: "M", part2: "AB", part3: "1234" }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (result.type === "ambiguous") {
|
|
114
|
+
// User needs to pick one
|
|
115
|
+
console.log(result.options)
|
|
99
116
|
}
|
|
117
|
+
|
|
118
|
+
if (result.type === "invalid") {
|
|
119
|
+
// Not a valid German license plate
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### Validate
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { isValidLicensePlate } from "kennzeichen"
|
|
127
|
+
|
|
128
|
+
isValidLicensePlate("M-AB 1234") // true
|
|
129
|
+
isValidLicensePlate("XX-AB 1234") // false (invalid location)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Format
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { formatParsedPlate } from "kennzeichen"
|
|
136
|
+
|
|
137
|
+
formatParsedPlate({ part1: "M", part2: "AB", part3: "1234" })
|
|
138
|
+
// "M-AB 1234"
|
|
100
139
|
```
|
|
101
140
|
|
|
102
141
|
## API Reference
|
|
@@ -105,19 +144,15 @@ function MyInput({ value, onChange }) {
|
|
|
105
144
|
|
|
106
145
|
#### `parseLicensePlate(input: string): ParseResult`
|
|
107
146
|
|
|
108
|
-
Parses a license plate input string
|
|
109
|
-
|
|
110
|
-
- With hyphen: `"M-AB 1234"`
|
|
111
|
-
- With spaces: `"M AB 1234"`
|
|
112
|
-
- Without separators: `"MAB1234"`
|
|
147
|
+
Parses a license plate input string. Handles various formats: `"M-AB 1234"`, `"M AB 1234"`, `"MAB1234"`.
|
|
113
148
|
|
|
114
149
|
#### `formatParsedPlate(plate: Partial<ParsedPlate>): string`
|
|
115
150
|
|
|
116
|
-
Formats a parsed plate into
|
|
151
|
+
Formats a parsed plate into standard display format: `"M-AB 1234"`.
|
|
117
152
|
|
|
118
153
|
#### `isValidLicensePlate(input: string): boolean`
|
|
119
154
|
|
|
120
|
-
Returns `true` if the input
|
|
155
|
+
Returns `true` if the input is a valid, unambiguous German license plate.
|
|
121
156
|
|
|
122
157
|
#### `sanitizeLicensePlate(plate: string): string`
|
|
123
158
|
|
|
@@ -127,52 +162,52 @@ Removes all spaces and hyphens from a license plate string.
|
|
|
127
162
|
|
|
128
163
|
Array of all 726 valid German location codes.
|
|
129
164
|
|
|
130
|
-
|
|
165
|
+
### React
|
|
131
166
|
|
|
132
|
-
|
|
167
|
+
#### `<LicensePlateInput>` (Headless Component)
|
|
133
168
|
|
|
134
|
-
|
|
169
|
+
Render props component for license plate input.
|
|
170
|
+
|
|
171
|
+
**Props:**
|
|
172
|
+
- `value?: string` - Controlled value
|
|
173
|
+
- `onChange?: (value: string) => void` - Called when value changes
|
|
174
|
+
- `children: (props: RenderProps) => ReactNode` - Render function
|
|
175
|
+
|
|
176
|
+
**RenderProps:**
|
|
177
|
+
- `inputProps` - Props to spread on input element
|
|
178
|
+
- `isOpen: boolean` - Whether dropdown should be visible
|
|
179
|
+
- `options: OptionItem[] | null` - Disambiguation options with helper methods
|
|
135
180
|
|
|
136
181
|
#### `useLicensePlate(options): UseLicensePlateReturn`
|
|
137
182
|
|
|
138
183
|
React hook for managing license plate input state.
|
|
139
184
|
|
|
140
185
|
**Options:**
|
|
141
|
-
|
|
142
186
|
- `value?: string` - Controlled value
|
|
143
187
|
- `onChange?: (value: string) => void` - Called when value changes
|
|
144
|
-
- `onBlur?: () => void` - Called when input loses focus
|
|
145
188
|
|
|
146
189
|
**Returns:**
|
|
147
|
-
|
|
148
190
|
- `inputValue: string` - Current input value
|
|
149
|
-
- `parseResult: ParseResult` - Current parse result
|
|
150
191
|
- `handleChange` - Input onChange handler
|
|
151
|
-
- `handleKeyDown` - Input onKeyDown handler (for dropdown navigation)
|
|
152
|
-
- `handleBlur` - Input onBlur handler
|
|
153
192
|
- `isDropdownOpen: boolean` - Whether dropdown should be visible
|
|
154
193
|
- `options: ParsedPlate[] | null` - Disambiguation options
|
|
155
|
-
- `activeIndex: number` - Currently highlighted option
|
|
156
194
|
- `selectOption(option)` - Select a disambiguation option
|
|
157
|
-
- `setActiveIndex(index)` - Set highlighted option
|
|
158
|
-
|
|
159
|
-
#### `<LicensePlateInput>` (Headless Component)
|
|
160
195
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
**Props:**
|
|
196
|
+
### Types
|
|
164
197
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
198
|
+
```typescript
|
|
199
|
+
type ParseResult =
|
|
200
|
+
| { type: "unambiguous"; plate: ParsedPlate }
|
|
201
|
+
| { type: "ambiguous"; options: ParsedPlate[] }
|
|
202
|
+
| { type: "partial"; plate: Partial<ParsedPlate> }
|
|
203
|
+
| { type: "invalid" }
|
|
171
204
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
205
|
+
type ParsedPlate = {
|
|
206
|
+
part1: string // Location code (e.g., 'M', 'HH', 'BGL')
|
|
207
|
+
part2: string // Letters (e.g., 'AB', 'X')
|
|
208
|
+
part3: string // Numbers + optional suffix (e.g., '1234', '99E', '42H')
|
|
209
|
+
}
|
|
210
|
+
```
|
|
176
211
|
|
|
177
212
|
## License
|
|
178
213
|
|