kennzeichen 0.1.0

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.
@@ -0,0 +1,99 @@
1
+ /**
2
+ * A parsed German license plate with its three components.
3
+ * Example: "M-AB 1234" -> { part1: "M", part2: "AB", part3: "1234" }
4
+ */
5
+ type ParsedPlate = {
6
+ part1: string;
7
+ part2: string;
8
+ part3: string;
9
+ };
10
+ /**
11
+ * Result of parsing a license plate input.
12
+ */
13
+ type ParseResult = {
14
+ type: "unambiguous";
15
+ plate: ParsedPlate;
16
+ } | {
17
+ type: "ambiguous";
18
+ options: ParsedPlate[];
19
+ } | {
20
+ type: "partial";
21
+ plate: Partial<ParsedPlate>;
22
+ } | {
23
+ type: "invalid";
24
+ };
25
+
26
+ /**
27
+ * All valid German license plate location codes (Unterscheidungszeichen).
28
+ * 726 codes including umlauts (Ä, Ö, Ü).
29
+ */
30
+ declare const LOCATION: readonly ["A", "AA", "AB", "ABG", "ABI", "AC", "AE", "AH", "AIB", "AIC", "AK", "ALF", "ALZ", "AM", "AN", "ANA", "ANG", "ANK", "AÖ", "AP", "APD", "ARN", "ART", "AS", "ASL", "ASZ", "AT", "AU", "AUR", "AW", "AZ", "AZE", "B", "BA", "BAD", "BAR", "BB", "BBG", "BBL", "BC", "BCH", "BD", "BE", "BED", "BER", "BF", "BGD", "BGL", "BH", "BI", "BID", "BIN", "BIR", "BIT", "BIW", "BK", "BKS", "BL", "BLB", "BLK", "BM", "BN", "BNA", "BO", "BÖ", "BOG", "BOH", "BOR", "BOT", "BP", "BRA", "BRB", "BRG", "BRK", "BRL", "BRV", "BS", "BSB", "BSK", "BT", "BTF", "BÜD", "BUL", "BÜR", "BÜS", "BÜZ", "BW", "BWL", "BYL", "BZ", "C", "CA", "CAS", "CB", "CE", "CHA", "CLP", "CLZ", "CO", "COC", "COE", "CR", "CUX", "CW", "D", "DA", "DAH", "DAN", "DAU", "DBR", "DD", "DE", "DEG", "DEL", "DGF", "DH", "DI", "DIL", "DIN", "DIZ", "DKB", "DL", "DLG", "DM", "DN", "DO", "DON", "DU", "DUD", "DÜW", "DW", "DZ", "E", "EA", "EB", "EBE", "EBN", "EBS", "ECK", "ED", "EE", "EF", "EG", "EH", "EI", "EIC", "EIL", "EIN", "EIS", "EL", "EM", "EMD", "EMS", "EN", "ER", "ERB", "ERH", "ERK", "ERZ", "ES", "ESB", "ESW", "EU", "EW", "F", "FB", "FD", "FDB", "FDS", "FEU", "FF", "FFB", "FG", "FI", "FKB", "FL", "FLÖ", "FN", "FO", "FOR", "FR", "FRG", "FRI", "FRW", "FS", "FT", "FTL", "FÜ", "FÜS", "FW", "FZ", "G", "GA", "GAN", "GAP", "GC", "GD", "GDB", "GE", "GEL", "GEO", "GER", "GF", "GG", "GHA", "GHC", "GI", "GK", "GL", "GLA", "GM", "GMN", "GN", "GNT", "GÖ", "GOA", "GOH", "GP", "GR", "GRA", "GRH", "GRI", "GRM", "GRZ", "GS", "GT", "GTH", "GÜ", "GUB", "GUN", "GV", "GVM", "GW", "GZ", "H", "HA", "HAB", "HAL", "HAM", "HAS", "HB", "HBN", "HBS", "HC", "HCH", "HD", "HDH", "HDL", "HE", "HEB", "HEF", "HEI", "HEL", "HER", "HET", "HF", "HG", "HGN", "HGW", "HH", "HHM", "HI", "HIG", "HIP", "HK", "HL", "HM", "HMÜ", "HN", "HO", "HOG", "HOH", "HOL", "HOM", "HOR", "HÖS", "HOT", "HP", "HR", "HRO", "HS", "HSK", "HST", "HU", "HV", "HVL", "HWI", "HX", "HY", "HZ", "IGB", "IK", "IL", "ILL", "IN", "IZ", "J", "JE", "JL", "JÜL", "K", "KA", "KB", "KC", "KE", "KEH", "KEL", "KEM", "KF", "KG", "KH", "KI", "KIB", "KK", "KL", "KLE", "KLZ", "KM", "KN", "KO", "KÖN", "KÖT", "KÖZ", "KR", "KRU", "KS", "KT", "KU", "KÜN", "KUS", "KW", "KY", "KYF", "L", "LA", "LAN", "LAU", "LB", "LBS", "LBZ", "LC", "LD", "LDK", "LDS", "LEO", "LER", "LEV", "LF", "LG", "LH", "LI", "LIB", "LIF", "LIP", "LL", "LM", "LN", "LÖ", "LÖB", "LOS", "LP", "LR", "LRO", "LSA", "LSN", "LSZ", "LU", "LÜN", "LUP", "LWL", "M", "MA", "MAB", "MAI", "MAK", "MAL", "MB", "MC", "MD", "ME", "MED", "MEG", "MEI", "MEK", "MEL", "MER", "MET", "MG", "MGH", "MGN", "MH", "MHL", "MI", "MIL", "MK", "MKK", "ML", "MM", "MN", "MO", "MOD", "MOL", "MON", "MOS", "MQ", "MR", "MS", "MSE", "MSH", "MSP", "MST", "MTK", "MTL", "MUC", "MÜ", "MÜB", "MÜL", "MÜR", "MVL", "MW", "MY", "MYK", "MZ", "MZG", "N", "NAB", "NAI", "NAU", "NB", "ND", "NDH", "NE", "NEA", "NEB", "NEC", "NEN", "NES", "NEU", "NEW", "NF", "NH", "NI", "NK", "NL", "NM", "NMB", "NMS", "NÖ", "NOH", "NOL", "NOM", "NOR", "NP", "NR", "NRW", "NT", "NU", "NVP", "NW", "NWM", "NY", "NZ", "OA", "OAL", "OB", "OBB", "OBG", "OC", "OCH", "OD", "OE", "OF", "OG", "OH", "OHA", "ÖHR", "OHV", "OHZ", "OK", "OL", "OP", "OPR", "OS", "OSL", "OTW", "OVI", "OVL", "OVP", "OZ", "P", "PA", "PAF", "PAN", "PAR", "PB", "PCH", "PE", "PEG", "PF", "PI", "PIR", "PL", "PLÖ", "PM", "PN", "PR", "PRÜ", "PS", "PW", "PZ", "QFT", "QLB", "R", "RA", "RC", "RD", "RDG", "RE", "REG", "REH", "REI", "RG", "RH", "RI", "RID", "RIE", "RL", "RM", "RN", "RO", "ROD", "ROF", "ROK", "ROL", "ROS", "ROT", "ROW", "RP", "RPL", "RS", "RSL", "RT", "RU", "RÜD", "RÜG", "RV", "RW", "RZ", "S", "SAB", "SAD", "SAL", "SAN", "SAW", "SÄK", "SB", "SBG", "SBK", "SC", "SCZ", "SDH", "SDL", "SDT", "SE", "SEB", "SEE", "SEF", "SEL", "SFB", "SFT", "SG", "SGH", "SH", "SHA", "SHG", "SHK", "SHL", "SI", "SIG", "SIH", "SIM", "SK", "SL", "SLE", "SLF", "SLG", "SLK", "SLN", "SLS", "SLÜ", "SLZ", "SM", "SMÜ", "SN", "SO", "SOB", "SOG", "SOK", "SÖM", "SON", "SP", "SPB", "SPN", "SR", "SRB", "SRO", "ST", "STA", "STB", "STD", "STE", "STL", "STO", "SU", "SUL", "SÜW", "SW", "SWA", "SY", "SZ", "SZB", "TBB", "TDO", "TE", "TET", "TF", "TG", "THL", "THW", "TIR", "TO", "TÖL", "TP", "TR", "TS", "TT", "TÜ", "TUT", "UE", "UEM", "UFF", "UH", "UL", "UM", "UN", "USI", "ÜB", "V", "VAI", "VB", "VEC", "VER", "VG", "VIB", "VIE", "VIT", "VK", "VOH", "VR", "VS", "W", "WA", "WAF", "WAK", "WAN", "WAR", "WAT", "WB", "WBS", "WDA", "WE", "WEL", "WEN", "WER", "WES", "WF", "WG", "WHV", "WI", "WIL", "WIN", "WIS", "WIT", "WIV", "WIZ", "WK", "WL", "WLG", "WM", "WMS", "WN", "WND", "WO", "WOB", "WOH", "WOL", "WOR", "WOS", "WR", "WRN", "WS", "WSF", "WST", "WSW", "WT", "WTL", "WTM", "WÜ", "WUG", "WÜM", "WUN", "WUR", "WW", "WZ", "WZL", "X", "Y", "Z", "ZE", "ZEL", "ZI", "ZIG", "ZP", "ZR", "ZW", "ZZ"];
31
+ type LocationCode = (typeof LOCATION)[number];
32
+ /**
33
+ * Set of valid location codes for O(1) lookup.
34
+ */
35
+ declare const LOCATION_SET: Set<string>;
36
+
37
+ /**
38
+ * Parses a license plate input string into its component parts.
39
+ * Handles various input formats:
40
+ * - With hyphen: "M-AB 1234"
41
+ * - With spaces: "M AB 1234"
42
+ * - Without separators: "MAB1234"
43
+ *
44
+ * @returns ParseResult with one of:
45
+ * - unambiguous: single valid interpretation
46
+ * - ambiguous: multiple valid interpretations (user must choose)
47
+ * - partial: incomplete but valid so far
48
+ * - invalid: cannot be parsed
49
+ */
50
+ declare function parseLicensePlate(input: string): ParseResult;
51
+
52
+ /**
53
+ * Formats a parsed plate into the standard display format: "M-AB 1234"
54
+ */
55
+ declare function formatParsedPlate(plate: Partial<ParsedPlate>): string;
56
+ /**
57
+ * Formats a raw license plate string into the standard display format.
58
+ * Expects input like "M-AB1234" or "M-AB 1234" and returns "M-AB 1234".
59
+ * Returns the original input if it can't be parsed.
60
+ */
61
+ declare function formatPlateNo(input: string): string;
62
+
63
+ /**
64
+ * Removes all spaces and hyphens from a license plate string.
65
+ * Useful for storing or comparing plates in a normalized form.
66
+ *
67
+ * @example
68
+ * sanitizeLicensePlate("M-AB 1234") // "MAB1234"
69
+ */
70
+ declare function sanitizeLicensePlate(plate: string): string;
71
+ /**
72
+ * Alias for sanitizeLicensePlate.
73
+ * Removes all spaces and hyphens from a license plate string.
74
+ */
75
+ declare function cleanPlateNo(input: string): string;
76
+ /**
77
+ * Checks if a license plate string is valid (unambiguously parseable).
78
+ *
79
+ * @example
80
+ * isValidLicensePlate("M-AB 1234") // true
81
+ * isValidLicensePlate("XX-AB 1234") // false (invalid location)
82
+ * isValidLicensePlate("MAB1234") // true (can be unambiguously parsed)
83
+ */
84
+ declare function isValidLicensePlate(input: string): boolean;
85
+ /**
86
+ * Simple regex-based validation for formatted German license plates.
87
+ * Expects format: "LOC-XX 1234" or "LOC-XX 1234E/H"
88
+ *
89
+ * This is a lighter-weight check that doesn't validate the location code
90
+ * against the full list. Use isValidLicensePlate() for full validation.
91
+ *
92
+ * @example
93
+ * isValidLicensePlateFormat("M-AB 1234") // true
94
+ * isValidLicensePlateFormat("XX-AB 1234") // true (doesn't check location)
95
+ * isValidLicensePlateFormat("MAB1234") // false (wrong format)
96
+ */
97
+ declare function isValidLicensePlateFormat(input: string): boolean;
98
+
99
+ export { LOCATION, LOCATION_SET, type LocationCode, type ParseResult, type ParsedPlate, cleanPlateNo, formatParsedPlate, formatPlateNo, isValidLicensePlate, isValidLicensePlateFormat, parseLicensePlate, sanitizeLicensePlate };
@@ -0,0 +1,22 @@
1
+ import {
2
+ LOCATION,
3
+ LOCATION_SET,
4
+ cleanPlateNo,
5
+ formatParsedPlate,
6
+ formatPlateNo,
7
+ isValidLicensePlate,
8
+ isValidLicensePlateFormat,
9
+ parseLicensePlate,
10
+ sanitizeLicensePlate
11
+ } from "../chunk-WNVAHMV3.js";
12
+ export {
13
+ LOCATION,
14
+ LOCATION_SET,
15
+ cleanPlateNo,
16
+ formatParsedPlate,
17
+ formatPlateNo,
18
+ isValidLicensePlate,
19
+ isValidLicensePlateFormat,
20
+ parseLicensePlate,
21
+ sanitizeLicensePlate
22
+ };
@@ -0,0 +1,143 @@
1
+ import { ParseResult, ParsedPlate } from '../core/index.js';
2
+ export { LOCATION, LOCATION_SET, LocationCode, cleanPlateNo, formatParsedPlate, formatPlateNo, isValidLicensePlate, isValidLicensePlateFormat, parseLicensePlate, sanitizeLicensePlate } from '../core/index.js';
3
+ import { ReactNode } from 'react';
4
+
5
+ interface UseLicensePlateOptions {
6
+ /** Controlled value */
7
+ value?: string;
8
+ /** Called when the value changes */
9
+ onChange?: (value: string) => void;
10
+ /** Called when the input loses focus */
11
+ onBlur?: () => void;
12
+ }
13
+ interface UseLicensePlateReturn {
14
+ /** Current input value */
15
+ inputValue: string;
16
+ /** Current parse result */
17
+ parseResult: ParseResult;
18
+ /** Handler for input onChange event */
19
+ handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
20
+ /** Handler for input onKeyDown event (for dropdown navigation) */
21
+ handleKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
22
+ /** Handler for input onBlur event */
23
+ handleBlur: () => void;
24
+ /** Whether the disambiguation dropdown should be open */
25
+ isDropdownOpen: boolean;
26
+ /** Available options when input is ambiguous (null otherwise) */
27
+ options: ParsedPlate[] | null;
28
+ /** Currently highlighted option index */
29
+ activeIndex: number;
30
+ /** Select a specific option from the disambiguation dropdown */
31
+ selectOption: (option: ParsedPlate) => void;
32
+ /** Set the active (highlighted) option index */
33
+ setActiveIndex: (index: number) => void;
34
+ }
35
+ /**
36
+ * React hook for managing license plate input state.
37
+ * Handles parsing, formatting, and disambiguation.
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * function MyInput() {
42
+ * const lp = useLicensePlate({ value, onChange })
43
+ *
44
+ * return (
45
+ * <div>
46
+ * <input
47
+ * value={lp.inputValue}
48
+ * onChange={lp.handleChange}
49
+ * onKeyDown={lp.handleKeyDown}
50
+ * onBlur={lp.handleBlur}
51
+ * />
52
+ * {lp.isDropdownOpen && lp.options && (
53
+ * <ul>
54
+ * {lp.options.map((opt, i) => (
55
+ * <li
56
+ * key={i}
57
+ * className={i === lp.activeIndex ? 'active' : ''}
58
+ * onClick={() => lp.selectOption(opt)}
59
+ * >
60
+ * {formatParsedPlate(opt)}
61
+ * </li>
62
+ * ))}
63
+ * </ul>
64
+ * )}
65
+ * </div>
66
+ * )
67
+ * }
68
+ * ```
69
+ */
70
+ declare function useLicensePlate(options?: UseLicensePlateOptions): UseLicensePlateReturn;
71
+
72
+ interface InputProps {
73
+ value: string;
74
+ onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
75
+ onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
76
+ onBlur: () => void;
77
+ }
78
+ interface OptionProps {
79
+ onClick: () => void;
80
+ onMouseDown: (e: React.MouseEvent) => void;
81
+ onMouseEnter: () => void;
82
+ }
83
+ interface OptionItem {
84
+ /** The parsed plate data */
85
+ plate: ParsedPlate;
86
+ /** Pre-formatted display string (e.g., "M-AB 1234") */
87
+ formatted: string;
88
+ /** Whether this option is currently highlighted */
89
+ isActive: boolean;
90
+ /** Get props to spread on the option element */
91
+ getProps: () => OptionProps;
92
+ }
93
+ interface RenderProps {
94
+ /** Props to spread on the input element */
95
+ inputProps: InputProps;
96
+ /** Whether the disambiguation dropdown should be visible */
97
+ isOpen: boolean;
98
+ /** Disambiguation options (null when not ambiguous) */
99
+ options: OptionItem[] | null;
100
+ /** Current parse result */
101
+ parseResult: ParseResult;
102
+ }
103
+ interface LicensePlateInputProps {
104
+ /** Controlled value */
105
+ value?: string;
106
+ /** Called when the value changes */
107
+ onChange?: (value: string) => void;
108
+ /** Called when the input loses focus */
109
+ onBlur?: () => void;
110
+ /** Render function that receives the headless props */
111
+ children: (props: RenderProps) => ReactNode;
112
+ }
113
+ /**
114
+ * Headless license plate input component using render props.
115
+ * Provides all the state and handlers needed to build a license plate input.
116
+ *
117
+ * @example
118
+ * ```tsx
119
+ * <LicensePlateInput value={value} onChange={onChange}>
120
+ * {({ inputProps, isOpen, options }) => (
121
+ * <div className="relative">
122
+ * <input {...inputProps} className="border rounded px-2 py-1" />
123
+ * {isOpen && options && (
124
+ * <ul className="absolute mt-1 border rounded bg-white shadow">
125
+ * {options.map((opt) => (
126
+ * <li
127
+ * key={opt.formatted}
128
+ * className={opt.isActive ? 'bg-blue-100' : ''}
129
+ * {...opt.getProps()}
130
+ * >
131
+ * {opt.formatted}
132
+ * </li>
133
+ * ))}
134
+ * </ul>
135
+ * )}
136
+ * </div>
137
+ * )}
138
+ * </LicensePlateInput>
139
+ * ```
140
+ */
141
+ declare function LicensePlateInput({ value, onChange, onBlur, children, }: LicensePlateInputProps): ReactNode;
142
+
143
+ export { type InputProps, LicensePlateInput, type LicensePlateInputProps, type OptionItem, type OptionProps, ParseResult, ParsedPlate, type RenderProps, type UseLicensePlateOptions, type UseLicensePlateReturn, useLicensePlate };
@@ -0,0 +1,171 @@
1
+ import {
2
+ LOCATION,
3
+ LOCATION_SET,
4
+ cleanPlateNo,
5
+ formatParsedPlate,
6
+ formatPlateNo,
7
+ isValidLicensePlate,
8
+ isValidLicensePlateFormat,
9
+ parseLicensePlate,
10
+ sanitizeLicensePlate
11
+ } from "../chunk-WNVAHMV3.js";
12
+
13
+ // src/react/useLicensePlate.ts
14
+ import { useCallback, useEffect, useRef, useState } from "react";
15
+ function useLicensePlate(options = {}) {
16
+ const { value = "", onChange, onBlur } = options;
17
+ const [inputValue, setInputValue] = useState(value);
18
+ const [parseResult, setParseResult] = useState(
19
+ () => parseLicensePlate(value)
20
+ );
21
+ const [disambiguationOptions, setDisambiguationOptions] = useState(null);
22
+ const [activeIndex, setActiveIndex] = useState(0);
23
+ const [dropdownOpen, setDropdownOpen] = useState(false);
24
+ const isUserTyping = useRef(false);
25
+ useEffect(() => {
26
+ if (isUserTyping.current) {
27
+ return;
28
+ }
29
+ if (value !== inputValue) {
30
+ setInputValue(value);
31
+ setParseResult(parseLicensePlate(value));
32
+ }
33
+ }, [value]);
34
+ const handleChange = useCallback(
35
+ (e) => {
36
+ const newValue = e.target.value.toUpperCase();
37
+ isUserTyping.current = true;
38
+ setInputValue(newValue);
39
+ const result = parseLicensePlate(newValue);
40
+ setParseResult(result);
41
+ setActiveIndex(0);
42
+ if (result.type === "unambiguous") {
43
+ const formatted = formatParsedPlate(result.plate);
44
+ setInputValue(formatted);
45
+ setDisambiguationOptions(null);
46
+ setDropdownOpen(false);
47
+ isUserTyping.current = false;
48
+ onChange?.(formatted);
49
+ } else if (result.type === "ambiguous") {
50
+ setDisambiguationOptions(result.options);
51
+ setDropdownOpen(true);
52
+ onChange?.(newValue);
53
+ } else {
54
+ setDisambiguationOptions(null);
55
+ setDropdownOpen(false);
56
+ onChange?.(newValue);
57
+ }
58
+ },
59
+ [onChange]
60
+ );
61
+ const selectOption = useCallback(
62
+ (option) => {
63
+ const formatted = formatParsedPlate(option);
64
+ setInputValue(formatted);
65
+ setParseResult({ type: "unambiguous", plate: option });
66
+ setDisambiguationOptions(null);
67
+ setDropdownOpen(false);
68
+ isUserTyping.current = false;
69
+ onChange?.(formatted);
70
+ },
71
+ [onChange]
72
+ );
73
+ const handleKeyDown = useCallback(
74
+ (e) => {
75
+ if (!disambiguationOptions || !dropdownOpen) return;
76
+ if (e.key === "ArrowDown") {
77
+ e.preventDefault();
78
+ setActiveIndex(
79
+ (prev) => Math.min(prev + 1, disambiguationOptions.length - 1)
80
+ );
81
+ } else if (e.key === "ArrowUp") {
82
+ e.preventDefault();
83
+ setActiveIndex((prev) => Math.max(prev - 1, 0));
84
+ } else if (e.key === "Enter") {
85
+ e.preventDefault();
86
+ const selected = disambiguationOptions[activeIndex];
87
+ if (selected) {
88
+ selectOption(selected);
89
+ }
90
+ } else if (e.key === "Escape") {
91
+ setDropdownOpen(false);
92
+ }
93
+ },
94
+ [disambiguationOptions, dropdownOpen, activeIndex, selectOption]
95
+ );
96
+ const handleBlur = useCallback(() => {
97
+ setTimeout(() => {
98
+ setDropdownOpen(false);
99
+ isUserTyping.current = false;
100
+ onBlur?.();
101
+ }, 150);
102
+ }, [onBlur]);
103
+ return {
104
+ inputValue,
105
+ parseResult,
106
+ handleChange,
107
+ handleKeyDown,
108
+ handleBlur,
109
+ isDropdownOpen: dropdownOpen,
110
+ options: disambiguationOptions,
111
+ activeIndex,
112
+ selectOption,
113
+ setActiveIndex
114
+ };
115
+ }
116
+
117
+ // src/react/LicensePlateInput.tsx
118
+ function LicensePlateInput({
119
+ value,
120
+ onChange,
121
+ onBlur,
122
+ children
123
+ }) {
124
+ const {
125
+ inputValue,
126
+ parseResult,
127
+ handleChange,
128
+ handleKeyDown,
129
+ handleBlur,
130
+ isDropdownOpen,
131
+ options: rawOptions,
132
+ activeIndex,
133
+ selectOption,
134
+ setActiveIndex
135
+ } = useLicensePlate({ value, onChange, onBlur });
136
+ const inputProps = {
137
+ value: inputValue,
138
+ onChange: handleChange,
139
+ onKeyDown: handleKeyDown,
140
+ onBlur: handleBlur
141
+ };
142
+ const options = rawOptions ? rawOptions.map((plate, index) => ({
143
+ plate,
144
+ formatted: formatParsedPlate(plate),
145
+ isActive: index === activeIndex,
146
+ getProps: () => ({
147
+ onClick: () => selectOption(plate),
148
+ onMouseDown: (e) => e.preventDefault(),
149
+ onMouseEnter: () => setActiveIndex(index)
150
+ })
151
+ })) : null;
152
+ return children({
153
+ inputProps,
154
+ isOpen: isDropdownOpen,
155
+ options,
156
+ parseResult
157
+ });
158
+ }
159
+ export {
160
+ LOCATION,
161
+ LOCATION_SET,
162
+ LicensePlateInput,
163
+ cleanPlateNo,
164
+ formatParsedPlate,
165
+ formatPlateNo,
166
+ isValidLicensePlate,
167
+ isValidLicensePlateFormat,
168
+ parseLicensePlate,
169
+ sanitizeLicensePlate,
170
+ useLicensePlate
171
+ };
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "kennzeichen",
3
+ "version": "0.1.0",
4
+ "description": "German license plate parsing and validation",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/core/index.js",
10
+ "types": "./dist/core/index.d.ts"
11
+ },
12
+ "./core": {
13
+ "import": "./dist/core/index.js",
14
+ "types": "./dist/core/index.d.ts"
15
+ },
16
+ "./react": {
17
+ "import": "./dist/react/index.js",
18
+ "types": "./dist/react/index.d.ts"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "test": "vitest run",
27
+ "lint": "oxlint -D recommended --ignore-pattern node_modules",
28
+ "typecheck": "tsc --noEmit"
29
+ },
30
+ "peerDependencies": {
31
+ "react": ">=17.0.0"
32
+ },
33
+ "peerDependenciesMeta": {
34
+ "react": {
35
+ "optional": true
36
+ }
37
+ },
38
+ "devDependencies": {
39
+ "@types/react": "^18.0.0",
40
+ "oxlint": "^0.16.0",
41
+ "react": "^18.0.0",
42
+ "tsup": "^8.0.0",
43
+ "typescript": "^5.0.0",
44
+ "vitest": "^2.0.0"
45
+ },
46
+ "keywords": [
47
+ "german",
48
+ "license-plate",
49
+ "kennzeichen",
50
+ "parser",
51
+ "validation"
52
+ ],
53
+ "license": "MIT",
54
+ "author": "Canida Software <bui.qd@canida.io>",
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "git+https://github.com/canida-software/kennzeichen.git"
58
+ },
59
+ "homepage": "https://github.com/canida-software/kennzeichen#readme",
60
+ "bugs": {
61
+ "url": "https://github.com/canida-software/kennzeichen/issues"
62
+ }
63
+ }