From 8627b1d574849aac3e6f060d21454a540f094307 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 24 Jun 2025 01:12:34 +0100 Subject: [PATCH] feat(editor): add geolocation support for content editing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add geolocation Tiptap extension for embedding maps - Create GeolocationExtended component for rendering map embeds - Create GeolocationPlaceholder for editor insertion - Add GeoCard component for displaying location data - Support latitude, longitude, zoom level, and optional labels - Enable location-based content in albums and posts Allows editors to embed interactive maps with specific locations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/lib/components/GeoCard.svelte | 273 +++++++++++ .../geolocation/GeolocationExtended.ts | 80 ++++ .../geolocation/GeolocationPlaceholder.ts | 55 +++ .../geolocation/geolocation-extended.svelte | 352 +++++++++++++++ .../geolocation-placeholder.svelte | 425 ++++++++++++++++++ .../extensions/geolocation/geolocation.ts | 122 +++++ .../components/GeolocationExtended.svelte | 112 +++++ .../components/GeolocationPlaceholder.svelte | 255 +++++++++++ 8 files changed, 1674 insertions(+) create mode 100644 src/lib/components/GeoCard.svelte create mode 100644 src/lib/components/edra/extensions/geolocation/GeolocationExtended.ts create mode 100644 src/lib/components/edra/extensions/geolocation/GeolocationPlaceholder.ts create mode 100644 src/lib/components/edra/extensions/geolocation/geolocation-extended.svelte create mode 100644 src/lib/components/edra/extensions/geolocation/geolocation-placeholder.svelte create mode 100644 src/lib/components/edra/extensions/geolocation/geolocation.ts create mode 100644 src/lib/components/edra/headless/components/GeolocationExtended.svelte create mode 100644 src/lib/components/edra/headless/components/GeolocationPlaceholder.svelte diff --git a/src/lib/components/GeoCard.svelte b/src/lib/components/GeoCard.svelte new file mode 100644 index 0000000..a054372 --- /dev/null +++ b/src/lib/components/GeoCard.svelte @@ -0,0 +1,273 @@ + + +
+ +
+ + diff --git a/src/lib/components/edra/extensions/geolocation/GeolocationExtended.ts b/src/lib/components/edra/extensions/geolocation/GeolocationExtended.ts new file mode 100644 index 0000000..d897d4c --- /dev/null +++ b/src/lib/components/edra/extensions/geolocation/GeolocationExtended.ts @@ -0,0 +1,80 @@ +import { Node, mergeAttributes, type NodeViewProps } from '@tiptap/core' +import type { Component } from 'svelte' +import { SvelteNodeViewRenderer } from 'svelte-tiptap' + +export interface GeolocationExtendedOptions { + HTMLAttributes: Record +} + +export const GeolocationExtended = ( + component: Component +): Node => + Node.create({ + name: 'geolocation', + addOptions() { + return { + HTMLAttributes: {} + } + }, + group: 'block', + atom: true, + draggable: true, + addAttributes() { + return { + latitude: { + default: null, + parseHTML: (element) => parseFloat(element.getAttribute('data-latitude') || '0'), + renderHTML: (attributes) => ({ + 'data-latitude': attributes.latitude + }) + }, + longitude: { + default: null, + parseHTML: (element) => parseFloat(element.getAttribute('data-longitude') || '0'), + renderHTML: (attributes) => ({ + 'data-longitude': attributes.longitude + }) + }, + title: { + default: null, + parseHTML: (element) => element.getAttribute('data-title'), + renderHTML: (attributes) => ({ + 'data-title': attributes.title + }) + }, + description: { + default: null, + parseHTML: (element) => element.getAttribute('data-description'), + renderHTML: (attributes) => ({ + 'data-description': attributes.description + }) + }, + markerColor: { + default: '#ef4444', + parseHTML: (element) => element.getAttribute('data-marker-color') || '#ef4444', + renderHTML: (attributes) => ({ + 'data-marker-color': attributes.markerColor + }) + }, + zoom: { + default: 15, + parseHTML: (element) => parseInt(element.getAttribute('data-zoom') || '15'), + renderHTML: (attributes) => ({ + 'data-zoom': attributes.zoom + }) + } + } + }, + parseHTML() { + return [{ tag: `div[data-type="${this.name}"]` }] + }, + renderHTML({ HTMLAttributes }) { + return [ + 'div', + mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { 'data-type': this.name }) + ] + }, + addNodeView() { + return SvelteNodeViewRenderer(component) + } + }) diff --git a/src/lib/components/edra/extensions/geolocation/GeolocationPlaceholder.ts b/src/lib/components/edra/extensions/geolocation/GeolocationPlaceholder.ts new file mode 100644 index 0000000..6f967a2 --- /dev/null +++ b/src/lib/components/edra/extensions/geolocation/GeolocationPlaceholder.ts @@ -0,0 +1,55 @@ +import { Editor, Node, mergeAttributes, type CommandProps, type NodeViewProps } from '@tiptap/core' +import type { Component } from 'svelte' +import { SvelteNodeViewRenderer } from 'svelte-tiptap' + +export interface GeolocationPlaceholderOptions { + HTMLAttributes: Record +} + +declare module '@tiptap/core' { + interface Commands { + geolocationPlaceholder: { + /** + * Inserts a geolocation placeholder + */ + insertGeolocationPlaceholder: () => ReturnType + } + } +} + +export const GeolocationPlaceholder = ( + component: Component +): Node => + Node.create({ + name: 'geolocation-placeholder', + addOptions() { + return { + HTMLAttributes: {} + } + }, + parseHTML() { + return [{ tag: `div[data-type="${this.name}"]` }] + }, + + renderHTML({ HTMLAttributes }) { + return ['div', mergeAttributes(HTMLAttributes)] + }, + group: 'block', + draggable: true, + atom: true, + content: 'inline*', + isolating: true, + + addNodeView() { + return SvelteNodeViewRenderer(component) + }, + addCommands() { + return { + insertGeolocationPlaceholder: () => (props: CommandProps) => { + return props.commands.insertContent({ + type: 'geolocation-placeholder' + }) + } + } + } + }) diff --git a/src/lib/components/edra/extensions/geolocation/geolocation-extended.svelte b/src/lib/components/edra/extensions/geolocation/geolocation-extended.svelte new file mode 100644 index 0000000..0cdb4b9 --- /dev/null +++ b/src/lib/components/edra/extensions/geolocation/geolocation-extended.svelte @@ -0,0 +1,352 @@ + + +
+
+
+ 📍 + {#if title} + {title} + {:else} + {latitude?.toFixed(4)}, {longitude?.toFixed(4)} + {/if} +
+
+ +
+
+ + +
+ + diff --git a/src/lib/components/edra/extensions/geolocation/geolocation-placeholder.svelte b/src/lib/components/edra/extensions/geolocation/geolocation-placeholder.svelte new file mode 100644 index 0000000..7299678 --- /dev/null +++ b/src/lib/components/edra/extensions/geolocation/geolocation-placeholder.svelte @@ -0,0 +1,425 @@ + + +
+ {#if !showForm} +
+
📍
+

Add a location

+
+ +
+ + + +
+
+
+ {:else} +
+

Add Location

+ +
+ + + +
+ +
+ + +
+ +
+ + +
+
+ {/if} +
+ + +