@phila/layerboard 3.0.0-beta.18 → 3.0.0-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,79 +1,213 @@
1
- # vue3-layerboard
1
+ # @phila/layerboard
2
2
 
3
- A Vue 3 + MapLibre GL JS framework for building interactive map applications with layer management, measurement tools, and ArcGIS integration.
3
+ A Vue 3 component framework for building interactive map applications powered by ArcGIS Online WebMaps and MapLibre GL JS. Provide a WebMap ID and get a full mapping app with layer management, popups, legends, search, and more.
4
4
 
5
- ## Features
5
+ ## Live Examples
6
6
 
7
- - **MapLibre GL JS Integration** - Modern, performant vector tile mapping
8
- - **Layer Management** - Dynamic layer loading from ArcGIS Online web maps
9
- - **Measurement Tools** - Interactive area and distance measurement
10
- - **Geolocation** - User location tracking and display
11
- - **Legend & Layer Controls** - Configurable layer visibility and legends
12
- - **Popup System** - Feature identification and attribute display
7
+ - [OpenMaps](https://openmaps.phila.gov) flat layer list (all layers searchable)
8
+ - [StreetSmartPHL](https://streetsmartphl.phila.gov) topic-based layout (layers grouped in accordions)
13
9
 
14
10
  ## Installation
15
11
 
16
12
  ```sh
17
- npm install @phila/layerboard
13
+ pnpm add @phila/layerboard
18
14
  ```
19
15
 
20
- ## Peer Dependencies
16
+ ### Peer Dependencies
21
17
 
22
- This package requires the following peer dependencies:
23
-
24
- - `vue` ^3.5.0
25
- - `pinia` ^3.0.0
26
- - `maplibre-gl` ^5.0.0
27
- - `@fortawesome/fontawesome-svg-core` ^7.0.0
28
- - `@fortawesome/free-solid-svg-icons` ^7.0.0
29
- - `@fortawesome/vue-fontawesome` ^3.0.0
18
+ ```sh
19
+ pnpm add vue pinia maplibre-gl @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/vue-fontawesome
20
+ ```
30
21
 
31
- ## Design Decisions
22
+ ## Quick Start
32
23
 
33
- ### Compact Text Field Styling
24
+ ```vue
25
+ <template>
26
+ <Layerboard
27
+ title="My Map App"
28
+ web-map-id="1596df70df0349e293ceec46a06ccc50"
29
+ />
30
+ </template>
34
31
 
35
- The phila-ui TextField component has a standard height of 56px, designed for form inputs where touch targets and readability are priorities. In the layerboard context (sidebar filter and map search control), we intentionally use a more compact ~40px version to save vertical space.
32
+ <script setup>
33
+ import { Layerboard } from "@phila/layerboard";
34
+ import "@phila/layerboard/dist/layerboard.css";
35
+ </script>
36
+ ```
36
37
 
37
- This is achieved through CSS overrides in:
38
+ This renders a full-screen map app with a sidebar listing all layers from the WebMap, complete with legends, opacity sliders, search, popups, and mobile responsiveness.
38
39
 
39
- - **LayerPanel.vue** - for the layer filter search box
40
- - **MapPanel.vue** - for the MapSearchControl on the map
40
+ ## Layout Modes
41
41
 
42
- The overrides remove padding from `.state-layer` and `.content` elements. See the detailed comments in those files for the technical breakdown.
42
+ ### Flat Mode (default)
43
43
 
44
- ## Development
44
+ All layers in a searchable list. Set `show-default-sidebar` to `true` (default) and the built-in `LayerPanel` renders in the sidebar.
45
45
 
46
- ### Recommended IDE Setup
46
+ ### Topics Mode
47
47
 
48
- [VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
48
+ Group layers into collapsible accordions using the sidebar slot:
49
49
 
50
- ### Recommended Browser Setup
50
+ ```vue
51
+ <Layerboard
52
+ title="StreetSmartPHL"
53
+ :web-map-id="webMapId"
54
+ :show-default-sidebar="false"
55
+ >
56
+ <template #sidebar="{ layers, visibleLayers, toggleLayer, setOpacity }">
57
+ <TopicAccordion title="Paving" :expanded="true">
58
+ <LayerCheckboxSet
59
+ :layers="pavingLayers"
60
+ :visible-layer-ids="visibleLayers"
61
+ @toggle-layer="toggleLayer"
62
+ @set-opacity="setOpacity"
63
+ />
64
+ </TopicAccordion>
65
+ </template>
66
+ </Layerboard>
67
+ ```
51
68
 
52
- - Chromium-based browsers (Chrome, Edge, Brave, etc.):
53
- - [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
54
- - [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters)
55
- - Firefox:
56
- - [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/)
57
- - [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/)
69
+ ## Props
70
+
71
+ | Prop | Type | Default | Description |
72
+ |------|------|---------|-------------|
73
+ | `title` | `string` | *required* | App title in header |
74
+ | `webMapId` | `string` | *required* | ArcGIS Online WebMap ID |
75
+ | `subtitle` | `string` | — | Subtitle in header |
76
+ | `themeColor` | `string` | `"#0f4d90"` | Header/footer background color |
77
+ | `showDefaultSidebar` | `boolean` | `true` | Show built-in LayerPanel (false for custom sidebar) |
78
+ | `sidebarWidth` | `string` | `"30%"` | Sidebar width (CSS units) |
79
+ | `sidebarLabel` | `string` | `"Layers"` | Mobile toggle label for sidebar view |
80
+ | `mapLabel` | `string` | `"Map"` | Mobile toggle label for map view |
81
+ | `fetchMetadata` | `boolean` | `false` | Fetch layer metadata from Carto |
82
+ | `tiledLayers` | `TiledLayerConfig[]` | `[]` | ESRI MapServer tiled layers |
83
+ | `dataSources` | `DataSourceConfig[]` | `[]` | External API data sources |
84
+ | `layerStyleOverrides` | `Record<string, LayerStyleOverride>` | `{}` | Override paint/legend per layer |
85
+ | `popupOverrides` | `Record<string, PopupOverride>` | `{}` | Override popup behavior per layer |
86
+ | `initialZoom` | `number` | — | Initial map zoom level |
87
+ | `initialCenter` | `[number, number]` | — | Initial map center `[lng, lat]` |
88
+ | `cyclomediaConfig` | `CyclomediaConfig` | — | Cyclomedia street-level imagery config |
89
+ | `pictometryCredentials` | `PictometryCredentials` | — | Pictometry oblique imagery credentials |
90
+
91
+ ### Control Positions
92
+
93
+ All default to sensible positions. Each accepts `"top-left" | "top-right" | "bottom-left" | "bottom-right"`.
94
+
95
+ | Prop | Default |
96
+ |------|---------|
97
+ | `basemapControlPosition` | `"top-right"` |
98
+ | `navigationControlPosition` | `"bottom-right"` |
99
+ | `geolocationControlPosition` | `"bottom-right"` |
100
+ | `searchControlPosition` | `"top-left"` |
101
+ | `drawControlPosition` | `"bottom-left"` (or `null` to remove) |
102
+ | `cyclomediaButtonPosition` | `"top-right"` |
103
+ | `pictometryButtonPosition` | `"top-right"` |
104
+
105
+ ## Events
106
+
107
+ | Event | Payload | Description |
108
+ |-------|---------|-------------|
109
+ | `configs-loaded` | `LayerConfig[]` | Layer configs loaded from WebMap |
110
+ | `load-error` | `string` | Error message on load failure |
111
+ | `zoom` | `number` | Zoom level changed |
112
+
113
+ ## Slots
114
+
115
+ | Slot | Scope | Description |
116
+ |------|-------|-------------|
117
+ | `header` | — | Replace default header |
118
+ | `sidebar` | layer state + methods (see below) | Replace default LayerPanel |
119
+ | `footer` | `{ openModal, closeModal, isModalOpen }` | Custom footer content |
120
+ | `modal` | `{ closeModal }` | Modal content |
121
+
122
+ ### Sidebar Slot Scope
123
+
124
+ The sidebar slot exposes the full layer state for building custom UIs:
125
+
126
+ ```typescript
127
+ {
128
+ layers: Array<{ config: LayerConfig; component: string }>
129
+ visibleLayers: Set<string>
130
+ layerOpacities: Record<string, number>
131
+ loadingLayers: Set<string>
132
+ layerErrors: Record<string, string>
133
+ currentZoom: number
134
+ toggleLayer: (id: string) => void
135
+ setLayerVisible: (id: string, visible: boolean) => void
136
+ setLayersVisible: (ids: string[], visible: boolean) => void
137
+ setOpacity: (id: string, opacity: number) => void
138
+ // Tiled layers
139
+ tiledLayers: TiledLayerConfig[]
140
+ visibleTiledLayers: Set<string>
141
+ tiledLayerOpacities: Record<string, number>
142
+ toggleTiledLayer: (id: string) => void
143
+ setTiledLayerVisible: (id: string, visible: boolean) => void
144
+ setTiledLayerOpacity: (id: string, opacity: number) => void
145
+ // Data sources
146
+ dataSourcesState: Record<string, DataSourceState>
147
+ dataSourcesLoading: boolean
148
+ getDataSource: (id: string) => unknown | null
149
+ refetchDataSource: (id: string) => Promise<void>
150
+ }
151
+ ```
58
152
 
59
- ### Type Support for `.vue` Imports in TS
153
+ ## Components
60
154
 
61
- TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
155
+ All components are exported for building custom layouts:
62
156
 
63
- ### Project Setup
157
+ ```typescript
158
+ import {
159
+ Layerboard, // Main framework component
160
+ LayerPanel, // Flat layer list with search/legends/opacity
161
+ MapPanel, // MapLibre map with layer rendering
162
+ TopicAccordion, // Collapsible accordion for topic grouping
163
+ LayerCheckboxSet, // Checkbox controls for layer toggling
164
+ LayerRadioButtonSet, // Radio buttons for mutually exclusive layers
165
+ } from "@phila/layerboard";
166
+ ```
64
167
 
65
- ```sh
66
- npm install
168
+ ## Types
169
+
170
+ All types are exported:
171
+
172
+ ```typescript
173
+ import type {
174
+ LayerConfig,
175
+ LayerDisplayOptions,
176
+ LayerStyleOverride,
177
+ LegendItem,
178
+ PopupConfig,
179
+ PopupField,
180
+ PopupOverride,
181
+ TiledLayerConfig,
182
+ DataSourceConfig,
183
+ DataSourceState,
184
+ LayerboardConfig,
185
+ TopicConfig,
186
+ FeatureFlags,
187
+ CyclomediaConfig, // re-exported from @phila/phila-ui-map-core
188
+ PictometryCredentials, // re-exported from @phila/phila-ui-map-core
189
+ } from "@phila/layerboard";
67
190
  ```
68
191
 
69
- ### Compile and Hot-Reload for Development
192
+ ## How It Works
193
+
194
+ 1. You provide an ArcGIS Online **WebMap ID**
195
+ 2. Layerboard fetches the WebMap JSON at runtime
196
+ 3. Esri renderers, symbols, scales, and popup configs are transformed into MapLibre-compatible layer configs
197
+ 4. Layers render on a MapLibre GL map — feature data is fetched from ArcGIS FeatureServer endpoints with spatial filtering and pagination
198
+ 5. Server-side geometry simplification (`maxAllowableOffset`) scales with zoom level for polygon layers
199
+
200
+ ## Development
70
201
 
71
202
  ```sh
72
- npm run dev
203
+ pnpm install
204
+ pnpm build # type-check + vite build
73
205
  ```
74
206
 
75
- ### Type-Check, Compile and Minify for Production
207
+ ### Publishing
76
208
 
77
209
  ```sh
78
- npm run build
210
+ pnpm version prerelease # bump beta version
211
+ git push origin main
212
+ git tag v<version> && git push origin v<version> # triggers publish workflow
79
213
  ```