{"_id":"@appberry/berrypickr","name":"@appberry/berrypickr","dist-tags":{"latest":"2.0.0"},"versions":{"2.0.0":{"name":"@appberry/berrypickr","version":"2.0.0","description":"Modern, framework-agnostic color picker for evergreen browsers.","license":"Apache-2.0","author":{"name":"Appberry.dev"},"type":"module","engines":{"node":">=20"},"keywords":["color","colorpicker","ui","typescript","berrypickr"],"main":"./dist/berrypickr.js","module":"./dist/berrypickr.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/berrypickr.js"},"./controller":{"types":"./dist/index.d.ts","import":"./dist/berrypickr.js"},"./bindings":{"types":"./dist/index.d.ts","import":"./dist/berrypickr.js"},"./contrast":{"types":"./dist/index.d.ts","import":"./dist/berrypickr.js"},"./mount":{"types":"./dist/index.d.ts","import":"./dist/berrypickr.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./styles/base.css":"./dist/styles/base.css","./styles/skin-template.css":"./dist/styles/skin-template.css"},"scripts":{"dev":"vitepress dev docs --host 0.0.0.0 --port 5173","build":"pnpm run build:lib && pnpm run build:styles && pnpm run docs:build","build:types":"tsc -p tsconfig.build.json","build:lib":"vite build && pnpm run build:types","build:styles":"node ./scripts/copy-styles.mjs","docs:dev":"vitepress dev docs --host 0.0.0.0 --port 5173","docs:build":"vitepress build docs","docs:preview":"vitepress preview docs --host 0.0.0.0 --port 4174","lint":"eslint .","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","dev:fixture":"vite --config playwright/vite.playwright.config.ts --host 127.0.0.1 --port 43123 --strictPort","test:e2e":"playwright test","changeset":"changeset","version-packages":"changeset version","check":"pnpm run lint && pnpm run typecheck && pnpm run test","check:ci":"pnpm run check && pnpm run test:e2e","prepublishOnly":"pnpm run check && pnpm run build:lib && pnpm run build:styles"},"peerDependencies":{"react":">=18","svelte":">=4","vue":">=3.3"},"peerDependenciesMeta":{"react":{"optional":true},"svelte":{"optional":true},"vue":{"optional":true}},"publishConfig":{"access":"public"},"devDependencies":{"@axe-core/playwright":"^4.11.1","@changesets/cli":"2.28.1","@eslint/js":"9.17.0","@playwright/test":"1.55.1","@types/node":"22.10.2","@types/react":"^19.2.14","eslint":"9.17.0","eslint-config-prettier":"9.1.0","globals":"15.13.0","jsdom":"25.0.1","prettier":"3.4.2","react":"^19.2.4","svelte":"^5.51.0","typescript":"5.7.2","typescript-eslint":"8.18.2","vite":"6.0.5","vitepress":"1.5.0","vitest":"2.1.9","vue":"^3.5.28"},"packageManager":"pnpm@9.0.6","gitHead":"fd76c88f899a7f5034140f1a36ff29820d03494f","_id":"@appberry/berrypickr@2.0.0","_nodeVersion":"24.11.1","_npmVersion":"11.6.4","dist":{"integrity":"sha512-WPkhGfe8VCDB03i+ruzIls6fo8VMQ0FxUImY75+4B8wk8UyYzX70Y8v10ncBPqOmPAGO/xBI0657wg1RI2mGaw==","shasum":"922d135cbf3733b9ee92a160952aa1b9a56aea49","tarball":"https://registry.npmjs.org/@appberry/berrypickr/-/berrypickr-2.0.0.tgz","fileCount":57,"unpackedSize":302228,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD/Y/PlGDXtprtiLcMqF5oAJ3leSoKm3o+aIL4khPKcjgIhAJP9EcwQCkMK0eta4TgmP+55yVVdiNYfFgglCErFgAXm"}]},"_npmUser":{"name":"mdisna","email":"devops@appberry.dev"},"directories":{},"maintainers":[{"name":"mdisna","email":"devops@appberry.dev"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/berrypickr_2.0.0_1771106950262_0.6127471732197134"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-14T22:09:10.150Z","2.0.0":"2026-02-14T22:09:10.429Z","modified":"2026-02-14T22:09:10.683Z"},"maintainers":[{"name":"mdisna","email":"devops@appberry.dev"}],"description":"Modern, framework-agnostic color picker for evergreen browsers.","keywords":["color","colorpicker","ui","typescript","berrypickr"],"author":{"name":"Appberry.dev"},"license":"Apache-2.0","readme":"# BerryPickr\n\nBerryPickr is a headless-first color picker plugin with an optional default UI mount.\nIt gives you one typed color state engine (`controller`) that you can use with:\n\n- the built-in UI mount (`mountBerryPickrUI`)\n- your own custom UI\n- plugin hooks for side effects (analytics, telemetry, policy checks)\n- framework adapters for React, Vue, and Svelte\n\n## Install\n\n```bash\npnpm add @appberry/berrypickr\n```\n\n## Why BerryPickr\n\n- Headless controller API with explicit commit flow (`setValue` vs `commit`)\n- Built-in undo/redo and configurable history\n- Context-aware values: `default`, `hover`, `active`, `focus`, `disabled`\n- Plugin lifecycle hooks: `setup`, `onChange`, `onCommit`, teardown\n- Safe plugin failure control with `pluginErrorPolicy: 'emit' | 'throw'`\n- Optional UI mount with popover mode and runtime updates\n- Binding helpers for CSS variables and inline styles\n- WCAG contrast helpers (`getContrastRatio`, `analyzeContrast`)\n- Official adapter entry points: `@appberry/berrypickr/react`, `@appberry/berrypickr/vue`, `@appberry/berrypickr/svelte`\n\n## Quick Start\n\n```ts\nimport {\n  createBerryPickrController,\n  mountBerryPickrUI,\n  createCssVarBinding,\n  type BerryPickrPlugin\n} from '@appberry/berrypickr';\nimport '@appberry/berrypickr/styles/base.css';\n\nconst telemetryPlugin: BerryPickrPlugin = {\n  name: 'telemetry',\n  onCommit(event) {\n    console.log('commit', event.transactionId, event.value?.to('hexa'));\n  }\n};\n\nconst controller = createBerryPickrController({\n  defaultValue: '#486DFF',\n  formats: ['hex', 'rgba', 'hsla'],\n  history: { limit: 200 },\n  plugins: [telemetryPlugin],\n  pluginErrorPolicy: 'emit'\n});\n\nconst mount = mountBerryPickrUI(controller, {\n  target: '#color-target',\n  mode: 'popover',\n  closeOnEscape: true\n});\n\ncreateCssVarBinding({\n  controller,\n  target: ':root',\n  variable: '--brand-color',\n  format: 'hexa',\n  event: 'commit'\n});\n\ncontroller.on('change', ({ value, source, transactionId }) => {\n  console.log(source, transactionId, value?.to('rgba'));\n});\n\n// Update UI options without remounting.\nmount.update({\n  closeOnOutsideClick: false\n});\n```\n\nMinimum lifecycle you should wire in production:\n\n- `mount.destroy({ remove: true })` when host view unmounts\n- `controller.destroy()` to release plugin teardown/listeners\n\n## Styling\n\nBerryPickr ships with two CSS assets:\n\n- `@appberry/berrypickr/styles/base.css` (required structure + interactions)\n- `@appberry/berrypickr/styles/skin-template.css` (starter theme tokens)\n\nUse CSS variables on `.bp-app` to skin without rewriting component structure:\n\n```css\n.bp-app {\n  --bp-surface: #f6f8ff;\n  --bp-text: #1a2445;\n  --bp-muted: #5d6888;\n  --bp-border: rgba(30, 52, 107, 0.16);\n  --bp-shadow: 0 22px 40px rgba(40, 66, 143, 0.25);\n  --bp-accent: #2f67d1;\n  --bp-danger: #be3f57;\n  --bp-focus: rgba(47, 103, 209, 0.38);\n  --bp-radius: 16px;\n}\n```\n\nRecommended practice:\n\n- Override tokens first; avoid structural CSS overrides unless necessary\n- Keep focus ring token (`--bp-focus`) high-contrast in every theme\n- Re-run keyboard and contrast checks after theme changes\n\n## Accessibility\n\nBerryPickr includes keyboard-first interactions and ARIA labeling hooks:\n\n- Escape-to-close in popover mode (`closeOnEscape`)\n- Keyboard interaction for palette and sliders\n- Localizable `i18n` labels for dialog, toggle, controls, and actions\n- E2E coverage in this repo (Playwright + axe)\n\n```ts\nmountBerryPickrUI(controller, {\n  target: '#color-trigger',\n  closeOnEscape: true,\n  i18n: {\n    dialog: 'Brand color dialog',\n    toggle: 'Open brand color dialog',\n    palette: 'Color palette',\n    hue: 'Hue slider',\n    alpha: 'Opacity slider'\n  }\n});\n```\n\nAccessibility checklist before release:\n\n- Verify keyboard-only access to all visible controls\n- Ensure visible focus states in your final skin\n- Confirm translated `i18n` labels match product terminology\n- Validate contrast for text/button labels in your theme\n\n## Documentation\n\n- Handbook index: [`docs/index.md`](docs/index.md)\n- Quickstart: [`docs/quickstart.md`](docs/quickstart.md)\n- Styling guide: [`docs/styling.md`](docs/styling.md)\n- Accessibility guide: [`docs/accessibility.md`](docs/accessibility.md)\n- Plugin guide + live demos: [`docs/plugins.md`](docs/plugins.md)\n","readmeFilename":"README.md","_rev":"1-5ccda46f22ac43e3ca7dc66e2ac0811b"}