@ogc-maps/storybook-components 0.2.2 → 0.2.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.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ogc-maps/storybook-components
2
2
 
3
- A reuseable, config-driven map component library built on OGC API standards. Designed for building interactive web maps with React, MapLibre GL JS, and `tipg`.
3
+ A reusable, config-driven map component library built on OGC API standards. Designed for building interactive web maps with React, MapLibre GL JS, and `tipg`.
4
4
 
5
5
  ## Features
6
6
 
@@ -20,69 +20,43 @@ npm install @ogc-maps/storybook-components
20
20
  yarn add @ogc-maps/storybook-components
21
21
  ```
22
22
 
23
- ## Usage
23
+ Peer dependencies: `react`, `react-dom`, `react-icons`
24
24
 
25
- ### 1. Import Styles
26
-
27
- Import the library's CSS in your main entry point (e.g., `main.tsx` or `App.tsx`):
25
+ ## Quick Start
28
26
 
29
27
  ```tsx
30
- import '@ogc-maps/storybook-components/dist/style.css';
31
- ```
28
+ // 1. Import styles in your entry point (default styles use the mapui: prefix; you can override with your own Tailwind/CSS)
29
+ import '@ogc-maps/storybook-components/style.css';
32
30
 
33
- ### 2. Use Components
31
+ // 2. Define and validate your config
32
+ import { safeValidateMapConfig } from '@ogc-maps/storybook-components/schemas';
34
33
 
35
- Components are exported as named exports. Example using the `LayerPanel`:
34
+ const result = safeValidateMapConfig(myConfig);
35
+ if (!result.success) throw new Error('Invalid config');
36
36
 
37
- ```tsx
37
+ // 3. Render components with your state
38
38
  import { LayerPanel } from '@ogc-maps/storybook-components/components/LayerPanel';
39
+ import { Legend } from '@ogc-maps/storybook-components/components/Legend';
39
40
 
40
- function MyMapUI() {
41
- const [activeLayers, setActiveLayers] = useState<string[]>(['my-layer-1']);
42
-
41
+ function MapUI({ layers, visibleIds, onToggle }) {
43
42
  return (
44
- <div className="absolute top-4 right-4 bg-white p-4 rounded shadow">
45
- <LayerPanel
46
- layers={myLayerConfig}
47
- activeLayerIds={activeLayers}
48
- onToggleVisibility={(layerId) => {
49
- // toggle logic
50
- }}
51
- />
52
- </div>
43
+ <>
44
+ <LayerPanel layers={layers} activeLayerIds={visibleIds} onToggleVisibility={onToggle} />
45
+ <Legend layers={layers} visibleLayerIds={visibleIds} />
46
+ </>
53
47
  );
54
48
  }
55
49
  ```
56
50
 
57
- ### 3. Use Hooks
58
-
59
- Data fetching hooks for OGC API endpoints:
60
-
61
- ```tsx
62
- import { useOgcFeatures } from '@ogc-maps/storybook-components/hooks';
63
-
64
- function FeatureList() {
65
- const { data, loading } = useOgcFeatures({
66
- collectionId: 'public.my_collection',
67
- limit: 10
68
- });
69
-
70
- if (loading) return <div>Loading...</div>;
71
-
72
- return (
73
- <ul>
74
- {data.features.map(f => (
75
- <li key={f.id}>{f.properties.name}</li>
76
- ))}
77
- </ul>
78
- );
79
- }
80
- ```
51
+ Default styles use the `mapui:` Tailwind prefix so they won't clash with your app's utility classes; override them with your own CSS or Tailwind as needed.
81
52
 
82
53
  ## Documentation
83
54
 
84
- Full documentation and component playground available at:
85
- [https://<YOUR_GITHUB_USERNAME>.github.io/ogc-maps](https://<YOUR_GITHUB_USERNAME>.github.io/ogc-maps) (Replace with actual URL once deployed)
55
+ - [Getting Started](../../docs/GETTING-STARTED.md) Installation, minimal config, first render
56
+ - [Configuration](../../docs/CONFIGURATION.md) Full `MapConfig` schema reference
57
+ - [Components](../../docs/COMPONENTS.md) — All 6 component APIs with props tables and examples
58
+ - [Hooks & Utilities](../../docs/HOOKS.md) — OGC API hooks and utility functions
59
+ - [Publishing](../../docs/PUBLISHING.md) — Versioning and release guide
86
60
 
87
61
  ## License
88
62
 
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAGA,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC;AAGxB,cAAc,WAAW,CAAC;AAG1B,cAAc,SAAS,CAAC;AAGxB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AACA,OAAO,iBAAiB,CAAC;AAGzB,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC;AAGxB,cAAc,WAAW,CAAC;AAG1B,cAAc,SAAS,CAAC;AAGxB,cAAc,SAAS,CAAC"}
package/dist/main.js CHANGED
@@ -7,7 +7,7 @@ import { S as g } from "./SearchPanel-CFVQV6JJ.js";
7
7
  import { u as p, a as d } from "./useOgcFeatures-CmJxErv4.js";
8
8
  import { f as y, a as L, b as u, g as F, c as P, d as M } from "./ogcApi-BuXSs9i0.js";
9
9
  import { BasemapConfigSchema as V, CirclePaintSchema as b, CircleStyleSchema as B, FillPaintSchema as D, FillStyleSchema as O, FilterConfigSchema as T, LayerConfigSchema as w, LegendConfigSchema as v, LegendEntrySchema as A, LinePaintSchema as E, LineStyleSchema as I, MapConfigSchema as J, OgcApiSourceSchema as Q, SearchConfigSchema as j, SearchFieldSchema as k, StyleConfigSchema as q, UIConfigSchema as z, ViewConfigSchema as G, safeValidateMapConfig as H, validateMapConfig as K } from "./schemas/index.js";
10
- export {
10
+ import './style.css';export {
11
11
  V as BasemapConfigSchema,
12
12
  o as BasemapSwitcher,
13
13
  b as CirclePaintSchema,
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--mapui-font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--mapui-font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--mapui-color-blue-50:oklch(97% .014 254.604);--mapui-color-blue-100:oklch(93.2% .032 255.585);--mapui-color-blue-300:oklch(80.9% .105 251.813);--mapui-color-blue-500:oklch(62.3% .214 259.815);--mapui-color-blue-600:oklch(54.6% .245 262.881);--mapui-color-blue-700:oklch(48.8% .243 264.376);--mapui-color-gray-100:oklch(96.7% .003 264.542);--mapui-color-gray-200:oklch(92.8% .006 264.531);--mapui-color-gray-300:oklch(87.2% .01 258.338);--mapui-color-gray-400:oklch(70.7% .022 261.325);--mapui-color-gray-500:oklch(55.1% .027 264.364);--mapui-color-gray-600:oklch(44.6% .03 256.802);--mapui-color-gray-700:oklch(37.3% .034 259.733);--mapui-color-gray-800:oklch(27.8% .033 256.848);--mapui-color-black:#000;--mapui-color-white:#fff;--mapui-spacing:.25rem;--mapui-text-xs:.75rem;--mapui-text-xs--line-height:calc(1/.75);--mapui-text-sm:.875rem;--mapui-text-sm--line-height:calc(1.25/.875);--mapui-font-weight-medium:500;--mapui-font-weight-semibold:600;--mapui-tracking-wide:.025em;--mapui-radius-sm:.25rem;--mapui-radius-md:.375rem;--mapui-radius-lg:.5rem;--mapui-default-transition-duration:.15s;--mapui-default-transition-timing-function:cubic-bezier(.4,0,.2,1);--mapui-default-font-family:var(--mapui-font-sans);--mapui-default-mono-font-family:var(--mapui-font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--mapui-default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--mapui-default-font-feature-settings,normal);font-variation-settings:var(--mapui-default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--mapui-default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--mapui-default-mono-font-feature-settings,normal);font-variation-settings:var(--mapui-default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.mapui\:pointer-events-none{pointer-events:none}.mapui\:absolute{position:absolute}.mapui\:relative{position:relative}.mapui\:top-0{top:calc(var(--mapui-spacing)*0)}.mapui\:right-full{right:100%}.mapui\:z-10{z-index:10}.mapui\:m-0{margin:calc(var(--mapui-spacing)*0)}.mapui\:mt-2{margin-top:calc(var(--mapui-spacing)*2)}.mapui\:mr-2{margin-right:calc(var(--mapui-spacing)*2)}.mapui\:mb-1{margin-bottom:calc(var(--mapui-spacing)*1)}.mapui\:mb-2{margin-bottom:calc(var(--mapui-spacing)*2)}.mapui\:flex{display:flex}.mapui\:inline-block{display:inline-block}.mapui\:h-0\.5{height:calc(var(--mapui-spacing)*.5)}.mapui\:h-3{height:calc(var(--mapui-spacing)*3)}.mapui\:h-4{height:calc(var(--mapui-spacing)*4)}.mapui\:h-6{height:calc(var(--mapui-spacing)*6)}.mapui\:h-10{height:calc(var(--mapui-spacing)*10)}.mapui\:h-12{height:calc(var(--mapui-spacing)*12)}.mapui\:w-3{width:calc(var(--mapui-spacing)*3)}.mapui\:w-4{width:calc(var(--mapui-spacing)*4)}.mapui\:w-6{width:calc(var(--mapui-spacing)*6)}.mapui\:w-10{width:calc(var(--mapui-spacing)*10)}.mapui\:w-16{width:calc(var(--mapui-spacing)*16)}.mapui\:w-64{width:calc(var(--mapui-spacing)*64)}.mapui\:w-full{width:100%}.mapui\:flex-1{flex:1}.mapui\:shrink-0{flex-shrink:0}.mapui\:cursor-grab{cursor:grab}.mapui\:cursor-pointer{cursor:pointer}.mapui\:list-none{list-style-type:none}.mapui\:flex-col{flex-direction:column}.mapui\:flex-wrap{flex-wrap:wrap}.mapui\:items-center{align-items:center}.mapui\:justify-between{justify-content:space-between}.mapui\:justify-center{justify-content:center}.mapui\:gap-0\.5{gap:calc(var(--mapui-spacing)*.5)}.mapui\:gap-1{gap:calc(var(--mapui-spacing)*1)}.mapui\:gap-2{gap:calc(var(--mapui-spacing)*2)}.mapui\:gap-3{gap:calc(var(--mapui-spacing)*3)}.mapui\:gap-4{gap:calc(var(--mapui-spacing)*4)}:where(.mapui\:space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--mapui-spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--mapui-spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.mapui\:space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--mapui-spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--mapui-spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.mapui\:space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--mapui-spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--mapui-spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.mapui\:overflow-hidden{overflow:hidden}.mapui\:rounded{border-radius:.25rem}.mapui\:rounded-full{border-radius:3.40282e38px}.mapui\:rounded-lg{border-radius:var(--mapui-radius-lg)}.mapui\:rounded-md{border-radius:var(--mapui-radius-md)}.mapui\:rounded-sm{border-radius:var(--mapui-radius-sm)}.mapui\:border{border-style:var(--tw-border-style);border-width:1px}.mapui\:border-2{border-style:var(--tw-border-style);border-width:2px}.mapui\:border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.mapui\:border-none{--tw-border-style:none;border-style:none}.mapui\:border-blue-500{border-color:var(--mapui-color-blue-500)}.mapui\:border-gray-100{border-color:var(--mapui-color-gray-100)}.mapui\:border-gray-200{border-color:var(--mapui-color-gray-200)}.mapui\:border-gray-300{border-color:var(--mapui-color-gray-300)}.mapui\:bg-black\/60{background-color:var(--mapui-color-black)}@supports (color:color-mix(in lab,red,red)){.mapui\:bg-black\/60{background-color:color-mix(in oklab,var(--mapui-color-black)60%,transparent)}}.mapui\:bg-blue-50{background-color:var(--mapui-color-blue-50)}.mapui\:bg-blue-100{background-color:var(--mapui-color-blue-100)}.mapui\:bg-blue-500{background-color:var(--mapui-color-blue-500)}.mapui\:bg-gray-100{background-color:var(--mapui-color-gray-100)}.mapui\:bg-transparent{background-color:#0000}.mapui\:bg-white{background-color:var(--mapui-color-white)}.mapui\:object-cover{object-fit:cover}.mapui\:p-0{padding:calc(var(--mapui-spacing)*0)}.mapui\:p-2{padding:calc(var(--mapui-spacing)*2)}.mapui\:p-3{padding:calc(var(--mapui-spacing)*3)}.mapui\:p-4{padding:calc(var(--mapui-spacing)*4)}.mapui\:px-2{padding-inline:calc(var(--mapui-spacing)*2)}.mapui\:px-3{padding-inline:calc(var(--mapui-spacing)*3)}.mapui\:px-4{padding-inline:calc(var(--mapui-spacing)*4)}.mapui\:py-1{padding-block:calc(var(--mapui-spacing)*1)}.mapui\:py-1\.5{padding-block:calc(var(--mapui-spacing)*1.5)}.mapui\:py-2{padding-block:calc(var(--mapui-spacing)*2)}.mapui\:pb-2{padding-bottom:calc(var(--mapui-spacing)*2)}.mapui\:pl-1{padding-left:calc(var(--mapui-spacing)*1)}.mapui\:font-mono{font-family:var(--mapui-font-mono)}.mapui\:text-sm{font-size:var(--mapui-text-sm);line-height:var(--tw-leading,var(--mapui-text-sm--line-height))}.mapui\:text-xs{font-size:var(--mapui-text-xs);line-height:var(--tw-leading,var(--mapui-text-xs--line-height))}.mapui\:font-medium{--tw-font-weight:var(--mapui-font-weight-medium);font-weight:var(--mapui-font-weight-medium)}.mapui\:font-semibold{--tw-font-weight:var(--mapui-font-weight-semibold);font-weight:var(--mapui-font-weight-semibold)}.mapui\:tracking-wide{--tw-tracking:var(--mapui-tracking-wide);letter-spacing:var(--mapui-tracking-wide)}.mapui\:text-blue-300{color:var(--mapui-color-blue-300)}.mapui\:text-blue-600{color:var(--mapui-color-blue-600)}.mapui\:text-blue-700{color:var(--mapui-color-blue-700)}.mapui\:text-gray-400{color:var(--mapui-color-gray-400)}.mapui\:text-gray-500{color:var(--mapui-color-gray-500)}.mapui\:text-gray-600{color:var(--mapui-color-gray-600)}.mapui\:text-gray-700{color:var(--mapui-color-gray-700)}.mapui\:text-gray-800{color:var(--mapui-color-gray-800)}.mapui\:text-white{color:var(--mapui-color-white)}.mapui\:uppercase{text-transform:uppercase}.mapui\:accent-blue-600{accent-color:var(--mapui-color-blue-600)}.mapui\:opacity-0{opacity:0}.mapui\:opacity-50{opacity:.5}.mapui\:opacity-100{opacity:1}.mapui\:shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.mapui\:shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.mapui\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--mapui-default-transition-timing-function));transition-duration:var(--tw-duration,var(--mapui-default-transition-duration))}.mapui\:outline-none{--tw-outline-style:none;outline-style:none}.mapui\:select-none{-webkit-user-select:none;user-select:none}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ogc-maps/storybook-components",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "main": "./dist/main.js",
6
6
  "publishConfig": {
@@ -13,6 +13,7 @@
13
13
  "types": "./dist/main.d.ts",
14
14
  "import": "./dist/main.js"
15
15
  },
16
+ "./style.css": "./dist/style.css",
16
17
  "./components/LayerPanel": {
17
18
  "types": "./dist/components/LayerPanel/index.d.ts",
18
19
  "import": "./dist/components/LayerPanel/index.js"