ansuko 1.3.2 → 1.3.3

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.ja.md CHANGED
@@ -167,6 +167,17 @@ extended.toPointGeoJson({ lat: 35.6895, lng: 139.6917 })
167
167
 
168
168
  // 複数のポリゴンを結合
169
169
  const unified = extended.unionPolygon([polygon1, polygon2])
170
+
171
+ // MapBoxユーティリティ
172
+ extended.mZoomInterpolate({ 10: 1, 15: 5, 20: 10 })
173
+ // => ["interpolate", ["linear"], ["zoom"], 10, 1, 15, 5, 20, 10]
174
+
175
+ extended.mProps({
176
+ fillColor: "#ff0000",
177
+ sourceLayer: "buildings",
178
+ visibility: true
179
+ })
180
+ // => { "fill-color": "#ff0000", "source-layer": "buildings", "visibility": "visible" }
170
181
  ```
171
182
 
172
183
  #### Prototypeプラグイン
@@ -254,6 +265,8 @@ extended.toPointGeoJson([139.7, 35.6])
254
265
  - **`toMultiLineStringGeoJson`** - 複数の線をMultiLineStringに変換
255
266
  - **`unionPolygon`** - 複数のPolygon/MultiPolygonを単一のジオメトリに結合
256
267
  - **`parseToTerraDraw`** - GeoJSONをTerra Draw互換のフィーチャーに変換
268
+ - **`mZoomInterpolate`** - ズームオブジェクトをMapBox補間式に変換
269
+ - **`mProps`** - camelCaseプロパティをMapBox互換形式に変換(minzoom、visibilityなどの特殊ケースに対応)
257
270
 
258
271
  ### Prototype拡張(プラグイン: `ansuko/plugins/prototype`)
259
272
 
package/README.md CHANGED
@@ -143,6 +143,8 @@ const value = _.equalsOr(a, b, defaultValue) // null == undefined
143
143
  - **`toMultiLineStringGeoJson`** - Convert multiple lines to MultiLineString
144
144
  - **`unionPolygon`** - Union multiple Polygon/MultiPolygon into single geometry
145
145
  - **`parseToTerraDraw`** - Convert GeoJSON to Terra Draw compatible features
146
+ - **`mZoomInterpolate`** - Convert zoom object to MapBox interpolation expression
147
+ - **`mProps`** - Convert camelCase properties to MapBox-compatible format (handles special cases like minzoom, visibility)
146
148
 
147
149
  ### Prototype Extensions (plugin: `ansuko/plugins/prototype`)
148
150
 
@@ -244,6 +246,17 @@ extended.toPointGeoJson({ lat: 35.6895, lng: 139.6917 })
244
246
 
245
247
  // Union multiple polygons
246
248
  const unified = extended.unionPolygon([polygon1, polygon2])
249
+
250
+ // MapBox utilities
251
+ extended.mZoomInterpolate({ 10: 1, 15: 5, 20: 10 })
252
+ // => ["interpolate", ["linear"], ["zoom"], 10, 1, 15, 5, 20, 10]
253
+
254
+ extended.mProps({
255
+ fillColor: "#ff0000",
256
+ sourceLayer: "buildings",
257
+ visibility: true
258
+ })
259
+ // => { "fill-color": "#ff0000", "source-layer": "buildings", "visibility": "visible" }
247
260
  ```
248
261
 
249
262
  #### Prototype Plugin
package/README.zh.md CHANGED
@@ -142,6 +142,8 @@ const value = _.equalsOr(a, b, defaultValue) // null == undefined
142
142
  - **`toMultiLineStringGeoJson`** - 将多条线转换为 MultiLineString
143
143
  - **`unionPolygon`** - 将多个 Polygon/MultiPolygon 合并为单个几何
144
144
  - **`parseToTerraDraw`** - 将 GeoJSON 转换为 Terra Draw 兼容的要素
145
+ - **`mZoomInterpolate`** - 将缩放对象转换为 MapBox 插值表达式
146
+ - **`mProps`** - 将 camelCase 属性转换为 MapBox 兼容格式(处理 minzoom、visibility 等特殊情况)
145
147
 
146
148
  ### 原型扩展(插件:`ansuko/plugins/prototype`)
147
149
 
@@ -243,6 +245,17 @@ extended.toPointGeoJson({ lat: 35.6895, lng: 139.6917 })
243
245
 
244
246
  // 合并多个多边形
245
247
  const unified = extended.unionPolygon([polygon1, polygon2])
248
+
249
+ // MapBox 工具
250
+ extended.mZoomInterpolate({ 10: 1, 15: 5, 20: 10 })
251
+ // => ["interpolate", ["linear"], ["zoom"], 10, 1, 15, 5, 20, 10]
252
+
253
+ extended.mProps({
254
+ fillColor: "#ff0000",
255
+ sourceLayer: "buildings",
256
+ visibility: true
257
+ })
258
+ // => { "fill-color": "#ff0000", "source-layer": "buildings", "visibility": "visible" }
246
259
  ```
247
260
 
248
261
  #### 原型插件
@@ -21,6 +21,8 @@ export interface AnsukoGeoPluginExtension {
21
21
  toMultiPolygonGeoJson: (geo: any, digit?: number) => GeoJSON.MultiPolygon | null;
22
22
  toMultiLineStringGeoJson: (geo: any, digit?: number) => GeoJSON.MultiLineString | null;
23
23
  unionPolygon: (geo: any, digit?: number) => GeoJSON.Polygon | GeoJSON.MultiPolygon | null;
24
+ mZoomInterpolate: (zoomValues: Record<number, number>, type?: string) => any;
25
+ mProps: (properties: Record<string, any>, excludeKeys?: string[]) => Record<string, any>;
24
26
  }
25
27
  declare const ansukoGeoPlugin: <T extends AnsukoType>(ansuko: T) => T & AnsukoGeoPluginExtension;
26
28
  export default ansukoGeoPlugin;
@@ -551,6 +551,108 @@ const ansukoGeoPlugin = (ansuko) => {
551
551
  }
552
552
  return features;
553
553
  };
554
+ /**
555
+ * Creates a MapBox zoom interpolation expression from a simple object mapping.
556
+ * Converts `{10: 1, 15: 5, 20: 10}` into MapBox's interpolation array format.
557
+ *
558
+ * @param zoomValues - Object mapping zoom levels to values
559
+ * @param type - Interpolation type: "linear", "exponential", or "cubic-bezier" (default: "linear")
560
+ * @returns MapBox interpolation expression array
561
+ * @example
562
+ * _.mZoomInterpolate({ 10: 1, 15: 5, 20: 10 })
563
+ * // Returns: ["interpolate", ["linear"], ["zoom"], 10, 1, 15, 5, 20, 10]
564
+ * @example
565
+ * _.mZoomInterpolate({ 12: 0.5, 18: 2 }, "exponential")
566
+ * @category Geo Utilities
567
+ */
568
+ const mZoomInterpolate = (zoomValues, type = "linear") => {
569
+ let vals = [];
570
+ Object.entries(zoomValues).sort((v1, v2) => {
571
+ return parseFloat(v1[0]) - parseFloat(v2[0]);
572
+ }).map(([zoom, val]) => {
573
+ vals.push(parseFloat(zoom));
574
+ vals.push(val);
575
+ });
576
+ return [
577
+ "interpolate",
578
+ [type],
579
+ ["zoom"],
580
+ ...vals,
581
+ ];
582
+ };
583
+ /**
584
+ * Converts camelCase properties to MapBox-compatible format.
585
+ * Handles special cases like minzoom, maxzoom, tileSize, cluster properties, and converts
586
+ * visibility boolean to "visible"/"none". Recursively processes nested objects and arrays.
587
+ *
588
+ * @param properties - Object with camelCase properties
589
+ * @param excludeKeys - Keys to exclude from conversion (keeps original key and value)
590
+ * @returns Converted properties object compatible with MapBox
591
+ * @example
592
+ * _.mProps({
593
+ * fillColor: "#ff0000",
594
+ * fillOpacity: 0.5,
595
+ * sourceLayer: "buildings"
596
+ * })
597
+ * // Returns: { "fill-color": "#ff0000", "fill-opacity": 0.5, "source-layer": "buildings" }
598
+ * @example
599
+ * _.mProps({ visibility: true }) // Returns: { visibility: "visible" }
600
+ * @example
601
+ * _.mProps({ minZoom: 10, maxZoom: 20 }) // Returns: { minzoom: 10, maxzoom: 20 }
602
+ * @category Geo Utilities
603
+ */
604
+ const mProps = (properties, excludeKeys = []) => {
605
+ if (_.isEmpty(properties)) {
606
+ return properties;
607
+ }
608
+ if (Array.isArray(properties)) {
609
+ return properties.map(p => mProps(p, excludeKeys));
610
+ }
611
+ if (typeof properties === "object") {
612
+ return Object.fromEntries(Object.entries(properties).map(([key, value]) => {
613
+ let newKey = key;
614
+ const lKey = key.toLowerCase();
615
+ if (lKey === "minzoom") {
616
+ newKey = "minzoom";
617
+ }
618
+ else if (lKey === "maxzoom") {
619
+ newKey = "maxzoom";
620
+ }
621
+ else if (lKey === "tilesize") {
622
+ newKey = "tileSize";
623
+ }
624
+ else if (lKey === "clusterradius") {
625
+ newKey = "clusterRadius";
626
+ }
627
+ else if (lKey === "clustermaxzoom") {
628
+ newKey = "clusterMaxZoom";
629
+ }
630
+ else if (lKey === "clusterminpoints") {
631
+ newKey = "clusterMinPoints";
632
+ }
633
+ else if (lKey === "clusterproperties") {
634
+ newKey = "clusterProperties";
635
+ }
636
+ else if (lKey === "linemetrics") {
637
+ newKey = "lineMetrics";
638
+ }
639
+ else {
640
+ newKey = _.kebabCase(newKey).toLowerCase();
641
+ }
642
+ if (key === "visibility" && _.isBoolean(value)) {
643
+ return ["visibility", value ? "visible" : "none"];
644
+ }
645
+ if (excludeKeys.includes(key) || excludeKeys.includes(newKey)) {
646
+ return [key, value];
647
+ }
648
+ if (Array.isArray(value) || typeof value === "object") {
649
+ value = mProps(value, excludeKeys);
650
+ }
651
+ return [newKey, value];
652
+ }));
653
+ }
654
+ return properties;
655
+ };
554
656
  const a = ansuko;
555
657
  a.toLngLatArray = toLngLatArray;
556
658
  a.toGeoJson = toGeoJson;
@@ -562,6 +664,8 @@ const ansukoGeoPlugin = (ansuko) => {
562
664
  a.toMultiPolygonGeoJson = toMultiPolygonGeoJson;
563
665
  a.unionPolygon = unionPolygon;
564
666
  a.parseToTerraDraw = parseToTerraDraw;
667
+ a.mZoomInterpolate = mZoomInterpolate;
668
+ a.mProps = mProps;
565
669
  return ansuko;
566
670
  };
567
671
  export default ansukoGeoPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ansuko",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "A modern JavaScript/TypeScript utility library that extends lodash with practical, intuitive behaviors. Fixes lodash quirks, adds Promise support, Japanese text processing, and GeoJSON utilities.",
5
5
  "keywords": [
6
6
  "lodash",