gcds-components icon indicating copy to clipboard operation
gcds-components copied to clipboard

Map component draft work

Open prushforth opened this issue 1 year ago • 2 comments

initial commit of directory for gcds-map component

Dynamically render layers based on passed props

Add gcds-map-layer, update gcds-map to use it. Update index.html with example map. Need to figure out how to get a storybook together.

Update gcds-map.stories.tsx

Add dependency on @maps4html/mapml

Updates for gcds-map

Remove dep on npm @maps4html/mapml

Summary | Résumé

1-3 sentence description of the changed you're proposing, including a link to a GitHub Issue # or Trello card if applicable.


Description en 1 à 3 phrases de la modification proposée, avec un lien vers le problème (« issue ») GitHub ou la fiche Trello, le cas échéant.

Test instructions | Instructions pour tester la modification

Sequential steps (1., 2., 3., ...) that describe how to test this change. This will help a developer test things out without too much detective work. Also, include any environmental setup steps that aren't in the normal README steps and/or any time-based elements that this requires.


Étapes consécutives (1., 2., 3., …) qui décrivent la façon de tester la modification. Elles aideront les développeurs à faire des tests sans avoir à jouer au détective. Veuillez aussi inclure toutes les étapes de configuration de l’environnement qui ne font pas partie des étapes normales dans le fichier README et tout élément temporel requis.

prushforth avatar Oct 07 '24 21:10 prushforth

Hey @prushforth. Thanks for the PR to add more context to the email.

I took a look at the code this afternoon and there seems to be some other issues with the current code that are not mentioned. It appears with the current setup all the gcds packages won't build, mainly the @cdssnc/gcds-components-react-ssr package, so we will have to find an alternative for importing the needed files.

I made some modifications to the gcds-map.tsx file to try something different. Now I don't know if this is the best way forward, that is something we can discuss all together, but it will hopefully let you continue with setting up storybook. See code below:

import { Component, Element, h, Prop, Host } from '@stencil/core';
// import 'https://cdn.jsdelivr.net/npm/@maps4html/mapml/dist/mapml-viewer.js';  // Import mapml-viewer

@Component({
  tag: 'gcds-map',
  styleUrl: 'gcds-map.css',
  shadow: true,
})
export class GcdsMap {
  @Element() el: HTMLElement;

  // <mapml-viewer> attributes
  @Prop() lat: number;
  @Prop() lon: number;
  @Prop() zoom: number;
  @Prop() projection: string = 'OSMTILE'; // Default projection
  @Prop() controls: boolean = true;
  @Prop() controlslist: string;

  // Add width and height props to allow setting dimensions at design time
  @Prop() width: string = '100%'; // Allow setting width of the map
  @Prop() height: string = '400px'; // Allow setting height of the map

  componentDidLoad() {
    // Apply width and height as CSS variables
    this.el.style.setProperty('--map-width', this.width);
    this.el.style.setProperty('--map-height', this.height);

    // Handle <layer-> readiness once the map is rendered
    this.handleLayerReady();
  }

  handleLayerReady() {
    // Wait for the 'layer-' custom element to be defined
    customElements.whenDefined('layer-').then(() => {
      // Find all <layer-> elements inside the mapml-viewer
      const layers = Array.from(this.el.shadowRoot.querySelectorAll('layer-'));

      layers.forEach(layer => {
        // Now we know the <layer-> element is fully defined, call whenReady()
        (layer as any).whenReady().then(() => {
          // Check for <map-extent> in the layer's shadow DOM and add 'checked' attribute
          // this is necessary only for geogratis MapML resources, but harmless
          // otherwise (unless someone wanted to have an unchecked sublayer, for
          // some reason (it is possible, but maybe not useful).
          const mapExtent = layer.shadowRoot?.querySelector('map-extent');
          if (mapExtent && !mapExtent.hasAttribute('checked')) {
            mapExtent.setAttribute('checked', 'true');
          }
        });
      });
    });
  }

  render() {
    // Find the <gcds-map-layer> children inside the light DOM
    const layers = Array.from(this.el.querySelectorAll('gcds-map-layer'));

    return (
      <Host>
        <mapml-viewer
          lat={this.lat}
          lon={this.lon}
          zoom={this.zoom}
          projection={this.projection}
          controls={this.controls ? true : undefined}
          controlslist={this.controlslist} // Pass the controlslist to mapml-viewer
        >
          {layers.map(layer => (
            <layer-
              label={layer.getAttribute('label')}
              src={layer.getAttribute('src')}
              checked={
                layer.getAttribute('checked') === 'true' ? 'checked' : undefined
              }
              opacity={layer.getAttribute('opacity')} // Pass the opacity to the <layer-> element
            ></layer->
          ))}
        </mapml-viewer>
        <script  type="module"  src="https://cdn.jsdelivr.net/npm/@maps4html/mapml/dist/mapml-viewer.js"></script>
      </Host>
    );
  }
}

I mainly just added a Host element around the rendered code and made the js files import through a

To get storybook, it now should be just trying to match how we have it setup with our components. Matching the properties on Meta and using Canvas over Story.

Hopefully this helps!

ethanWallace avatar Oct 08 '24 19:10 ethanWallace

hi @ethanWallace and thank you I'm certain this will unblock me. I will take a closer look tomorrow!

prushforth avatar Oct 08 '24 21:10 prushforth

Closing in favour of going with #759

prushforth avatar Feb 20 '25 00:02 prushforth