fix: maplibre reactive signal bugs and stale signal re-push (#3)
Some checks failed
CI / Build and Test (push) Failing after 36s
Some checks failed
CI / Build and Test (push) Failing after 36s
This commit was merged in pull request #3.
This commit is contained in:
52
internal/examples/effectspike/main.go
Normal file
52
internal/examples/effectspike/main.go
Normal file
@@ -0,0 +1,52 @@
|
||||
// Spike to validate that Datastar's data-effect re-evaluates when signals are
|
||||
// updated via PatchSignals from the server, and that Via's hex signal IDs work
|
||||
// in $signalID expression syntax.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/ryanhamamura/via"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v := via.New()
|
||||
v.Config(via.Options{
|
||||
DocumentTitle: "data-effect Spike",
|
||||
ServerAddress: ":7332",
|
||||
DevMode: true,
|
||||
})
|
||||
|
||||
v.Page("/", func(c *via.Context) {
|
||||
x := c.Signal(0)
|
||||
y := c.Signal(0)
|
||||
|
||||
c.OnInterval(time.Second, func() {
|
||||
x.SetValue(rand.Intn(500))
|
||||
y.SetValue(rand.Intn(500))
|
||||
c.SyncSignals()
|
||||
})
|
||||
|
||||
c.View(func() h.H {
|
||||
return h.Div(
|
||||
h.Attr("style", "padding:1rem;font-family:sans-serif"),
|
||||
h.H1(h.Text("data-effect Spike")),
|
||||
h.P(h.Text("x: "), x.Text(), h.Text(" y: "), y.Text()),
|
||||
h.Div(
|
||||
h.ID("box"),
|
||||
h.Attr("style", "width:20px;height:20px;background:red;position:absolute"),
|
||||
h.DataEffect(fmt.Sprintf(
|
||||
"document.getElementById('box').style.left=$%s+'px';"+
|
||||
"document.getElementById('box').style.top=$%s+'px'",
|
||||
x.ID(), y.ID(),
|
||||
)),
|
||||
),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
v.Start()
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/ryanhamamura/via"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
@@ -25,7 +26,10 @@ func main() {
|
||||
Height: "500px",
|
||||
})
|
||||
|
||||
// Markers with popups
|
||||
m.AddControl("nav", maplibre.NavigationControl{})
|
||||
m.AddControl("scale", maplibre.ScaleControl{Unit: "metric"})
|
||||
|
||||
// Static markers with popups
|
||||
m.AddMarker("sf", maplibre.Marker{
|
||||
LngLat: maplibre.LngLat{Lng: -122.4194, Lat: 37.7749},
|
||||
Color: "#e74c3c",
|
||||
@@ -41,6 +45,43 @@ func main() {
|
||||
},
|
||||
})
|
||||
|
||||
// Signal-backed marker — server pushes position updates
|
||||
vehicleLng := c.Signal(-122.43)
|
||||
vehicleLat := c.Signal(37.77)
|
||||
|
||||
m.AddMarker("vehicle", maplibre.Marker{
|
||||
LngSignal: vehicleLng,
|
||||
LatSignal: vehicleLat,
|
||||
Color: "#9b59b6",
|
||||
})
|
||||
|
||||
c.OnInterval(time.Second, func() {
|
||||
vehicleLng.SetValue(-122.43 + (rand.Float64()-0.5)*0.02)
|
||||
vehicleLat.SetValue(37.77 + (rand.Float64()-0.5)*0.02)
|
||||
c.SyncSignals()
|
||||
})
|
||||
|
||||
// Draggable marker — user drags, signals update
|
||||
pinLng := c.Signal(-122.41)
|
||||
pinLat := c.Signal(37.78)
|
||||
|
||||
m.AddMarker("pin", maplibre.Marker{
|
||||
LngSignal: pinLng,
|
||||
LatSignal: pinLat,
|
||||
Color: "#3498db",
|
||||
Draggable: true,
|
||||
})
|
||||
|
||||
// Click event — click to place a marker
|
||||
click := m.OnClick()
|
||||
handleClick := c.Action(func() {
|
||||
e := click.Data()
|
||||
m.AddMarker("clicked", maplibre.Marker{
|
||||
LngLat: e.LngLat,
|
||||
Color: "#f39c12",
|
||||
})
|
||||
})
|
||||
|
||||
// GeoJSON polygon source + fill layer
|
||||
m.AddSource("park", maplibre.GeoJSONSource{
|
||||
Data: map[string]any{
|
||||
@@ -70,24 +111,20 @@ func main() {
|
||||
},
|
||||
})
|
||||
|
||||
// Viewport info signal (updated on action)
|
||||
viewportInfo := c.Signal("")
|
||||
|
||||
// FlyTo action
|
||||
// FlyTo actions using CameraOptions
|
||||
zoom14 := 14.0
|
||||
flyToSF := c.Action(func() {
|
||||
m.FlyTo(maplibre.LngLat{Lng: -122.4194, Lat: 37.7749}, 14)
|
||||
m.FlyTo(maplibre.CameraOptions{
|
||||
Center: &maplibre.LngLat{Lng: -122.4194, Lat: 37.7749},
|
||||
Zoom: &zoom14,
|
||||
})
|
||||
})
|
||||
|
||||
flyToOak := c.Action(func() {
|
||||
m.FlyTo(maplibre.LngLat{Lng: -122.2711, Lat: 37.8044}, 14)
|
||||
})
|
||||
|
||||
// Read viewport action
|
||||
readViewport := c.Action(func() {
|
||||
center := m.Center()
|
||||
zoom := m.Zoom()
|
||||
viewportInfo.SetValue(fmt.Sprintf("Center: %.4f, %.4f | Zoom: %.1f", center.Lng, center.Lat, zoom))
|
||||
c.Sync()
|
||||
m.FlyTo(maplibre.CameraOptions{
|
||||
Center: &maplibre.LngLat{Lng: -122.2711, Lat: 37.8044},
|
||||
Zoom: &zoom14,
|
||||
})
|
||||
})
|
||||
|
||||
c.View(func() h.H {
|
||||
@@ -95,13 +132,19 @@ func main() {
|
||||
h.Div(
|
||||
h.Attr("style", "max-width:960px;margin:0 auto;padding:1rem;font-family:sans-serif"),
|
||||
h.H1(h.Text("MapLibre GL Example")),
|
||||
m.Element(),
|
||||
h.Div(h.Attr("style", "margin-top:1rem;display:flex;gap:0.5rem"),
|
||||
m.Element(
|
||||
click.Input(handleClick.OnInput()),
|
||||
),
|
||||
h.Div(h.Attr("style", "margin-top:1rem;display:flex;gap:0.5rem;flex-wrap:wrap"),
|
||||
h.Button(h.Text("Fly to San Francisco"), flyToSF.OnClick()),
|
||||
h.Button(h.Text("Fly to Oakland"), flyToOak.OnClick()),
|
||||
h.Button(h.Text("Read Viewport"), readViewport.OnClick()),
|
||||
),
|
||||
h.P(viewportInfo.Text()),
|
||||
h.Div(h.Attr("style", "margin-top:0.5rem;font-size:0.9rem"),
|
||||
h.P(h.Text("Zoom: "), m.Zoom.Text()),
|
||||
h.P(h.Text("Center: "), m.CenterLng.Text(), h.Text(", "), m.CenterLat.Text()),
|
||||
h.P(h.Text("Vehicle: "), vehicleLng.Text(), h.Text(", "), vehicleLat.Text()),
|
||||
h.P(h.Text("Draggable Pin: "), pinLng.Text(), h.Text(", "), pinLat.Text()),
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user