{"_id":"meemaw","_rev":"3-a6474cbe53f6fd5055c34ae256b979d3","name":"meemaw","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"meemaw","version":"1.0.0","keywords":["react","components","utility","declarative","ui","hooks","typescript"],"author":{"name":"spiderocious","email":"devferanmi@gmail.com"},"license":"MIT","_id":"meemaw@1.0.0","maintainers":[{"name":"devferanmi","email":"devferanmi@gmail.com"}],"homepage":"https://github.com/spiderocious/meemaw","bugs":{"url":"https://github.com/spiderocious/meemaw/issues"},"dist":{"shasum":"9d96e1a57e0f2b215f0d06402a5a6f706a9afaff","tarball":"https://registry.npmjs.org/meemaw/-/meemaw-1.0.0.tgz","fileCount":9,"integrity":"sha512-lmZMGZGD8tQZKs25z7SLQUd243xYhmrAZC+a7VT7mxBAS1EXahpiJpJXv0GLYIPhhekonMDQPJDdo225cYdrsQ==","signatures":[{"sig":"MEUCIQDfVySz4AqHw/Wy9EbAxrtSBGWhaZVIVtKwOYY4FIzijAIgePNohquDcBv7xJJZ3f5B48giTCX9vHteImwNpR8n+O8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":88336},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"e07acbcde61adcbebc7f50c4b7ee7442a47a881b","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","size":"size-limit","test":"jest","build":"tsup","format":"prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"","typecheck":"tsc --noEmit","test:watch":"jest --watch","format:check":"prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\"","test:coverage":"jest --coverage","prepublishOnlys":"npm run typecheck && npm run test && npm run build"},"_npmUser":{"name":"devferanmi","email":"devferanmi@gmail.com"},"repository":{"url":"git+https://github.com/spiderocious/meemaw.git","type":"git"},"size-limit":[{"path":"dist/index.js","limit":"10 KB"}],"_npmVersion":"10.9.2","description":"Elegant, declarative React utility components for common UI patterns","directories":{},"sideEffects":false,"_nodeVersion":"23.6.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","tsup":"^8.3.5","react":"^18.3.1","eslint":"^8.57.1","ts-jest":"^29.2.5","prettier":"^3.7.4","react-dom":"^18.3.1","size-limit":"^11.1.6","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/react":"^18.3.17","@types/react-dom":"^18.3.5","@testing-library/react":"^14.3.1","eslint-config-prettier":"^10.1.8","jest-environment-jsdom":"^29.7.0","@testing-library/jest-dom":"^6.6.3","@typescript-eslint/parser":"^6.21.0","@size-limit/preset-small-lib":"^11.1.6","@typescript-eslint/eslint-plugin":"^6.21.0"},"peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"_npmOperationalInternal":{"tmp":"tmp/meemaw_1.0.0_1766499365962_0.6225095966885925","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"meemaw","version":"1.0.1","keywords":["react","components","utility","declarative","ui","hooks","typescript"],"author":{"name":"spiderocious","email":"devferanmi@gmail.com"},"license":"MIT","_id":"meemaw@1.0.1","maintainers":[{"name":"devferanmi","email":"devferanmi@gmail.com"}],"homepage":"https://github.com/spiderocious/meemaw","bugs":{"url":"https://github.com/spiderocious/meemaw/issues"},"dist":{"shasum":"08238b4c4e49bcebe106b4049db976eebcffa6b9","tarball":"https://registry.npmjs.org/meemaw/-/meemaw-1.0.1.tgz","fileCount":7,"integrity":"sha512-4FwKv+fs2wfu/Anc97aV0qrCF319CNB+ceHFq0b466aldhFpY8xOnueK+JQI0zAsswF26EHq4pR7/FK5HFdG8w==","signatures":[{"sig":"MEQCIDbJnQrJkvAC79ai9xmJxIwmQrrgeNLSreRQSbjILM95AiAWb58vby32VSP3dS3lw+KZxWBFBnFUP9+alTRehGVK3A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25808},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"4885384ee27a59d217623f82526a0ad2d16ec93d","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","size":"size-limit","test":"jest","build":"tsup","format":"prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"","typecheck":"tsc --noEmit","test:watch":"jest --watch","format:check":"prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\"","test:coverage":"jest --coverage","prepublishOnly":"npm run typecheck && npm run test && npm run build"},"_npmUser":{"name":"devferanmi","email":"devferanmi@gmail.com"},"repository":{"url":"git+https://github.com/spiderocious/meemaw.git","type":"git"},"size-limit":[{"path":"dist/index.js","limit":"10 KB"}],"_npmVersion":"10.9.2","description":"Elegant, declarative React utility components for common UI patterns","directories":{},"sideEffects":false,"_nodeVersion":"23.6.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","tsup":"^8.3.5","react":"^18.3.1","eslint":"^8.57.1","ts-jest":"^29.2.5","prettier":"^3.7.4","react-dom":"^18.3.1","size-limit":"^11.1.6","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/react":"^18.3.17","@types/react-dom":"^18.3.5","@testing-library/react":"^14.3.1","eslint-config-prettier":"^10.1.8","jest-environment-jsdom":"^29.7.0","@testing-library/jest-dom":"^6.6.3","@typescript-eslint/parser":"^6.21.0","@size-limit/preset-small-lib":"^11.1.6","@typescript-eslint/eslint-plugin":"^6.21.0"},"peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"_npmOperationalInternal":{"tmp":"tmp/meemaw_1.0.1_1766499574008_0.9705423331251881","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"meemaw","version":"1.0.2","description":"Elegant, declarative React utility components for common UI patterns","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"sideEffects":false,"scripts":{"build":"tsup","dev":"tsup --watch","test":"jest","test:watch":"jest --watch","test:coverage":"jest --coverage","typecheck":"tsc --noEmit","lint":"eslint src --ext .ts,.tsx","format":"prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"","format:check":"prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\"","prepublishOnly":"npm run typecheck && npm run test && npm run build","size":"size-limit"},"keywords":["react","components","utility","declarative","ui","hooks","typescript"],"author":{"name":"spiderocious","email":"devferanmi@gmail.com"},"license":"MIT","peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"devDependencies":{"@size-limit/preset-small-lib":"^11.1.6","@testing-library/jest-dom":"^6.6.3","@testing-library/react":"^14.3.1","@types/jest":"^29.5.14","@types/react":"^18.3.17","@types/react-dom":"^18.3.5","@typescript-eslint/eslint-plugin":"^6.21.0","@typescript-eslint/parser":"^6.21.0","eslint":"^8.57.1","eslint-config-prettier":"^10.1.8","jest":"^29.7.0","jest-environment-jsdom":"^29.7.0","prettier":"^3.7.4","react":"^18.3.1","react-dom":"^18.3.1","size-limit":"^11.1.6","ts-jest":"^29.2.5","tsup":"^8.3.5","typescript":"^5.7.2"},"size-limit":[{"path":"dist/index.js","limit":"10 KB"}],"repository":{"type":"git","url":"git+https://github.com/spiderocious/meemaw.git"},"bugs":{"url":"https://github.com/spiderocious/meemaw/issues"},"homepage":"https://github.com/spiderocious/meemaw","_id":"meemaw@1.0.2","gitHead":"35924e8e52897c5a2b186f1060313f681b89a1e8","_nodeVersion":"23.6.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-+ignRrXPJDk1P1f4AgcNhi5dqxDZc17Wq48MBYuliDj+Idq47lad2YCR160x7CTzdO8AYJV3sSJL+6h585qAug==","shasum":"8c090316e65fea430fb4c6954162c8a09886a0a3","tarball":"https://registry.npmjs.org/meemaw/-/meemaw-1.0.2.tgz","fileCount":7,"unpackedSize":33828,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC+AZkIXkPd/Hwwc2bl6k1J1vqMsNfNWrtra24M5wqk0AIhAKla2FuR2mG7Zw/hIA3PoY0b1/ZhdYCmpzFcUcXi5ZHO"}]},"_npmUser":{"name":"devferanmi","email":"devferanmi@gmail.com"},"directories":{},"maintainers":[{"name":"devferanmi","email":"devferanmi@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/meemaw_1.0.2_1766500515379_0.08781120650915919"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-23T14:16:05.820Z","modified":"2025-12-23T14:35:15.721Z","1.0.0":"2025-12-23T14:16:06.115Z","1.0.1":"2025-12-23T14:19:34.144Z","1.0.2":"2025-12-23T14:35:15.524Z"},"bugs":{"url":"https://github.com/spiderocious/meemaw/issues"},"author":{"name":"spiderocious","email":"devferanmi@gmail.com"},"license":"MIT","homepage":"https://github.com/spiderocious/meemaw","keywords":["react","components","utility","declarative","ui","hooks","typescript"],"repository":{"type":"git","url":"git+https://github.com/spiderocious/meemaw.git"},"description":"Elegant, declarative React utility components for common UI patterns","maintainers":[{"name":"devferanmi","email":"devferanmi@gmail.com"}],"readme":"# Meemaw\n\n**Elegant, declarative React utility components for common UI patterns**\n\n• [Installation](#installation)\n• [Components](#components)\n• [Examples](#examples)\n• [Documentation](#documentation)\n\n---\n\n## Why Meemaw?\n\nStop writing repetitive JSX patterns. Meemaw provides a collection of lightweight, zero-dependency React components that make your code more readable and maintainable.\n\n```jsx\n// Before\n{\n  isLoggedIn ? <Dashboard /> : <Login />;\n}\n\n// After\n<Show when={isLoggedIn} fallback={<Login />}>\n  <Dashboard />\n</Show>;\n```\n\n### Features\n\n- **Zero dependencies** - Only React as peer dependency\n- **Tiny bundle** - Less than 10KB total\n- **Tree-shakeable** - Import only what you need\n- **TypeScript first** - Full type safety out of the box\n- **100% test coverage** - Thoroughly tested and reliable\n- **SSR compatible** - Works with Next.js, Remix, and other frameworks\n\n---\n\n## Installation\n\n```bash\nnpm install meemaw\n```\n\n```bash\nyarn add meemaw\n```\n\n```bash\npnpm add meemaw\n```\n\n---\n\n## Components\n\n### Conditional Rendering\n\n#### `<Switch>`, `<Case>`, `<Default>`\n\nClean match-case pattern for multiple conditions. No more nested ternaries.\n\n```jsx\nimport { Switch, Case, Default } from 'meemaw';\n\nfunction OrderStatus({ status }) {\n  return (\n    <Switch>\n      <Case when={status === 'pending'}>\n        <PendingIcon /> Processing your order...\n      </Case>\n      <Case when={status === 'shipped'}>\n        <TruckIcon /> On the way!\n      </Case>\n      <Case when={status === 'delivered'}>\n        <CheckIcon /> Delivered\n      </Case>\n      <Default>\n        <ErrorIcon /> Unknown status\n      </Default>\n    </Switch>\n  );\n}\n```\n\n#### `<Show>`\n\nSimple conditional rendering with optional fallback.\n\n```jsx\nimport { Show } from 'meemaw';\n\n// Basic usage\n<Show when={isLoggedIn}>\n  <UserProfile />\n</Show>\n\n// With fallback\n<Show when={hasPermission} fallback={<AccessDenied />}>\n  <AdminPanel />\n</Show>\n\n// Using 'if' prop (alias for 'when')\n<Show if={isLoading} fallback={<Content />}>\n  <Spinner />\n</Show>\n```\n\n#### `<Hidden>`\n\nHide content conditionally or based on viewport breakpoints.\n\n```jsx\nimport { Hidden } from 'meemaw';\n\n// Conditional hiding\n<Hidden when={!isPublic}>\n  <SecretContent />\n</Hidden>\n\n// Responsive hiding\n<Hidden on=\"mobile\">\n  <DesktopNav />\n</Hidden>\n\n<Hidden on={['mobile', 'tablet']}>\n  <DesktopOnlyFeature />\n</Hidden>\n```\n\n**Breakpoints:**\n\n- `mobile`: < 768px\n- `tablet`: < 1024px\n- `desktop`: ≥ 1024px\n\n#### `<Loadable>`\n\nHandle async operation states with built-in loading and error UI.\n\n```jsx\nimport { Loadable } from 'meemaw';\n\nfunction UserData() {\n  const { data, loading, error } = useFetch('/api/user');\n\n  return (\n    <Loadable loading={loading} error={error}>\n      <UserProfile data={data} />\n    </Loadable>\n  );\n}\n\n// Custom loading and error components\n<Loadable\n  loading={isLoading}\n  error={error}\n  loadingComponent={<CustomSpinner />}\n  errorComponent={<ErrorAlert message={err.message} />}\n>\n  <Content />\n</Loadable>;\n```\n\n---\n\n### Iteration\n\n#### `<Repeat>`\n\nIterate arrays or repeat elements n times with clean syntax.\n\n```jsx\nimport { Repeat } from 'meemaw';\n\n// Repeat n times\n<Repeat times={5}>\n  {(_, index) => <Star key={index} />}\n</Repeat>\n\n// Iterate over array\nconst users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];\n\n<Repeat each={users}>\n  {(user, index) => (\n    <UserCard key={user.id} user={user} />\n  )}\n</Repeat>\n\n// Static children (repeated as-is)\n<Repeat times={3}>\n  <Divider />\n</Repeat>\n```\n\n---\n\n### Time-based Components\n\n#### `<Delayed>`\n\nDelay rendering until a condition is met or timeout expires.\n\n```jsx\nimport { Delayed } from 'meemaw';\n\n// Show after 3 seconds\n<Delayed till={3000}>\n  <Announcement />\n</Delayed>\n\n// Show at specific date/time\n<Delayed till={new Date('2025-01-01')}>\n  <NewYearMessage />\n</Delayed>\n\n// Show when condition becomes true\n<Delayed until={dataLoaded} fallback={<Loading />}>\n  <DataView />\n</Delayed>\n```\n\n#### `<ShowOnce>`\n\nDisplay content only once with optional persistence.\n\n```jsx\nimport { ShowOnce } from 'meemaw';\n\n// Show for 5 seconds then hide forever\n<ShowOnce for={5000} persist>\n  <WelcomeBanner />\n</ShowOnce>\n\n// Show once per session\n<ShowOnce persist persistType=\"session\">\n  <NewFeatureTooltip />\n</ShowOnce>\n\n// Show once across all sessions (localStorage)\n<ShowOnce persist persistKey=\"onboarding-v1\" persistType=\"local\">\n  <OnboardingTour />\n</ShowOnce>\n\n// Show once in memory (resets on page reload)\n<ShowOnce persist persistType=\"memory\">\n  <FirstTimeHint />\n</ShowOnce>\n```\n\n**Persistence types:**\n\n- `local` - Persists across browser sessions (localStorage)\n- `session` - Persists within current session (sessionStorage)\n- `memory` - Persists only in memory (resets on reload)\n\n---\n\n### Interaction Components\n\n#### `<CopyToClipboard>`\n\nCopy text to clipboard with automatic success/error handling.\n\n```jsx\nimport { CopyToClipboard } from 'meemaw';\n\n// Copy specific text\n<CopyToClipboard text=\"npm install meemaw\">\n  <button>Copy command</button>\n</CopyToClipboard>\n\n// Copy with callbacks\n<CopyToClipboard\n  text={code}\n  onSuccess={() => toast.success('Copied!')}\n  onError={(err) => toast.error(err.message)}\n>\n  <CopyButton />\n</CopyToClipboard>\n\n// Render function pattern with copy state\n<CopyToClipboard text={shareUrl}>\n  {(copy, copied) => (\n    <button onClick={copy}>\n      {copied ? 'Copied!' : 'Copy link'}\n    </button>\n  )}\n</CopyToClipboard>\n\n// Auto-extract text from children\n<CopyToClipboard>\n  <code>const greeting = \"Hello, World!\";</code>\n</CopyToClipboard>\n```\n\n#### `<Clamp>`\n\nTruncate text with optional expand/collapse functionality.\n\n```jsx\nimport { Clamp } from 'meemaw';\n\n// Clamp by character count\n<Clamp maxChar={100}>\n  {longText}\n</Clamp>\n\n// Clamp by line count\n<Clamp maxLines={3}>\n  <p>{article}</p>\n</Clamp>\n\n// Expandable with custom text\n<Clamp\n  maxChar={200}\n  expandable\n  expandText=\"Read more\"\n  collapseText=\"Show less\"\n  truncateEnd=\"...\"\n  onToggle={(isExpanded) => console.log('Expanded:', isExpanded)}\n>\n  {biography}\n</Clamp>\n```\n\n---\n\n## Real-World Examples\n\n### Loading States\n\n```jsx\nfunction UserDashboard() {\n  const { data, loading, error } = useQuery('/api/dashboard');\n\n  return (\n    <Loadable loading={loading} error={error} loadingComponent={<DashboardSkeleton />}>\n      <Switch>\n        <Case when={!data.posts.length}>\n          <EmptyState />\n        </Case>\n        <Case when={data.posts.length > 0}>\n          <Repeat each={data.posts}>{post => <PostCard key={post.id} post={post} />}</Repeat>\n        </Case>\n      </Switch>\n    </Loadable>\n  );\n}\n```\n\n### Responsive Navigation\n\n```jsx\nfunction Navigation() {\n  return (\n    <>\n      <Hidden on={['mobile', 'tablet']}>\n        <DesktopNav />\n      </Hidden>\n\n      <Hidden on=\"desktop\">\n        <MobileNav />\n      </Hidden>\n    </>\n  );\n}\n```\n\n### First-Time User Experience\n\n```jsx\nfunction App() {\n  return (\n    <div>\n      <ShowOnce persist persistKey=\"welcome-v2\" persistType=\"local\">\n        <WelcomeModal />\n      </ShowOnce>\n\n      <Delayed until={userDataLoaded}>\n        <MainContent />\n      </Delayed>\n    </div>\n  );\n}\n```\n\n### Role-Based Content\n\n```jsx\nfunction Dashboard({ user }) {\n  return (\n    <Switch>\n      <Case when={user.role === 'admin'}>\n        <AdminDashboard />\n      </Case>\n      <Case when={user.role === 'moderator'}>\n        <ModeratorDashboard />\n      </Case>\n      <Case when={user.role === 'user'}>\n        <UserDashboard />\n      </Case>\n      <Default>\n        <GuestView />\n      </Default>\n    </Switch>\n  );\n}\n```\n\n### Code Snippet with Copy\n\n```jsx\nfunction CodeBlock({ code, language }) {\n  return (\n    <div className=\"code-block\">\n      <CopyToClipboard text={code}>\n        {(copy, copied) => (\n          <button onClick={copy} className=\"copy-btn\">\n            {copied ? '✓ Copied' : 'Copy'}\n          </button>\n        )}\n      </CopyToClipboard>\n      <pre>\n        <code className={language}>{code}</code>\n      </pre>\n    </div>\n  );\n}\n```\n\n### Article Preview\n\n```jsx\nfunction ArticleCard({ article }) {\n  return (\n    <article>\n      <h2>{article.title}</h2>\n      <Clamp maxLines={3} expandable expandText=\"Read more\" collapseText=\"Show less\">\n        <p>{article.content}</p>\n      </Clamp>\n    </article>\n  );\n}\n```\n\n---\n\n## TypeScript Support\n\nAll components are written in TypeScript with full type definitions included.\n\n```tsx\nimport { Show, Repeat, ShowOnce, PersistenceType } from 'meemaw';\n\ninterface User {\n  id: number;\n  name: string;\n}\n\nconst users: User[] = [\n  /* ... */\n];\n\n<Repeat<User> each={users}>{(user, index) => <div key={user.id}>{user.name}</div>}</Repeat>;\n\nconst persistType: PersistenceType = 'local';\n<ShowOnce persist persistType={persistType}>\n  <Notification />\n</ShowOnce>;\n```\n\n---\n\n## Bundle Size\n\nMeemaw is optimized for minimal bundle impact:\n\n| Export                | Size (minified + gzipped) |\n| --------------------- | ------------------------- |\n| Full package          | ~7 KB                     |\n| Individual components | ~0.5-1.5 KB each          |\n\nCheck the current size: `npm run size`\n\nOnly import what you need - tree-shaking ensures you only ship the components you use.\n\n---\n\n## Browser Support\n\nMeemaw supports all modern browsers:\n\n- Chrome (last 2 versions)\n- Firefox (last 2 versions)\n- Safari (last 2 versions)\n- Edge (last 2 versions)\n\nFor older browsers, you may need to include appropriate polyfills.\n\n---\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Run tests\nnpm test\n\n# Run tests in watch mode\nnpm test:watch\n\n# Build the library\nnpm run build\n\n# Type check\nnpm run typecheck\n\n# Lint\nnpm run lint\n\n# Format code\nnpm run format\n```\n\n---\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add some amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n---\n\n## License\n\nMIT © [spiderocious](https://github.com/spiderocious)\n\n---\n\n## Links\n\n- [npm Package](https://www.npmjs.com/package/meemaw)\n- [GitHub Repository](https://github.com/spiderocious/meemaw)\n- [Issue Tracker](https://github.com/spiderocious/meemaw/issues)\n\n---\n\n<div align=\"center\">\n\n**Made with ❤️ for the React community**\n\nIf you find this library useful, please consider giving it a star on GitHub!\n\n</div>\n","readmeFilename":"README.md"}