{"_id":"@barberaa/dynamic-app-icon","_rev":"2-1fae4b7f51c031fe19fe2173d7bcd8e9","name":"@barberaa/dynamic-app-icon","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@barberaa/dynamic-app-icon","version":"0.1.0","keywords":["react-native","expo","@barberaa/dynamic-app-icon","DynamicAppIcon"],"author":{"url":"https://github.com/notsooryaa","name":"Sooryaa VR","email":"sooryaavr@gmail.com"},"license":"MIT","_id":"@barberaa/dynamic-app-icon@0.1.0","maintainers":[{"name":"sooryaavr","email":"sec19it164@sairamtap.edu.in"}],"homepage":"https://github.com/notsooryaa/dynamic-app-icon#readme","bugs":{"url":"https://github.com/notsooryaa/dynamic-app-icon/issues"},"dist":{"shasum":"b49104d293beb84b247b1674b8548f12019c6db9","tarball":"https://registry.npmjs.org/@barberaa/dynamic-app-icon/-/dynamic-app-icon-0.1.0.tgz","fileCount":63,"integrity":"sha512-wkg2cwMAGL13SutXUXrDv5PZKwHJQZzrznDIl4YqnB2GQb9fOgdm3+zxFktDe8H/tm1C62fXGQyiAwGwq9+y7w==","signatures":[{"sig":"MEYCIQCnc8gwgXF6IMNfRpKOJcK6oAYPNcvtFX4hC5QM9oDdhgIhANATpocQTYLZCKKV+G629m9rFbXmenu9AvGqpULb8nTW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":193128},"jest":{"roots":["<rootDir>/src"],"preset":"jest-expo"},"main":"build/index.js","types":"build/index.d.ts","gitHead":"52d2e77f5a10bc24de48e7840aa4606b0e645171","scripts":{"lint":"eslint src/","test":"node internal/module_scripts/test.js","build":"node internal/module_scripts/build.js","clean":"node internal/module_scripts/clean.js","prepare":"node internal/module_scripts/prepare.js","open:ios":"node internal/module_scripts/open-ios.js","build:plugin":"node internal/module_scripts/build.js plugin","open:android":"node internal/module_scripts/open-android.js"},"_npmUser":{"name":"sooryaavr","email":"sec19it164@sairamtap.edu.in"},"repository":{"url":"git+https://github.com/notsooryaa/dynamic-app-icon.git","type":"git"},"_npmVersion":"10.9.4","description":"Expo dynamic icon module","directories":{},"_nodeVersion":"22.22.0","dependencies":{},"_hasShrinkwrap":false,"devDependencies":{"expo":"^57.0.17","jest":"^29.7.0","eslint":"~9.39.4","prettier":"^3.0.0","jest-expo":"~55.0.9","typescript":"^5.9.2","@babel/core":"^7.26.0","@types/jest":"^29.2.1","@types/react":"~19.1.1","react-native":"0.82.1","@expo/image-utils":"^0.11.5","babel-preset-expo":"~55.0.8","@expo/config-plugins":"^57.0.9","eslint-config-universe":"^15.0.3"},"peerDependencies":{"expo":"*","react":"*","react-native":"*"},"_npmOperationalInternal":{"tmp":"tmp/dynamic-app-icon_0.1.0_1788503899601_0.954914786216893","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@barberaa/dynamic-app-icon","version":"0.2.0","description":"Expo dynamic icon module","main":"build/index.js","types":"build/index.d.ts","scripts":{"build":"node internal/module_scripts/build.js","build:plugin":"node internal/module_scripts/build.js plugin","clean":"node internal/module_scripts/clean.js","lint":"eslint src/","test":"node internal/module_scripts/test.js","prepare":"node internal/module_scripts/prepare.js","open:ios":"node internal/module_scripts/open-ios.js","open:android":"node internal/module_scripts/open-android.js"},"keywords":["react-native","expo","@barberaa/dynamic-app-icon","DynamicAppIcon"],"repository":{"type":"git","url":"git+https://github.com/notsooryaa/dynamic-app-icon.git"},"bugs":{"url":"https://github.com/notsooryaa/dynamic-app-icon/issues"},"author":{"name":"Sooryaa VR","email":"sooryaavr@gmail.com","url":"https://github.com/notsooryaa"},"license":"MIT","homepage":"https://github.com/notsooryaa/dynamic-app-icon#readme","dependencies":{},"devDependencies":{"@babel/core":"^7.26.0","@expo/config-plugins":"^57.0.9","@expo/image-utils":"^0.11.5","@types/jest":"^29.2.1","@types/react":"~19.1.1","babel-preset-expo":"~55.0.8","eslint":"~9.39.4","eslint-config-universe":"^15.0.3","expo":"^57.0.17","jest":"^29.7.0","jest-expo":"~55.0.9","prettier":"^3.0.0","react-native":"0.82.1","typescript":"^5.9.2"},"jest":{"preset":"jest-expo","roots":["<rootDir>/src"]},"peerDependencies":{"expo":"*","react":"*","react-native":"*"},"_id":"@barberaa/dynamic-app-icon@0.2.0","gitHead":"8d87879d5c509c081ee104193284a338cd079694","_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-+fhe2qiGdfkgleROHfILzJ5cEwUQZbT3KucDPUmZ16CqEFNF0NiMYfQW6G8s8py5r87tGCRGOUbssZClBjOo2w==","shasum":"21ca2f0d1d81841e7aaf00792e7acf69a215b3dd","tarball":"https://registry.npmjs.org/@barberaa/dynamic-app-icon/-/dynamic-app-icon-0.2.0.tgz","fileCount":61,"unpackedSize":167999,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD0x7M11rgNFUSpm7nKuHHAjogs4JCYTowZHHeG3t2yZQIhAOZDmfaXkMTYPIFb1NiNkRbenjYbwyeglA0SCdiu/6c7"}]},"_npmUser":{"name":"sooryaavr","email":"sec19it164@sairamtap.edu.in"},"directories":{},"maintainers":[{"name":"sooryaavr","email":"sec19it164@sairamtap.edu.in"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dynamic-app-icon_0.2.0_1788509973916_0.051532871759955245"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-04T06:38:19.413Z","modified":"2026-09-04T08:19:34.268Z","0.1.0":"2026-09-04T06:38:19.765Z","0.2.0":"2026-09-04T08:19:34.056Z"},"bugs":{"url":"https://github.com/notsooryaa/dynamic-app-icon/issues"},"author":{"name":"Sooryaa VR","email":"sooryaavr@gmail.com","url":"https://github.com/notsooryaa"},"license":"MIT","homepage":"https://github.com/notsooryaa/dynamic-app-icon#readme","keywords":["react-native","expo","@barberaa/dynamic-app-icon","DynamicAppIcon"],"repository":{"type":"git","url":"git+https://github.com/notsooryaa/dynamic-app-icon.git"},"description":"Expo dynamic icon module","maintainers":[{"name":"sooryaavr","email":"sec19it164@sairamtap.edu.in"}],"readme":"# @barberaa/dynamic-app-icon\n\nChange your Expo / React Native app's launcher icon at runtime — on both\nAndroid and iOS — from a single, platform-independent JavaScript API.\n\nIcons are declared at build time through an Expo config plugin, bundled into the\nnative app, and selected at runtime. No manual editing of the native `android/`\nor `ios/` projects is required, and everything is reconstructed automatically on\n`expo prebuild --clean`.\n\n```ts\nimport { setAppIcon } from \"@barberaa/dynamic-app-icon\";\n\nawait setAppIcon(\"dark\");\n```\n\n---\n\n## Features\n\n- One JS API for both platforms — no `Platform.OS` branching.\n- Expo config plugin generates all native icon configuration at build time.\n- Survives `expo prebuild` and `expo prebuild --clean`.\n- Reads the active icon from the OS, so it is correct after an app restart.\n- Clear, coded errors for invalid or unconfigured icons.\n\n## Requirements\n\n- Expo SDK 57+ (uses Expo Modules).\n- A prebuild / bare workflow (`expo prebuild`, `expo run:*`, or EAS Build).\n  Icons must be bundled at build time, so this does not run in Expo Go.\n\n---\n\n## Installation\n\n```bash\nnpx expo install @barberaa/dynamic-app-icon\n```\n\n## Configuration\n\nAdd the plugin to your app config (`app.json` / `app.config.js`) and declare\nyour icons. Each value is a path to a source PNG, relative to the project root.\n\n```json\n{\n  \"expo\": {\n    \"plugins\": [\n      [\n        \"@barberaa/dynamic-app-icon\",\n        {\n          \"icons\": {\n            \"default\": \"./assets/icon-default.png\",\n            \"dark\": \"./assets/icon-dark.png\",\n            \"christmas\": \"./assets/icon-christmas.png\"\n          }\n        }\n      ]\n    ]\n  }\n}\n```\n\nThen regenerate the native projects and build:\n\n```bash\nnpx expo prebuild --clean\nnpx expo run:ios      # or run:android\n```\n\n### Icon rules\n\n- **`default`** is your app's primary icon. `resetAppIcon()` returns to it.\n- Icon **names** must match `^[a-z][a-z0-9_]*$` — lowercase, starting with a\n  letter, and containing only lowercase letters, digits, and underscores\n  (e.g. `default`, `dark`, `winter_2025`).\n- **Source images** should be square PNGs; a large master (e.g. 1024×1024) gives\n  the best results. The plugin resizes them for every required density.\n- Source files must exist, or `prebuild` fails with a descriptive error.\n\n> Adding a **new** icon to the config requires a native rebuild (the image must\n> be bundled). Switching between already-bundled icons does not.\n\n---\n\n## API\n\nAll functions are async and platform-independent.\n\n### `setAppIcon(name)`\n\n```ts\nawait setAppIcon(\"dark\");\n```\n\nSelects the icon with the given name. The name must be one of the configured\nicons (see [`getAvailableIcons`](#getavailableicons)); otherwise it throws a\n[`DynamicAppIconError`](#errors) with code `ERR_ICON_NOT_CONFIGURED`.\n\n### `getAppIcon()`\n\n```ts\nconst current = await getAppIcon(); // e.g. \"dark\"\n```\n\nReturns the name of the currently active icon, queried from the OS. Returns\n`\"default\"` when the primary icon is active.\n\n### `resetAppIcon()`\n\n```ts\nawait resetAppIcon();\n```\n\nRestores the default icon. Equivalent to `setAppIcon(\"default\")`.\n\n### `getAvailableIcons()`\n\n```ts\nconst icons = await getAvailableIcons(); // [\"default\", \"dark\", \"christmas\"]\n```\n\nReturns the names of every icon bundled into the app. Always includes\n`\"default\"`.\n\n### Errors\n\nFailures throw a `DynamicAppIconError` carrying a machine-readable `code`:\n\n```ts\nimport { DynamicAppIconError, DynamicAppIconErrorCode } from \"@barberaa/dynamic-app-icon\";\n\ntry {\n  await setAppIcon(\"does-not-exist\");\n} catch (e) {\n  if (e instanceof DynamicAppIconError) {\n    console.warn(e.code, e.message);\n    // e.code === DynamicAppIconErrorCode.IconNotConfigured\n  }\n}\n```\n\n| Code                       | Meaning                                        |\n| -------------------------- | ---------------------------------------------- |\n| `ERR_ICON_NOT_CONFIGURED`  | The requested icon was not configured.         |\n| `ERR_INVALID_ARGUMENT`     | The icon name was empty or not a string.       |\n| `ERR_UNSUPPORTED`          | Alternate icons are unsupported on the device. |\n| `ERR_ICON_SWITCH_FAILED`   | The OS failed to apply the icon change.        |\n\n---\n\n## Example\n\n```tsx\nimport { useEffect, useState } from \"react\";\nimport { Button, Text, View } from \"react-native\";\nimport {\n  getAppIcon,\n  getAvailableIcons,\n  resetAppIcon,\n  setAppIcon,\n} from \"@barberaa/dynamic-app-icon\";\n\nexport function IconSwitcher() {\n  const [icons, setIcons] = useState<string[]>([]);\n  const [current, setCurrent] = useState(\"default\");\n\n  useEffect(() => {\n    (async () => {\n      setIcons(await getAvailableIcons());\n      setCurrent(await getAppIcon());\n    })();\n  }, []);\n\n  return (\n    <View>\n      <Text>Active: {current}</Text>\n      {icons.map((icon) => (\n        <Button\n          key={icon}\n          title={icon}\n          onPress={async () => {\n            await setAppIcon(icon);\n            setCurrent(await getAppIcon());\n          }}\n        />\n      ))}\n      <Button title=\"Reset\" onPress={resetAppIcon} />\n    </View>\n  );\n}\n```\n\n---\n\n## Platform behavior\n\nThe two platforms apply icon changes differently:\n\n- **iOS** — the icon changes immediately via `UIApplication.setAlternateIconName`.\n  iOS shows a system alert (\"You have changed the icon for …\") that cannot be\n  suppressed by a normal app.\n- **Android** — Android has no live icon-change API; icons are implemented with\n  launcher `activity-alias` entries. To avoid tearing down the running app, the\n  change is applied when the app next enters the **background**, so the new icon\n  is in place by the time the user returns to the home screen. Exact refresh\n  timing can vary by device and launcher.\n\n---\n\n## How it works\n\n- **Build time (config plugin):** reads your `icons` map and generates the\n  native configuration — Android launcher resources + `activity-alias` entries,\n  and an iOS asset catalog + the `ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES`\n  build setting. The configured icon names are recorded natively (Android\n  `meta-data`, iOS `Info.plist`) so the runtime module can report them.\n- **Runtime (native module):** `setAppIcon` toggles the active Android alias or\n  calls `setAlternateIconName` on iOS; `getAppIcon` reads the active icon back\n  from the OS.\n\nThe generated native projects are treated as build artifacts — the source of\ntruth is your Expo config plus this package.\n\n---\n\n## License\n\nMIT © [Sooryaa VR](https://github.com/notsooryaa)\n","readmeFilename":"README.md"}