{"_id":"body-muscles","name":"body-muscles","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"body-muscles","version":"1.0.0","description":"Interactive SVG body map with 70+ muscles, intensity visualization, and zero dependencies. Works with React, Vue, Svelte, or vanilla JS.","main":"dist/index.js","module":"dist/esm/index.js","browser":"dist/umd/body-muscles.umd.min.js","unpkg":"dist/umd/body-muscles.umd.min.js","jsdelivr":"dist/umd/body-muscles.umd.min.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/esm/index.js","require":"./dist/index.js"}},"sideEffects":false,"scripts":{"build":"rm -rf dist && tsc -p tsconfig.build.json && tsc -p tsconfig.build.json --module esnext --outDir dist/esm && node scripts/fix-esm-imports.js && node scripts/build-umd.js","typecheck":"tsc -p tsconfig.build.json --noEmit","docs":"rm -rf docs/lib && cp dist/umd/body-muscles.umd.js docs/lib/body-muscles.umd.js && npx serve docs","docs:build":"rm -rf docs/lib && mkdir -p docs/lib && cp dist/umd/body-muscles.umd.js docs/lib/body-muscles.umd.js","prepublishOnly":"npm run build"},"keywords":["body-map","body-muscles","muscle-chart","anatomy","anatomical","svg","interactive-body-map","muscle-visualization","body-mapping","fitness","workout","human-body","typescript","framework-agnostic","vanilla-js","react","vue","svelte","zero-dependencies"],"author":{"name":"vulovix"},"license":"Apache-2.0","engines":{"node":">=16"},"devDependencies":{"esbuild":"^0.28.0","typescript":"^5.0.0"},"repository":{"type":"git","url":"git+https://github.com/vulovix/body-muscles.git"},"bugs":{"url":"https://github.com/vulovix/body-muscles/issues"},"homepage":"https://vulovix.github.io/body-muscles","_id":"body-muscles@1.0.0","gitHead":"38216b99c7c67518579a2eb71895886621c864ca","_nodeVersion":"24.5.0","_npmVersion":"11.5.1","dist":{"integrity":"sha512-vaYkR9gyaVbqncbA4sGfFuZKwvWiAE6JZYpHR4Stt/jfzYfLPymCE63bba7LEAUi1X8h2wsguP5qYOxmZ2f1ZA==","shasum":"4b2890e5794389d33096b0d4cf1177338abebdfe","tarball":"https://registry.npmjs.org/body-muscles/-/body-muscles-1.0.0.tgz","fileCount":95,"unpackedSize":258941,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIERJbAWOUwMFD26+Dn5XeojMwG/SVZ1h8fYe0LX85KHRAiEAp2qWrQK93msdK/LAb6TuM01VyBT2uEg/fedWE75fLos="}]},"_npmUser":{"name":"localxost","email":"vulovix@gmail.com"},"directories":{},"maintainers":[{"name":"localxost","email":"vulovix@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/body-muscles_1.0.0_1776196808715_0.010373847455225516"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-14T20:00:08.714Z","1.0.0":"2026-04-14T20:00:08.868Z","modified":"2026-04-14T20:00:09.115Z"},"maintainers":[{"name":"localxost","email":"vulovix@gmail.com"}],"description":"Interactive SVG body map with 70+ muscles, intensity visualization, and zero dependencies. Works with React, Vue, Svelte, or vanilla JS.","homepage":"https://vulovix.github.io/body-muscles","keywords":["body-map","body-muscles","muscle-chart","anatomy","anatomical","svg","interactive-body-map","muscle-visualization","body-mapping","fitness","workout","human-body","typescript","framework-agnostic","vanilla-js","react","vue","svelte","zero-dependencies"],"repository":{"type":"git","url":"git+https://github.com/vulovix/body-muscles.git"},"author":{"name":"vulovix"},"bugs":{"url":"https://github.com/vulovix/body-muscles/issues"},"license":"Apache-2.0","readme":"# Body Muscles\n\n**Interactive SVG body map with 70+ muscles, intensity visualization, and zero dependencies.**\n\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n[![npm](https://img.shields.io/npm/v/body-muscles)](https://www.npmjs.com/package/body-muscles)\n\nWorks with React, Vue, Svelte, Angular, or vanilla JavaScript. No framework required.\n\n## Features\n\n- **70+ Anatomical Regions** — Granular muscle mapping with accurate SVG paths\n- **Dual Views** — Anterior (front) and posterior (back) with automatic viewport switching\n- **Intensity Scale** — 0–10 gradient color mapping (yellow → orange → red)\n- **Interactive** — Hover effects, selection states, glow filters\n- **Zero Dependencies** — Pure TypeScript, ~40KB UMD / ~29KB minified\n- **Three Build Formats** — ESM, CommonJS, UMD (works with `file://` too)\n- **TypeScript First** — Full type safety with exported types and interfaces\n\n## Installation\n\n```bash\nnpm install body-muscles\n```\n\n```bash\nyarn add body-muscles\n```\n\n```bash\npnpm add body-muscles\n```\n\n**CDN (ESM):**\n\n```html\n<script type=\"module\">\n  import { BodyChart, ViewSide } from \"https://esm.sh/body-muscles\";\n</script>\n```\n\n**CDN (UMD) — no bundler needed, works from filesystem:**\n\n```html\n<script src=\"https://unpkg.com/body-muscles/dist/umd/body-muscles.umd.min.js\"></script>\n<script>\n  const { BodyChart, ViewSide } = BodyMuscles;\n</script>\n```\n\n## Quick Start\n\n```typescript\nimport { BodyChart, ViewSide } from \"body-muscles\";\n\nconst chart = new BodyChart(document.getElementById(\"container\"), {\n  view: ViewSide.FRONT,\n  bodyState: {},\n  onMuscleClick: (id, name) => {\n    console.log(`Clicked: ${name} (${id})`);\n  },\n  onMuscleHover: (id) => {\n    console.log(\"Hovered:\", id);\n  },\n});\n\n// Update body state\nchart.update({\n  bodyState: {\n    \"biceps-left\": { intensity: 7, selected: true },\n    \"chest-upper-right\": { intensity: 4, selected: false },\n  },\n});\n\n// Switch to back view\nchart.update({ view: ViewSide.BACK });\n\n// Cleanup when done\nchart.destroy();\n```\n\n## API Reference\n\n### `new BodyChart(container, options)`\n\nCreates an interactive body map inside the given DOM element.\n\n#### Options\n\n| Option              | Type                                   | Default     | Description                                 |\n| ------------------- | -------------------------------------- | ----------- | ------------------------------------------- |\n| `view`              | `ViewSide`                             | —           | `FRONT` or `BACK` anatomical view           |\n| `bodyState`         | `BodyState`                            | —           | Map of muscle IDs to intensity & selection   |\n| `onMuscleClick`     | `(id: MuscleId, name: string) => void` | `() => {}`  | Click handler                               |\n| `onMuscleHover`     | `(id: MuscleId \\| null) => void`       | `() => {}`  | Hover state change handler                  |\n| `className`         | `string`                               | `\"\"`        | CSS class for the container wrapper          |\n| `ariaLabel`         | `string`                               | `\"\"`        | Accessibility label for the SVG             |\n| `showViewLabel`     | `boolean`                              | `false`     | Show \"Front View\" / \"Back View\" indicator   |\n| `enableTransitions` | `boolean`                              | `true`      | Smooth CSS transitions on state changes     |\n\n#### Methods\n\n| Method                              | Description                                       |\n| ----------------------------------- | ------------------------------------------------- |\n| `update(options: Partial<Options>)` | Merge new options. View change triggers re-render. |\n| `destroy()`                         | Remove all DOM elements and event listeners.       |\n\n### Types\n\n```typescript\nenum ViewSide {\n  FRONT = \"FRONT\",\n  BACK = \"BACK\",\n}\n\ntype MuscleId = string;\n\ninterface BodyPartState {\n  intensity: number; // 0-10\n  selected: boolean;\n}\n\ntype BodyState = Partial<Record<MuscleId, BodyPartState>>;\n```\n\n### Data Exports\n\n| Export             | Description                                                                            |\n| ------------------ | -------------------------------------------------------------------------------------- |\n| `MUSCLE_MAP`       | All 70+ muscle definitions (front + back)                                              |\n| `FRONT_MUSCLES`    | Anterior-view muscle definitions                                                       |\n| `BACK_MUSCLES`     | Posterior-view muscle definitions                                                      |\n| `MUSCLE_GROUPS`    | Named groups: Head & Neck, Shoulders, Arms, Chest, Back, Abdominals, Legs, Hands & Feet |\n| `INTENSITY_COLORS` | Color map (0-10) from slate → yellow → orange → red                                    |\n\n### Utility Functions\n\n| Function                                     | Description                              |\n| -------------------------------------------- | ---------------------------------------- |\n| `getMuscleColor(state, isHovered)`           | Returns hex color for a `BodyPartState`   |\n| `filterMuscles(view)`                        | Returns `MuscleDef[]` for the given view  |\n| `createBodyPartState(intensity?, selected?)` | Factory with validation                   |\n| `isValidIntensity(value)`                    | Type guard for 0-10 integer               |\n| `extractMuscleSide(id)`                      | Returns `\"left\" \\| \"right\" \\| \"central\"`  |\n| `extractMuscleGroup(id)`                     | Returns base group string                 |\n\n## Framework Examples\n\n### Vanilla JavaScript\n\n```html\n<div id=\"body-map\"></div>\n<script src=\"https://unpkg.com/body-muscles/dist/umd/body-muscles.umd.min.js\"></script>\n<script>\n  const { BodyChart, ViewSide } = BodyMuscles;\n  const state = {};\n\n  const chart = new BodyChart(document.getElementById(\"body-map\"), {\n    view: ViewSide.FRONT,\n    bodyState: state,\n    onMuscleClick(id, name) {\n      const cur = state[id] || { intensity: 0, selected: false };\n      state[id] = { ...cur, selected: !cur.selected };\n      chart.update({ bodyState: state });\n    },\n  });\n</script>\n```\n\n### React\n\n```jsx\nimport { useRef, useEffect, useState } from \"react\";\nimport { BodyChart, ViewSide } from \"body-muscles\";\n\nfunction BodyMap() {\n  const ref = useRef(null);\n  const chartRef = useRef(null);\n  const [bodyState, setBodyState] = useState({});\n\n  useEffect(() => {\n    chartRef.current = new BodyChart(ref.current, {\n      view: ViewSide.FRONT,\n      bodyState,\n      onMuscleClick(id) {\n        setBodyState((prev) => ({\n          ...prev,\n          [id]: {\n            intensity: prev[id]?.intensity ?? 0,\n            selected: !prev[id]?.selected,\n          },\n        }));\n      },\n    });\n    return () => chartRef.current?.destroy();\n  }, []);\n\n  useEffect(() => {\n    chartRef.current?.update({ bodyState });\n  }, [bodyState]);\n\n  return <div ref={ref} />;\n}\n```\n\n### Vue 3\n\n```vue\n<template>\n  <div ref=\"container\" />\n</template>\n\n<script setup>\nimport { ref, onMounted, onUnmounted, watch } from \"vue\";\nimport { BodyChart, ViewSide } from \"body-muscles\";\n\nconst container = ref(null);\nconst bodyState = ref({});\nlet chart;\n\nonMounted(() => {\n  chart = new BodyChart(container.value, {\n    view: ViewSide.FRONT,\n    bodyState: bodyState.value,\n    onMuscleClick(id) {\n      const cur = bodyState.value[id] || { intensity: 0, selected: false };\n      bodyState.value = {\n        ...bodyState.value,\n        [id]: { ...cur, selected: !cur.selected },\n      };\n    },\n  });\n});\n\nwatch(bodyState, (s) => chart?.update({ bodyState: s }), { deep: true });\nonUnmounted(() => chart?.destroy());\n</script>\n```\n\n### Svelte\n\n```svelte\n<script>\n  import { onMount, onDestroy } from \"svelte\";\n  import { BodyChart, ViewSide } from \"body-muscles\";\n\n  let container;\n  let chart;\n  let bodyState = {};\n\n  onMount(() => {\n    chart = new BodyChart(container, {\n      view: ViewSide.FRONT,\n      bodyState,\n      onMuscleClick(id) {\n        const cur = bodyState[id] || { intensity: 0, selected: false };\n        bodyState = { ...bodyState, [id]: { ...cur, selected: !cur.selected } };\n        chart.update({ bodyState });\n      },\n    });\n  });\n\n  onDestroy(() => chart?.destroy());\n</script>\n\n<div bind:this={container} />\n```\n\n## Muscle ID Naming\n\n```\n{muscle_group}-{side}             →  biceps-left\n{muscle_group}-{sub_group}-{side} →  shoulder-front-left\n{singular}                        →  spine\n```\n\n## Project Structure\n\n```\nbody-muscles/\n├── src/\n│   ├── BodyChart.ts          # Main class\n│   ├── types.ts              # TypeScript types & utilities\n│   ├── index.ts              # Public exports\n│   ├── data/                 # SVG path data & muscle definitions\n│   └── utils/                # getMuscleColor, filterMuscles\n├── dist/\n│   ├── esm/                  # ESM build\n│   └── umd/                  # UMD build (browser/CDN)\n├── docs/                     # Documentation site\n├── scripts/                  # Build scripts\n├── package.json\n└── tsconfig.json\n```\n\n## License\n\nApache 2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE).\n","readmeFilename":"README.md","_rev":"1-0a24bf751974bfcafa516fb4b58508fe"}