@grit-npm/grit-utils
v0.3.8
Published
Collection of handy utils for use in JavaScript and OpenLayers projects.
Downloads
20
Readme
grit-utils
A collection of handy utility functions for JavaScript and OpenLayers projects.
Features
- Geometry helpers for working with OpenLayers layers and features
- Styling utilities to generate custom polygon styles
- Marker placement functions for additional polygon highlighting
- General utilities like a modern, Vuex-compatible
debouncefunction - Fully ESM-based build with optimized Rollup output
- Tree-shakable — only import what you need
Installation
npm install grit-utils
# or
yarn add grit-utils
# or
pnpm add grit-utilsUsage
Example: Add a feature to a layer
import { addFeatureToLayer } from "@grit-npm/grit-utils";
// Assuming you have a Vector layer with a source:
addFeatureToLayer(myVectorLayer, myFeature);Example: Generate a polygon style
import { generatePolygonStyle } from "@grit-npm/grit-utils";
const customStyle = generatePolygonStyle({
stroke: { color: 'red', width: 2, lineDash: [4, 4] },
fill: { color: 'rgba(255,0,0,0.5)' }
})Example: Placing additional Polygon Marker
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Feature from "ol/Feature";
import { Polygon } from "ol/geom";
import { placingAdditionalPolygonMarker } from "@grit-npm/grit-utils";
import mapMarker from "./mapMarker";
import store from "./store";
const vectorLayer = new VectorLayer({ source: new VectorSource() })
map.addLayer(vectorLayer)
const squareFeature = new Feature(new Polygon([[
[0, 0],
[100, 0],
[100, 100],
[0, 100],
[0, 0]
]]))
placingAdditionalPolygonMarker(
vectorLayer,
mapMarker,
store,
"HighlightFkz",
[squareFeature],
defaultStyleObject,
true
)Example: Placing additional Polygon Marker by Geometry
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import { Polygon } from "ol/geom";
import { placingAdditionalPolygonMarkerByGeom } from "@grit-npm/grit-utils";
import mapMarker from "./mapMarker";
import store from "./store";
const vectorLayer = new VectorLayer({ source: new VectorSource() })
map.addLayer(vectorLayer)
const square = new Polygon([[
[0, 0],
[100, 0],
[100, 100],
[0, 100],
[0, 0]
]])
placingAdditionalPolygonMarkerByGeom(
vectorLayer,
mapMarker,
store,
"HighlightFkz",
square,
defaultStyleObject,
false, // not clicked
true // use additional style
)Example: Remove Feature from Layer
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Feature from "ol/Feature";
import { Polygon } from "ol/geom";
import { removeFeatureFromLayer } from "@grit-npm/grit-utils";
// 1. Create a vector layer and add it to your map
const layer = new VectorLayer({
source: new VectorSource(),
});
map.addLayer(layer)
// 2. Create a simple polygon feature
const square = new Polygon([[
[0, 0],
[10, 0],
[10, 10],
[0, 10],
[0, 0]
]])
const feature = new Feature(square);
// 3. Add the feature to the layer
layer.getSource().addFeature(feature);
// 4. Remove the feature from the layer
removeFeatureFromLayer(layer, feature);Example: Change active module in menu
import { changeModule } from "@grit-npm/grit-utils";
import store from "./store";
await changeModule(store, "measure", "mainMenu");Example: Debounce any function (supports Vuex dispatch)
import { debounce } from "@grit-npm/grit-utils";
// Normal function debounce
const debouncedResize = debounce(onResize);
window.addEventListener("resize", debouncedResize);
// Vuex dispatch debounce
await debounce.dispatch(
store,
"Modules/Module/FETCH_URL",
{ id },
{ root: true },
500,
);Example: Get module properties from store configuration
import { getModuleProps } from "@grit-npm/grit-utils";
import store from "./store";
// Get configuration for a specific module
const moduleConfig = getModuleProps(store, "measure");
// Returns: { name: 'Measure', type: 'measure', ...otherProps }
// For modules not found in config, returns default structure
const unknownConfig = getModuleProps(store, "unknownModule");
// Returns: { name: 'UnknownModule', type: 'unknownModule' }Example: Determine the menu side of a module
import { getModuleSide } from "@grit-npm/grit-utils";
import store from "./store";
const side = getModuleSide(store, "legend");
// => "mainMenu"
// Optional: limit the inspected sides
const custom = getModuleSide(store, "measure", { sides: ["secondaryMenu"] });Example: Wait until a Vuex module is ready
import { waitForModule } from "@grit-npm/grit-utils";
import store from "./store";
// Resolve when module exists and has at least one key
const measure = await waitForModule(store, "measure");
// Wait for specific state and resolve a derived value directly
const layerList = await waitForModule(store, "layers", {
predicate: (m) => Array.isArray(m?.list) && m.list.length > 0,
selector: (m) => m.list,
});
// Add a timeout so calls don’t wait indefinitely
await waitForModule(store, "topics", { timeout: 10000 });Example: Check whether a module is active (with GFI handling)
import { isGfiModuleActive } from "@grit-npm/grit-utils";
import store from "./store";
// Consider module active if it’s the current component or if GFI is open and matches selectors
const isActive = isGfiModuleActive(store, "measure", ["#my-gfi", ".gfi-panel"]);
// With explicit flag and custom side name
const active = isGfiModuleActive(store, "buffer", [], { flag: this.isActive, side: "mainMenu" });Example: Highlight FKZ by querying WFS around a coordinate
import { handleFkzHighlighting } from "@grit-npm/grit-utils";
import store from "./store";
const coordinate = [565000, 5934000]; // EPSG:25832 [x, y]
const request = {
url: "https://example.org/wfs",
typename: "my:typename",
storedQueryId: "STORED_QUERY_ID",
outputFormat: "application/json",
}
await handleFkzHighlighting(
store,
coordinate,
request,
(data) => {
// Use response payload for highlighting
// e.g., parse features and update your map
}
)Type Definitions
- JSDoc‑driven types are generated automatically after each build.
- The build runs Rollup and then tsc in declaration‑only mode, emitting
.d.tsfiles todist. - We don’t use TypeScript for source — the TS step only reads JSDoc and writes definitions.
Commands
- Generate types manually:
npm run types - Build (JS + types):
npm run build
Notes
- JS type checking is disabled for generation (
checkJs: false) to keep the process non‑blocking. - Editors pick up types via
package.jsontypesand per‑moduleexportsentries.
Development
- Install deps:
npm ci - Build library:
npm run build - Local pack test:
npm pack - Lint/format (Biome):
npx biome check .andnpx biome format --write . - Lint ignores generated files under
dist/**.
Automation
- Rollup inputs are discovered automatically; any new
src/**/*.js(exceptsrc/index.js) is included in the build. - Package exports are synced automatically before each build (
prebuild):- For every
src/<path>.js, an export entry is generated:- key:
"./<path>" - import:
"./dist/<path>.js" - types:
"./dist/<path>.d.ts"
- key:
- For every
- You can run the sync directly:
node scripts/sync-exports.js.
Requirements
- Node.js: 16, 18, or 20 LTS recommended.
- Peer dependencies (not bundled):
ol9.2.4@masterportal/masterportalapi2.40.0axios,i18next,i18next-vuewhen using related helpers
Engine note
- Using Node 22 may show an EBADENGINE warning from
@masterportal/masterportalapi(it declares support for 16/18/20). It’s a warning only; use Node 20 LTS to silence it if desired.
