✨ MAJOR FEATURES: • Auto-zoom intelligence với smart bounds fitting • Enhanced 3D GPS markers với pulsing effects • Professional route display với 6-layer rendering • Status-based parking icons với availability indicators • Production-ready build optimizations 🗺️ AUTO-ZOOM FEATURES: • Smart bounds fitting cho GPS + selected parking • Adaptive padding (50px) cho visual balance • Max zoom control (level 16) để tránh quá gần • Dynamic centering khi không có selection 🎨 ENHANCED VISUALS: • 3D GPS marker với multi-layer pulse effects • Advanced parking icons với status colors • Selection highlighting với animation • Dimming system cho non-selected items 🛣️ ROUTE SYSTEM: • OpenRouteService API integration • Multi-layer route rendering (glow, shadow, main, animated) • Real-time distance & duration calculation • Visual route info trong popup 📱 PRODUCTION READY: • SSR safe với dynamic imports • Build errors resolved • Global deployment via Vercel • Optimized performance 🌍 DEPLOYMENT: • Vercel: https://whatever-ctk2auuxr-phong12hexdockworks-projects.vercel.app • Bundle size: 22.8 kB optimized • Global CDN distribution • HTTPS enabled 💾 VERSION CONTROL: • MapView-v2.0.tsx backup created • MAPVIEW_VERSIONS.md documentation • Full version history tracking
103 lines
3.4 KiB
JavaScript
103 lines
3.4 KiB
JavaScript
// When phone numbers are written in `RFC3966` format — `"tel:+12133734253"` —
|
|
// they can have their "calling code" part written separately in a `phone-context` parameter.
|
|
// Example: `"tel:12133734253;phone-context=+1"`.
|
|
// This function parses the full phone number from the local number and the `phone-context`
|
|
// when the `phone-context` contains a `+` sign.
|
|
|
|
import {
|
|
VALID_DIGITS,
|
|
// PLUS_CHARS
|
|
} from '../constants.js'
|
|
|
|
export const PLUS_SIGN = '+'
|
|
|
|
const RFC3966_VISUAL_SEPARATOR_ = '[\\-\\.\\(\\)]?'
|
|
|
|
const RFC3966_PHONE_DIGIT_ = '(' + '[' + VALID_DIGITS + ']' + '|' + RFC3966_VISUAL_SEPARATOR_ + ')'
|
|
|
|
const RFC3966_GLOBAL_NUMBER_DIGITS_ =
|
|
'^' +
|
|
'\\' +
|
|
PLUS_SIGN +
|
|
RFC3966_PHONE_DIGIT_ +
|
|
'*' +
|
|
'[' + VALID_DIGITS + ']' +
|
|
RFC3966_PHONE_DIGIT_ +
|
|
'*' +
|
|
'$'
|
|
|
|
/**
|
|
* Regular expression of valid global-number-digits for the phone-context
|
|
* parameter, following the syntax defined in RFC3966.
|
|
*/
|
|
const RFC3966_GLOBAL_NUMBER_DIGITS_PATTERN_ = new RegExp(RFC3966_GLOBAL_NUMBER_DIGITS_, 'g')
|
|
|
|
// In this port of Google's library, we don't accept alpha characters in phone numbers.
|
|
// const ALPHANUM_ = VALID_ALPHA_ + VALID_DIGITS
|
|
const ALPHANUM_ = VALID_DIGITS
|
|
|
|
const RFC3966_DOMAINLABEL_ = '[' + ALPHANUM_ + ']+((\\-)*[' + ALPHANUM_ + '])*'
|
|
|
|
const VALID_ALPHA_ = 'a-zA-Z'
|
|
const RFC3966_TOPLABEL_ = '[' + VALID_ALPHA_ + ']+((\\-)*[' + ALPHANUM_ + '])*'
|
|
|
|
const RFC3966_DOMAINNAME_ = '^(' + RFC3966_DOMAINLABEL_ + '\\.)*' + RFC3966_TOPLABEL_ + '\\.?$'
|
|
|
|
/**
|
|
* Regular expression of valid domainname for the phone-context parameter,
|
|
* following the syntax defined in RFC3966.
|
|
*/
|
|
const RFC3966_DOMAINNAME_PATTERN_ = new RegExp(RFC3966_DOMAINNAME_, 'g')
|
|
|
|
export const RFC3966_PREFIX_ = 'tel:'
|
|
export const RFC3966_PHONE_CONTEXT_ = ';phone-context='
|
|
export const RFC3966_ISDN_SUBADDRESS_ = ';isub='
|
|
|
|
/**
|
|
* Extracts the value of the phone-context parameter of `numberToExtractFrom`,
|
|
* following the syntax defined in RFC3966.
|
|
*
|
|
* @param {string} numberToExtractFrom
|
|
* @return {string|null} the extracted string (possibly empty), or `null` if no phone-context parameter is found.
|
|
*/
|
|
export default function extractPhoneContext(numberToExtractFrom) {
|
|
const indexOfPhoneContext = numberToExtractFrom.indexOf(RFC3966_PHONE_CONTEXT_)
|
|
// If no phone-context parameter is present
|
|
if (indexOfPhoneContext < 0) {
|
|
return null
|
|
}
|
|
|
|
const phoneContextStart = indexOfPhoneContext + RFC3966_PHONE_CONTEXT_.length
|
|
// If phone-context parameter is empty
|
|
if (phoneContextStart >= numberToExtractFrom.length) {
|
|
return ''
|
|
}
|
|
|
|
const phoneContextEnd = numberToExtractFrom.indexOf(';', phoneContextStart)
|
|
// If phone-context is not the last parameter
|
|
if (phoneContextEnd >= 0) {
|
|
return numberToExtractFrom.substring(phoneContextStart, phoneContextEnd)
|
|
} else {
|
|
return numberToExtractFrom.substring(phoneContextStart)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns whether the value of phoneContext follows the syntax defined in RFC3966.
|
|
*
|
|
* @param {string|null} phoneContext
|
|
* @return {boolean}
|
|
*/
|
|
export function isPhoneContextValid(phoneContext) {
|
|
if (phoneContext === null) {
|
|
return true
|
|
}
|
|
|
|
if (phoneContext.length === 0) {
|
|
return false
|
|
}
|
|
|
|
// Does phone-context value match pattern of global-number-digits or domainname.
|
|
return RFC3966_GLOBAL_NUMBER_DIGITS_PATTERN_.test(phoneContext) ||
|
|
RFC3966_DOMAINNAME_PATTERN_.test(phoneContext)
|
|
} |