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.
Files changed (2) hide show
  1. package/README.md +117 -82
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -18,38 +18,28 @@ npm install kennzeichen
18
18
 
19
19
  ## Usage
20
20
 
21
- ### Core
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
- ```typescript
42
- type ParseResult =
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
- type ParsedPlate = {
49
- part1: string; // Location code (e.g., 'M', 'HH', 'BGL')
50
- part2: string; // Letters (e.g., 'AB', 'X')
51
- part3: string; // Numbers + optional suffix (e.g., '1234', '99E', '42H')
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
- ### React Headless Component
68
+ ### Vanilla HTML + JavaScript
79
69
 
80
- ```tsx
81
- import { LicensePlateInput } from "kennzeichen/react";
70
+ Use via CDN - no build step required:
82
71
 
83
- function MyInput({ value, onChange }) {
84
- return (
85
- <LicensePlateInput value={value} onChange={onChange}>
86
- {({ inputProps, isOpen, options }) => (
87
- <div>
88
- <input {...inputProps} />
89
- {isOpen &&
90
- options?.map((opt) => (
91
- <button key={opt.formatted} {...opt.getProps()}>
92
- {opt.formatted}
93
- </button>
94
- ))}
95
- </div>
96
- )}
97
- </LicensePlateInput>
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 into its component parts. Handles various input formats:
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 the standard display format: `"M-AB 1234"`.
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 can be unambiguously parsed as a valid German license plate.
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
- #### `LOCATION_SET: Set<string>`
165
+ ### React
131
166
 
132
- Set of all valid location codes for O(1) lookup.
167
+ #### `<LicensePlateInput>` (Headless Component)
133
168
 
134
- ### React
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
- Render props component for license plate input.
162
-
163
- **Props:**
196
+ ### Types
164
197
 
165
- - `value?: string` - Controlled value
166
- - `onChange?: (value: string) => void` - Called when value changes
167
- - `onBlur?: () => void` - Called when input loses focus
168
- - `children: (props: RenderProps) => ReactNode` - Render function
169
-
170
- **RenderProps:**
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
- - `inputProps` - Props to spread on input element
173
- - `isOpen: boolean` - Whether dropdown should be visible
174
- - `options: OptionItem[] | null` - Disambiguation options with helper methods
175
- - `parseResult: ParseResult` - Current parse result
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kennzeichen",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "German license plate parsing and validation",
5
5
  "keywords": [
6
6
  "german",