Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom cursor #45

Merged
merged 1 commit into from
Nov 29, 2024
Merged

Custom cursor #45

merged 1 commit into from
Nov 29, 2024

Conversation

ciscorn
Copy link
Member

@ciscorn ciscorn commented Nov 29, 2024

<MapLibre {cursor} />

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new Cursor component for interactive cursor style changes on the map.
    • Added a new markdown file for the "Change Cursor" example, showcasing the new functionality.
    • Added an optional cursor property to the MapLibre component, allowing custom cursor styles.
  • Bug Fixes

    • Corrected spelling of "Documentaion" to "Documentation" in the README.
  • Documentation

    • Updated README for clarity, including emoji replacements for warnings.

Copy link

coderabbitai bot commented Nov 29, 2024

Walkthrough

The changes in this pull request include updates to the README.md file for the svelte-maplibre-gl project, introducing a new Svelte component Cursor that allows for interactive cursor style changes on a map. Additionally, a new markdown file for the component example is created, and the MapLibre.svelte component is modified to accept a custom cursor style. The routing logic in +page.ts is also updated to accommodate these new features and improve content loading.

Changes

File Path Change Summary
README.md Replaced "⚠️" with ":warning:" in two instances and corrected "Documentaion" to "Documentation."
src/content/examples/cursor/Cursor.svelte Added a new Svelte component for interactive cursor styles on a map using svelte-maplibre-gl.
src/content/examples/cursor/content.svelte.md Created a new markdown file for "Change Cursor" example, importing Demo and CodeBlock components.
src/lib/maplibre/map/MapLibre.svelte Introduced a new optional cursor property in the Props interface to allow custom cursor styles on the map.
src/routes/components/[slug]/+page.ts Modified imports and changed the path for loading content; added shiki highlighter for syntax highlighting support.

Possibly related PRs

  • Support [lng, lat] alongside {lng, lat} in two-way bindings #12: The changes in this PR enhance the handling of geographic coordinates in the Svelte MapLibre GL library, which may relate to the overall functionality of the MapLibre component mentioned in the main PR.
  • Add 'Limit Map Interactions' example #18: This PR adds a new example that demonstrates limiting map interactions, which could be relevant to the interactive features discussed in the main PR.
  • extension: maplibre-contour #30: The introduction of the MapLibreContourSource component in this PR relates to the MapLibre component's functionality, enhancing the mapping capabilities.
  • Add a utility component for loading images from URLs #35: The addition of the ImageLoader utility component may connect with the overall functionality of the MapLibre component, particularly in managing image resources on the map.
  • deck.gl: More reactivity #39: The changes in this PR focus on improving reactivity in the DeckGL integration, which could relate to the interactive features of the MapLibre component.
  • CustomLayer component #41: The introduction of the CustomLayer component enhances the mapping capabilities, which is relevant to the overall functionality of the MapLibre component.
  • Add PMTiles and Three.js demo #43: The addition of the PMTiles and Three.js demo may relate to the interactive and visual aspects of the MapLibre component, enhancing its capabilities.

🐰 In the meadow, I hop and play,
With cursors that dance and sway.
A map so bright, a joy to see,
New examples bloom, come hop with me!
Documentation shines, all clear and bright,
Together we code, from morning to night! 🌼


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

cloudflare-workers-and-pages bot commented Nov 29, 2024

Deploying svelte-maplibre-gl with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0b3c250
Status: ✅  Deploy successful!
Preview URL: https://9d3de007.svelte-maplibre-gl.pages.dev
Branch Preview URL: https://cursor.svelte-maplibre-gl.pages.dev

View logs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (9)
src/content/examples/cursor/content.svelte.md (3)

1-4: Consider enhancing the description with more details.

While the current description is clear, it could be more informative by including:

  • The specific cursor styles that can be changed
  • When the hover effect occurs (e.g., over specific map features)
  • Any configuration options available
 ---
 title: Change Cursor
-description: Change the cursor style on hover
+description: Customize the map cursor style when hovering over different map features. Supports standard CSS cursor values and custom cursors.
 ---

9-9: Consider using module aliases for imports.

The relative import path ../../CodeBlock.svelte could be fragile if the file structure changes. Consider using module aliases (e.g., $lib, $components) for more maintainable imports.

-import CodeBlock from "../../CodeBlock.svelte";
+import CodeBlock from "$components/CodeBlock.svelte";

13-15: Consider adding usage context before the demo.

To improve the learning experience, consider adding a brief explanation or context before the demo component. This could help users understand what to expect and how to interact with the demo.

+<p>
+  This example demonstrates how to customize the map cursor. Try hovering over different
+  parts of the map to see the cursor change.
+</p>
+
 <Demo />

 <CodeBlock content={demoRaw} {shiki} />
src/routes/components/[slug]/+page.ts (1)

9-13: Consider memoizing the highlighter initialization

The highlighter is currently initialized on every module import. Consider memoizing this initialization to improve performance, especially since the configuration is static.

-const shiki = createHighlighter({
+const shiki = browser ? await createHighlighter({
 	themes: [dark],
 	langs: [svelte],
 	engine: browser ? createOnigurumaEngine(import('shiki/wasm')) : createJavaScriptRegexEngine()
-});
+}) : null;
src/content/examples/cursor/Cursor.svelte (2)

5-26: Consider extracting constants to a separate file.

The CURSORS array and center coordinates could be useful in other components. Consider moving them to a separate constants file for better reusability and maintainability.

+// src/lib/constants/map.ts
+export const MAP_CENTER = [0, 0];
+export const CURSOR_STYLES = [
+  'cell',
+  'col-resize',
+  // ... rest of the cursors
+];

-const center = [0, 0];
-const CURSORS = [
-  'cell',
-  'col-resize',
-  // ... rest of the cursors
-];
+import { MAP_CENTER as center, CURSOR_STYLES as CURSORS } from '$lib/constants/map';

47-67: Consider making styles more configurable.

The circle styling and container height could be made more flexible:

  1. Extract circle paint properties to a constant or make them configurable via props
  2. Consider using more responsive height classes
-class="h-[55vh] min-h-[300px]"
+class="h-screen min-h-[300px] max-h-[800px]"

+const circlePaint = {
+  'circle-radius': 12,
+  'circle-color': '#007cbf',
+  'circle-stroke-color': '#fff',
+  'circle-stroke-width': 3
+} as const;

-paint={{
-  'circle-radius': 12,
-  'circle-color': '#007cbf',
-  'circle-stroke-color': '#fff',
-  'circle-stroke-width': 3
-}}
+paint={circlePaint}
🧰 Tools
🪛 eslint

[error] 58-58: 'e' is defined but never used.

(@typescript-eslint/no-unused-vars)

src/lib/maplibre/map/MapLibre.svelte (3)

21-21: Add JSDoc documentation for the cursor property

Consider adding JSDoc documentation to describe the expected cursor values and their effects.

+		/** Custom cursor style to be applied to the map canvas. Accepts standard CSS cursor values. */
		cursor?: string;

201-204: Optimize cursor initialization

The cursor initialization can be simplified and the code duplication with the reactive effect can be eliminated.

-		if (cursor) {
-			map.getCanvas().style.cursor = cursor ?? '';
-		}

The initial cursor setup can be handled by the reactive effect that follows, avoiding code duplication.


316-321: Improve cursor effect implementation

The cursor effect implementation can be enhanced for better clarity and efficiency.

 	$effect(() => {
-		cursor;
-		if (map && !firstRun) {
-			map.getCanvas().style.cursor = cursor ?? '';
-		}
+		if (!map) return;
+		map.getCanvas().style.cursor = cursor ?? '';
 	});

Changes:

  1. Removed redundant cursor tracking line as $effect automatically tracks it
  2. Simplified the condition as firstRun check isn't necessary for cursor updates
  3. Early return pattern for better readability
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between b5afda4 and 316dd46.

📒 Files selected for processing (5)
  • README.md (2 hunks)
  • src/content/examples/cursor/Cursor.svelte (1 hunks)
  • src/content/examples/cursor/content.svelte.md (1 hunks)
  • src/lib/maplibre/map/MapLibre.svelte (4 hunks)
  • src/routes/components/[slug]/+page.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • README.md
🧰 Additional context used
🪛 eslint
src/content/examples/cursor/Cursor.svelte

[error] 28-28: 'GeoJSON' is not defined.

(no-undef)


[error] 58-58: 'e' is defined but never used.

(@typescript-eslint/no-unused-vars)

🔇 Additional comments (5)
src/content/examples/cursor/content.svelte.md (1)

9-10: Verify CodeBlock component implementation.

Let's ensure the CodeBlock component exists and follows the same pattern across the codebase.

✅ Verification successful

CodeBlock component and shiki prop usage verified

The CodeBlock component exists at src/content/CodeBlock.svelte and is properly implemented with the expected shiki prop. The component is consistently imported and used across multiple example files in the codebase, with all instances following the same pattern of importing CodeBlock and destructuring the shiki prop from $props(). The implementation matches the usage in the file under review.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify CodeBlock component existence and usage pattern

# Check if CodeBlock component exists
fd CodeBlock.svelte

# Check the usage pattern of CodeBlock with shiki prop
rg -A 2 "import CodeBlock.*from" --type svelte

Length of output: 130


Script:

#!/bin/bash
# Let's verify the CodeBlock component and its usage with different approaches

# Check the content of CodeBlock component
cat src/content/CodeBlock.svelte

# Search for CodeBlock imports and usage across all files
rg "import CodeBlock" 

# Search for shiki prop usage
rg "shiki.*props" 

Length of output: 5167

src/routes/components/[slug]/+page.ts (1)

19-19: Verify the impact of changing content path from 'examples' to 'components'

This change could affect existing routes and documentation. Please ensure all references are updated accordingly.

src/content/examples/cursor/Cursor.svelte (1)

1-4: LGTM! Imports are properly organized.

The necessary components are imported from the correct locations.

src/lib/maplibre/map/MapLibre.svelte (2)

100-100: LGTM!

The cursor property is correctly destructured from props.


21-21: Verify cursor implementation completeness

Let's verify the cursor implementation across the codebase.

Also applies to: 100-100, 201-204, 316-321

✅ Verification successful

Let me try a different approach to gather the necessary information since the svelte file type wasn't recognized.


Let me check the cursor example implementation to complete the verification.


Cursor implementation is properly implemented and documented

The cursor implementation is complete and well-integrated:

  • The cursor prop is properly implemented in MapLibre.svelte with proper type definition and reactive updates
  • There's a dedicated example (src/content/examples/cursor/Cursor.svelte) demonstrating various cursor styles
  • The implementation correctly handles cursor state changes through the canvas element
  • No conflicting cursor implementations were found in the codebase
  • The cursor property is properly reset when undefined
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check cursor-related implementations and documentation

# Check for cursor usage in other components
echo "Checking cursor usage in components..."
rg -l "cursor" --type svelte

# Check for potential conflicting cursor styles
echo "Checking for potential cursor style conflicts..."
rg -l "style\.cursor|\.style\.cursor" --type svelte

# Check for cursor documentation in examples
echo "Checking cursor documentation..."
rg -l "cursor" --type md

Length of output: 484


Script:

#!/bin/bash
# Search for cursor-related code in all files
echo "Checking cursor usage in all files..."
rg -l "cursor"

# Check the content of the cursor example documentation
echo -e "\nChecking cursor example content..."
cat src/content/examples/cursor/content.svelte.md

# Search for style.cursor patterns in all files
echo -e "\nChecking cursor style patterns..."
rg "style\.cursor|\.style\.cursor"

Length of output: 1742


Script:

#!/bin/bash
# Check the cursor example implementation
echo "Checking cursor example implementation..."
cat src/content/examples/cursor/Cursor.svelte

# Check the MapLibre component for cursor-related code
echo -e "\nChecking MapLibre cursor implementation..."
rg -A 5 -B 5 "cursor" src/lib/maplibre/map/MapLibre.svelte

Length of output: 2564

Comment on lines 55 to 60
onmousemove={(e) => {
cursor = e.features![0].properties.cursor;
}}
onmouseleave={(e) => {
cursor = undefined;
}}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve type safety in event handlers.

The non-null assertion on e.features! could lead to runtime errors. Consider adding proper type checking:

-onmousemove={(e) => {
-  cursor = e.features![0].properties.cursor;
-}}
-onmouseleave={(e) => {
-  cursor = undefined;
-}}
+onmousemove={(e) => {
+  if (e.features && e.features.length > 0) {
+    cursor = e.features[0].properties.cursor;
+  }
+}}
+onmouseleave={() => {
+  cursor = undefined;
+}}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onmousemove={(e) => {
cursor = e.features![0].properties.cursor;
}}
onmouseleave={(e) => {
cursor = undefined;
}}
onmousemove={(e) => {
if (e.features && e.features.length > 0) {
cursor = e.features[0].properties.cursor;
}
}}
onmouseleave={() => {
cursor = undefined;
}}
🧰 Tools
🪛 eslint

[error] 58-58: 'e' is defined but never used.

(@typescript-eslint/no-unused-vars)

Comment on lines +28 to +43
const data: GeoJSON.FeatureCollection = {
type: 'FeatureCollection',
features: CURSORS.map((cursor, i) => ({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
center[0] + Math.cos((i / CURSORS.length) * Math.PI * 2) * 15,
center[1] + Math.sin((i / CURSORS.length) * Math.PI * 2) * 15
]
},
properties: {
cursor
}
}))
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix GeoJSON type definition.

The ESLint error about undefined GeoJSON can be resolved by either:

  1. Adding the @types/geojson package
  2. Explicitly importing GeoJSON types
+import type { Feature, FeatureCollection, Point } from 'geojson';
+
-const data: GeoJSON.FeatureCollection = {
+const data: FeatureCollection = {
   type: 'FeatureCollection',
-  features: CURSORS.map((cursor, i) => ({
+  features: CURSORS.map((cursor, i): Feature<Point> => ({
     type: 'Feature',
     geometry: {
       type: 'Point',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const data: GeoJSON.FeatureCollection = {
type: 'FeatureCollection',
features: CURSORS.map((cursor, i) => ({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
center[0] + Math.cos((i / CURSORS.length) * Math.PI * 2) * 15,
center[1] + Math.sin((i / CURSORS.length) * Math.PI * 2) * 15
]
},
properties: {
cursor
}
}))
};
import type { Feature, FeatureCollection, Point } from 'geojson';
const data: FeatureCollection = {
type: 'FeatureCollection',
features: CURSORS.map((cursor, i): Feature<Point> => ({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
center[0] + Math.cos((i / CURSORS.length) * Math.PI * 2) * 15,
center[1] + Math.sin((i / CURSORS.length) * Math.PI * 2) * 15
]
},
properties: {
cursor
}
}))
};
🧰 Tools
🪛 eslint

[error] 28-28: 'GeoJSON' is not defined.

(no-undef)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (4)
src/routes/components/[slug]/+page.ts (1)

28-29: Add type safety for the shiki highlighter

The shiki highlighter is added to the return object without type information. Consider adding proper typing to ensure type safety.

+import type { Highlighter } from 'shiki';

 return {
   Content: post.default,
   meta: { ...post.metadata, slug },
-  shiki: await shiki
+  shiki: (await shiki) as Highlighter | null
 };
src/content/examples/cursor/Cursor.svelte (2)

5-26: Consider improving configurability and modularity.

The component could be more flexible and maintainable with these changes:

  • Make center coordinates configurable via props to allow different map centers
  • Move CURSORS array to a separate constants file for reuse across components
 <script lang="ts">
 	import { MapLibre, GeoJSONSource } from 'svelte-maplibre-gl';
 	import CircleLayer from '$lib/maplibre/layers/CircleLayer.svelte';
+	export let center = [0, 0];
 
 	let cursor: string | undefined = $state();
-	const center = [0, 0];
-	const CURSORS = [
-		'cell',
-		'col-resize',
-		// ... other cursors
-	];
+	import { CURSORS } from '$lib/constants/cursors';

46-69: Enhance component configurability.

Consider making the component more configurable and maintainable:

  • Make the zoom level configurable via props
  • Extract paint properties to a separate configuration object
 <script lang="ts">
+  export let initialZoom = 2;
+  const circlePaint = {
+    'circle-radius': 12,
+    'circle-color': '#007cbf',
+    'circle-stroke-color': '#fff',
+    'circle-stroke-width': 3
+  };
 </script>

 <MapLibre
   class="h-[55vh] min-h-[300px]"
   style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
-  zoom={2}
+  zoom={initialZoom}
   {cursor}
   center={{ lng: 0, lat: 0 }}
 >
   <GeoJSONSource {data}>
     <CircleLayer
       {/* ... event handlers ... */}
-      paint={{
-        'circle-radius': 12,
-        'circle-color': '#007cbf',
-        'circle-stroke-color': '#fff',
-        'circle-stroke-width': 3
-      }}
+      paint={circlePaint}
     />
   </GeoJSONSource>
 </MapLibre>
src/lib/maplibre/map/MapLibre.svelte (1)

201-203: Optimize initial cursor setup

The current implementation has redundant null checks and duplicates logic with the reactive updates.

Consider simplifying to:

-		if (cursor) {
-			map.getCanvas().style.cursor = cursor ?? '';
-		}
+		map.getCanvas().style.cursor = cursor ?? '';
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 316dd46 and 0b3c250.

📒 Files selected for processing (5)
  • README.md (2 hunks)
  • src/content/examples/cursor/Cursor.svelte (1 hunks)
  • src/content/examples/cursor/content.svelte.md (1 hunks)
  • src/lib/maplibre/map/MapLibre.svelte (4 hunks)
  • src/routes/components/[slug]/+page.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • README.md
  • src/content/examples/cursor/content.svelte.md
🧰 Additional context used
🪛 eslint
src/content/examples/cursor/Cursor.svelte

[error] 28-28: 'GeoJSON' is not defined.

(no-undef)

🔇 Additional comments (7)
src/routes/components/[slug]/+page.ts (3)

3-7: LGTM: Imports are well-structured

The imports are properly organized, with clear separation between app-specific and third-party dependencies.


Line range hint 19-24: Verify the impact of path changes

The import path has changed from 'examples' to 'components'. This could potentially break existing documentation.

Let's verify the existence of content in both locations:


9-13: Consider adding error handling for highlighter initialization

While the conditional engine selection is good for browser compatibility, consider:

  1. Adding error handling for WASM import failures
  2. Moving the initialization into the load function to avoid potential SSR issues

Let's verify if there are any existing error handlers for WASM imports:

Consider this safer implementation:

-const shiki = createHighlighter({
-	themes: [dark],
-	langs: [svelte],
-	engine: browser ? createOnigurumaEngine(import('shiki/wasm')) : createJavaScriptRegexEngine()
-});

+async function createSafeHighlighter() {
+  try {
+    return await createHighlighter({
+      themes: [dark],
+      langs: [svelte],
+      engine: browser ? createOnigurumaEngine(import('shiki/wasm')) : createJavaScriptRegexEngine()
+    });
+  } catch (error) {
+    console.error('Failed to initialize syntax highlighter:', error);
+    return null;
+  }
+}
src/content/examples/cursor/Cursor.svelte (2)

28-43: ⚠️ Potential issue

Fix GeoJSON type definition.

The GeoJSON type is still undefined. This needs to be fixed for proper type safety.

+import type { Feature, FeatureCollection, Point } from 'geojson';
+
-const data: GeoJSON.FeatureCollection = {
+const data: FeatureCollection = {
   type: 'FeatureCollection',
-  features: CURSORS.map((cursor, i) => ({
+  features: CURSORS.map((cursor, i): Feature<Point> => ({
     type: 'Feature',
     geometry: {
       type: 'Point',
🧰 Tools
🪛 eslint

[error] 28-28: 'GeoJSON' is not defined.

(no-undef)


55-60: ⚠️ Potential issue

Improve type safety in event handlers.

The non-null assertion on e.features! should be replaced with proper type checking.

-onmousemove={(e) => {
-  cursor = e.features![0].properties.cursor;
-}}
-onmouseleave={() => {
-  cursor = undefined;
-}}
+onmousemove={(e) => {
+  if (e.features && e.features.length > 0) {
+    cursor = e.features[0].properties.cursor;
+  }
+}}
+onmouseleave={() => {
+  cursor = undefined;
+}}
src/lib/maplibre/map/MapLibre.svelte (2)

21-21: LGTM: Props interface change

The cursor property is correctly defined as an optional string type, following MapLibre GL JS API patterns.


316-321: Verify cursor cleanup and usage patterns

While the implementation looks functional, let's verify a few aspects:

✅ Verification successful

Cursor implementation is properly scoped and handled

The cursor implementation is well-contained within the MapLibre component with no conflicting usage across the codebase:

  • The cursor style manipulation is only present in MapLibre.svelte
  • The cursor prop is properly typed and exported
  • The effect correctly updates the cursor style when the cursor prop changes
  • No cleanup is needed as Svelte's reactivity will handle the component destruction automatically, and the cursor style will be cleaned up with the canvas element
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check cursor-related patterns in the codebase

# Check for other cursor style manipulations that might conflict
rg -l "style\.cursor" --type svelte

# Check for cursor-related cleanup in destroy/cleanup blocks
rg -l "cursor.*destroy|destroy.*cursor" --type svelte

# Check for example usage patterns
rg -l "<MapLibre.*cursor.*>" --type svelte

Length of output: 231


Script:

#!/bin/bash
# Description: Check cursor-related patterns in the codebase without file type filtering

# Check for other cursor style manipulations that might conflict
rg -l "style\.cursor"

# Check for cursor-related cleanup in destroy/cleanup blocks
rg -l "cursor.*destroy|destroy.*cursor"

# Check for example usage patterns
rg -l "<MapLibre.*cursor"

# Check for cursor prop usage in MapLibre component
rg -l "export let cursor" src/lib/maplibre/map/MapLibre.svelte

# Look for other cursor-related code in MapLibre component
rg "cursor" src/lib/maplibre/map/MapLibre.svelte

Length of output: 395

Comment on lines +316 to +321
$effect(() => {
cursor;
if (map && !firstRun) {
map.getCanvas().style.cursor = cursor ?? '';
}
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Optimize reactive cursor updates

The current implementation can be improved for better maintainability and efficiency.

Consider combining initial setup and reactive updates into a single effect:

-	$effect(() => {
-		cursor;
-		if (map && !firstRun) {
-			map.getCanvas().style.cursor = cursor ?? '';
-		}
-	});
+	$effect(() => {
+		if (map) {
+			map.getCanvas().style.cursor = cursor ?? '';
+		}
+	});

This change:

  1. Removes unnecessary cursor dependency tracking
  2. Eliminates the need for firstRun check since the cursor should be set whenever it changes
  3. Combines initial setup and reactive updates into a single location
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$effect(() => {
cursor;
if (map && !firstRun) {
map.getCanvas().style.cursor = cursor ?? '';
}
});
$effect(() => {
if (map) {
map.getCanvas().style.cursor = cursor ?? '';
}
});

@ciscorn ciscorn merged commit 4ea5671 into main Nov 29, 2024
5 checks passed
@ciscorn ciscorn deleted the cursor branch November 29, 2024 11:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant