🎯 MapView v2.0 - Global Deployment Ready

 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
This commit is contained in:
2025-07-20 19:52:16 +07:00
parent 3203463a6a
commit c65cc97a33
64624 changed files with 7199453 additions and 6462 deletions

View File

@@ -0,0 +1,9 @@
export declare const TSC_NO_ERRORS_MESSAGE = "Found 0 errors. Watching for file changes.";
export declare const TSC_COMPILATION_STARTED_MESSAGE = "Starting compilation in watch mode...";
export declare const SWC_LOG_PREFIX: string;
export declare const TSC_LOG_PREFIX: string;
export declare const TSC_LOG_ERROR_PREFIX: string;
export declare const TSC_LOG_SUCCESS_PREFIX: string;
export declare const INITIALIZING_TYPE_CHECKER: string;
export declare const FOUND_NO_ISSUES_METADATA_GENERATION_SKIPPED: string;
export declare const FOUND_NO_ISSUES_GENERATING_METADATA: string;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FOUND_NO_ISSUES_GENERATING_METADATA = exports.FOUND_NO_ISSUES_METADATA_GENERATION_SKIPPED = exports.INITIALIZING_TYPE_CHECKER = exports.TSC_LOG_SUCCESS_PREFIX = exports.TSC_LOG_ERROR_PREFIX = exports.TSC_LOG_PREFIX = exports.SWC_LOG_PREFIX = exports.TSC_COMPILATION_STARTED_MESSAGE = exports.TSC_NO_ERRORS_MESSAGE = void 0;
const chalk = require("chalk");
exports.TSC_NO_ERRORS_MESSAGE = 'Found 0 errors. Watching for file changes.';
exports.TSC_COMPILATION_STARTED_MESSAGE = 'Starting compilation in watch mode...';
exports.SWC_LOG_PREFIX = chalk.cyan('> ') + chalk.bgCyan.bold(' SWC ');
exports.TSC_LOG_PREFIX = chalk.cyan('> ') + chalk.bgCyan.bold(' TSC ');
exports.TSC_LOG_ERROR_PREFIX = chalk.red('> ') + chalk.bgRed.bold(' TSC ');
exports.TSC_LOG_SUCCESS_PREFIX = chalk.green('> ') + chalk.bgGreen.bold(' TSC ');
exports.INITIALIZING_TYPE_CHECKER = chalk.bgCyan.bold(' TSC ') + chalk.cyan(' Initializing type checker...');
exports.FOUND_NO_ISSUES_METADATA_GENERATION_SKIPPED = exports.TSC_LOG_SUCCESS_PREFIX + chalk.green(' Found 0 issues.');
exports.FOUND_NO_ISSUES_GENERATING_METADATA = exports.TSC_LOG_SUCCESS_PREFIX +
chalk.green(' Found 0 issues. Generating metadata...');

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const ui_1 = require("../../ui");
const base_compiler_1 = require("../base-compiler");
const plugin_metadata_generator_1 = require("../plugins/plugin-metadata-generator");
const plugins_loader_1 = require("../plugins/plugins-loader");
const constants_1 = require("./constants");
const type_checker_host_1 = require("./type-checker-host");
const [tsConfigPath, appName, sourceRoot, plugins] = process.argv.slice(2);
class ForkedTypeChecker extends base_compiler_1.BaseCompiler {
constructor() {
super(...arguments);
this.pluginMetadataGenerator = new plugin_metadata_generator_1.PluginMetadataGenerator();
this.typeCheckerHost = new type_checker_host_1.TypeCheckerHost();
}
async run(configuration, tsConfigPath, appName, extras) {
const { readonlyVisitors } = this.loadPlugins(configuration, tsConfigPath, appName);
const outputDir = this.getPathToSource(configuration, tsConfigPath, appName);
try {
const onTypeCheckOrProgramInit = (program) => {
if (readonlyVisitors.length > 0) {
console.log(constants_1.FOUND_NO_ISSUES_GENERATING_METADATA);
this.pluginMetadataGenerator.generate({
outputDir,
visitors: readonlyVisitors,
tsProgramRef: program,
});
}
else {
console.log(constants_1.FOUND_NO_ISSUES_METADATA_GENERATION_SKIPPED);
}
};
this.typeCheckerHost.run(tsConfigPath, {
watch: extras.watch,
onTypeCheck: onTypeCheckOrProgramInit,
onProgramInit: onTypeCheckOrProgramInit,
});
}
catch (err) {
console.log(ui_1.ERROR_PREFIX, err.message);
}
}
}
const pluginsLoader = new plugins_loader_1.PluginsLoader();
const forkedTypeChecker = new ForkedTypeChecker(pluginsLoader);
const applicationName = appName === 'undefined' ? '' : appName;
const options = {
sourceRoot,
};
if (applicationName) {
options.projects = {};
options.projects[applicationName] = {
compilerOptions: {
plugins: JSON.parse(plugins),
},
};
}
else {
options.compilerOptions = {
plugins: JSON.parse(plugins),
};
}
forkedTypeChecker.run(options, tsConfigPath, applicationName, { watch: true, typeCheck: true });

View File

@@ -0,0 +1,24 @@
import * as ts from 'typescript';
import { Configuration } from '../../configuration';
import { AssetsManager } from '../assets-manager';
import { BaseCompiler } from '../base-compiler';
import { PluginsLoader } from '../plugins/plugins-loader';
export type SwcCompilerExtras = {
watch: boolean;
typeCheck: boolean;
assetsManager: AssetsManager;
tsOptions: ts.CompilerOptions;
};
export declare class SwcCompiler extends BaseCompiler {
private readonly pluginMetadataGenerator;
private readonly typeCheckerHost;
constructor(pluginsLoader: PluginsLoader);
run(configuration: Required<Configuration>, tsConfigPath: string, appName: string, extras: SwcCompilerExtras, onSuccess?: () => void): Promise<void>;
private runTypeChecker;
private runSwc;
private loadSwcCliBinary;
private getSwcRcFileContentIfExists;
private deepMerge;
private debounce;
private watchFilesInOutDir;
}

View File

@@ -0,0 +1,192 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SwcCompiler = void 0;
const chalk = require("chalk");
const child_process_1 = require("child_process");
const chokidar = require("chokidar");
const fs_1 = require("fs");
const path = require("path");
const path_1 = require("path");
const ui_1 = require("../../ui");
const tree_kill_1 = require("../../utils/tree-kill");
const base_compiler_1 = require("../base-compiler");
const swc_defaults_1 = require("../defaults/swc-defaults");
const get_value_or_default_1 = require("../helpers/get-value-or-default");
const plugin_metadata_generator_1 = require("../plugins/plugin-metadata-generator");
const constants_1 = require("./constants");
const type_checker_host_1 = require("./type-checker-host");
class SwcCompiler extends base_compiler_1.BaseCompiler {
constructor(pluginsLoader) {
super(pluginsLoader);
this.pluginMetadataGenerator = new plugin_metadata_generator_1.PluginMetadataGenerator();
this.typeCheckerHost = new type_checker_host_1.TypeCheckerHost();
}
async run(configuration, tsConfigPath, appName, extras, onSuccess) {
const swcOptions = (0, swc_defaults_1.swcDefaultsFactory)(extras.tsOptions, configuration);
const swcrcFilePath = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.builder.options.swcrcPath', appName);
if (extras.watch) {
if (extras.typeCheck) {
this.runTypeChecker(configuration, tsConfigPath, appName, extras);
}
await this.runSwc(swcOptions, extras, swcrcFilePath);
if (onSuccess) {
onSuccess();
const debounceTime = 150;
const callback = this.debounce(onSuccess, debounceTime);
this.watchFilesInOutDir(swcOptions, callback);
}
}
else {
if (extras.typeCheck) {
await this.runTypeChecker(configuration, tsConfigPath, appName, extras);
}
await this.runSwc(swcOptions, extras, swcrcFilePath);
if (onSuccess) {
onSuccess();
}
extras.assetsManager?.closeWatchers();
}
}
runTypeChecker(configuration, tsConfigPath, appName, extras) {
if (extras.watch) {
const args = [
tsConfigPath,
appName,
configuration.sourceRoot ?? 'src',
JSON.stringify(configuration.compilerOptions.plugins ?? []),
];
const childProcessRef = (0, child_process_1.fork)((0, path_1.join)(__dirname, 'forked-type-checker.js'), args, {
cwd: process.cwd(),
});
process.on('exit', () => childProcessRef && (0, tree_kill_1.treeKillSync)(childProcessRef.pid));
}
else {
const { readonlyVisitors } = this.loadPlugins(configuration, tsConfigPath, appName);
const outputDir = this.getPathToSource(configuration, tsConfigPath, appName);
let fulfilled = false;
return new Promise((resolve, reject) => {
try {
this.typeCheckerHost.run(tsConfigPath, {
watch: extras.watch,
onTypeCheck: (program) => {
if (!fulfilled) {
fulfilled = true;
resolve();
}
if (readonlyVisitors.length > 0) {
process.nextTick(() => console.log(constants_1.FOUND_NO_ISSUES_GENERATING_METADATA));
this.pluginMetadataGenerator.generate({
outputDir,
visitors: readonlyVisitors,
tsProgramRef: program,
});
}
else {
process.nextTick(() => console.log(constants_1.FOUND_NO_ISSUES_METADATA_GENERATION_SKIPPED));
}
},
});
}
catch (err) {
if (!fulfilled) {
fulfilled = true;
reject(err);
}
}
});
}
}
async runSwc(options, extras, swcrcFilePath) {
process.nextTick(() => console.log(constants_1.SWC_LOG_PREFIX, chalk.cyan('Running...')));
const swcCli = this.loadSwcCliBinary();
const swcRcFile = await this.getSwcRcFileContentIfExists(swcrcFilePath);
const swcOptions = this.deepMerge(options.swcOptions, swcRcFile);
if (swcOptions?.jsc?.baseUrl && !(0, path_1.isAbsolute)(swcOptions?.jsc?.baseUrl)) {
// jsc.baseUrl should be resolved by the caller, if it's passed as an object.
// https://github.com/swc-project/swc/pull/7827
const rootDir = process.cwd();
swcOptions.jsc.baseUrl = path.join(rootDir, swcOptions.jsc.baseUrl);
}
await swcCli.default({
...options,
swcOptions,
cliOptions: {
...options.cliOptions,
watch: extras.watch,
},
});
}
loadSwcCliBinary() {
try {
return require('@swc/cli/lib/swc/dir');
}
catch (err) {
console.error(ui_1.ERROR_PREFIX +
' Failed to load "@swc/cli" and/or "@swc/core" required packages. Please, make sure to install them as development dependencies.');
process.exit(1);
}
}
getSwcRcFileContentIfExists(swcrcFilePath) {
try {
return JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(process.cwd(), swcrcFilePath ?? '.swcrc'), 'utf8'));
}
catch (err) {
if (swcrcFilePath !== undefined) {
console.error(ui_1.ERROR_PREFIX +
` Failed to load "${swcrcFilePath}". Please, check if the file exists and is valid JSON.`);
process.exit(1);
}
return {};
}
}
deepMerge(target, source) {
if (typeof target !== 'object' ||
target === null ||
typeof source !== 'object' ||
source === null) {
return source;
}
if (Array.isArray(target) && Array.isArray(source)) {
return source.reduce((acc, value, index) => {
acc[index] = this.deepMerge(target[index], value);
return acc;
}, target);
}
const merged = { ...target };
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (key in target) {
merged[key] = this.deepMerge(target[key], source[key]);
}
else {
merged[key] = source[key];
}
}
}
return merged;
}
debounce(callback, wait) {
let timeout;
return () => {
clearTimeout(timeout);
timeout = setTimeout(callback, wait);
};
}
watchFilesInOutDir(options, onChange) {
const dir = (0, path_1.isAbsolute)(options.cliOptions.outDir)
? options.cliOptions.outDir
: (0, path_1.join)(process.cwd(), options.cliOptions.outDir);
const paths = (0, path_1.join)(dir, '**/*.js');
const watcher = chokidar.watch(paths, {
ignoreInitial: true,
awaitWriteFinish: {
stabilityThreshold: 50,
pollInterval: 10,
},
});
for (const type of ['add', 'change']) {
watcher.on(type, async () => onChange());
}
}
}
exports.SwcCompiler = SwcCompiler;

View File

@@ -0,0 +1,14 @@
import * as ts from 'typescript';
export interface TypeCheckerHostRunOptions {
watch?: boolean;
onTypeCheck?: (program: ts.Program) => void;
onProgramInit?: (program: ts.Program) => void;
}
export declare class TypeCheckerHost {
private readonly typescriptLoader;
private readonly tsConfigProvider;
run(tsconfigPath: string | undefined, options: TypeCheckerHostRunOptions): void;
private runInWatchMode;
private runOnce;
private createWatchCompilerHost;
}

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypeCheckerHost = void 0;
const chalk = require("chalk");
const ora = require("ora");
const ts = require("typescript");
const tsconfig_provider_1 = require("../helpers/tsconfig-provider");
const typescript_loader_1 = require("../typescript-loader");
const constants_1 = require("./constants");
class TypeCheckerHost {
constructor() {
this.typescriptLoader = new typescript_loader_1.TypeScriptBinaryLoader();
this.tsConfigProvider = new tsconfig_provider_1.TsConfigProvider(this.typescriptLoader);
}
run(tsconfigPath, options) {
if (!tsconfigPath) {
throw new Error('"tsconfigPath" is required when "tsProgramRef" is not provided.');
}
const tsBinary = this.typescriptLoader.load();
const spinner = ora({
text: constants_1.INITIALIZING_TYPE_CHECKER,
});
if (options.watch) {
console.log();
spinner.start();
this.runInWatchMode(tsconfigPath, tsBinary, options);
spinner.succeed();
return;
}
spinner.start();
this.runOnce(tsconfigPath, tsBinary, options);
spinner.succeed();
}
runInWatchMode(tsconfigPath, tsBinary, options) {
const { options: tsOptions } = this.tsConfigProvider.getByConfigFilename(tsconfigPath);
let builderProgram = undefined;
const reportWatchStatusCallback = (diagnostic) => {
if (diagnostic.messageText !== constants_1.TSC_NO_ERRORS_MESSAGE) {
if (diagnostic.messageText?.includes('Found')) {
console.log(constants_1.TSC_LOG_ERROR_PREFIX, chalk.red(diagnostic.messageText));
}
return;
}
if (!builderProgram) {
return;
}
const tsProgram = builderProgram.getProgram().getProgram();
options.onTypeCheck?.(tsProgram);
};
const host = this.createWatchCompilerHost(tsBinary, tsconfigPath, tsOptions, reportWatchStatusCallback);
builderProgram = tsBinary.createWatchProgram(host);
process.nextTick(() => {
options.onProgramInit?.(builderProgram.getProgram().getProgram());
});
}
runOnce(tsconfigPath, tsBinary, options) {
const { options: tsOptions, fileNames, projectReferences, } = this.tsConfigProvider.getByConfigFilename(tsconfigPath);
const createProgram = tsBinary.createIncrementalProgram ?? tsBinary.createProgram;
const program = createProgram.call(ts, {
rootNames: fileNames,
projectReferences,
options: tsOptions,
});
const programRef = program.getProgram
? program.getProgram()
: program;
const diagnostics = tsBinary.getPreEmitDiagnostics(programRef);
if (diagnostics.length > 0) {
const formatDiagnosticsHost = {
getCanonicalFileName: (path) => path,
getCurrentDirectory: tsBinary.sys.getCurrentDirectory,
getNewLine: () => tsBinary.sys.newLine,
};
console.log();
console.log(tsBinary.formatDiagnosticsWithColorAndContext(diagnostics, formatDiagnosticsHost));
process.exit(1);
}
options.onTypeCheck?.(programRef);
}
createWatchCompilerHost(tsBinary, tsConfigPath, options, reportWatchStatusCallback) {
const origDiagnosticReporter = tsBinary.createDiagnosticReporter(tsBinary.sys, true);
const tsOptions = {
...options,
preserveWatchOutput: true,
noEmit: true,
};
return tsBinary.createWatchCompilerHost(tsConfigPath, tsOptions, tsBinary.sys, undefined, origDiagnosticReporter, reportWatchStatusCallback);
}
}
exports.TypeCheckerHost = TypeCheckerHost;