[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-72631":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":20,"hasPages":20,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":23,"readmeContent":24,"aiSummary":25,"trendingCount":16,"starSnapshotCount":16,"syncStatus":26,"lastSyncTime":27,"discoverSource":28},72631,"ripple","Ripple-TS\u002Fripple","Ripple-TS","the elegant TypeScript UI framework","https:\u002F\u002Fripple-ts.com",null,"JavaScript",7378,288,29,30,0,41,38.38,"MIT License",false,"main",[],"2026-06-12 02:03:05","\u003Ca href=\"https:\u002F\u002Fripplejs.com\">\n  \u003Cpicture>\n    \u003Csource media=\"(min-width: 768px)\" srcset=\"assets\u002Fripple-desktop.png\">\n    \u003Cimg src=\"assets\u002Fripple-mobile.png\" alt=\"Ripple - the elegant TypeScript UI framework\" \u002F>\n  \u003C\u002Fpicture>\n\u003C\u002Fa>\n\n[![CI](https:\u002F\u002Fgithub.com\u002FRipple-TS\u002Fripple\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002FRipple-TS\u002Fripple\u002Factions\u002Fworkflows\u002Fci.yml)\n[![Discord](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDiscord-Join%20Server-7289da?logo=discord&logoColor=white)](https:\u002F\u002Fdiscord.gg\u002FJBF2ySrh2W)\n[![Open in StackBlitz](https:\u002F\u002Fdeveloper.stackblitz.com\u002Fimg\u002Fopen_in_stackblitz_small.svg)](https:\u002F\u002Fstackblitz.com\u002Fgithub\u002FRipple-TS\u002Fripple\u002Ftree\u002Fmain\u002Ftemplates\u002Fbasic)\n\n# Ripple TS\n\nRipple is a TypeScript UI framework that combines the best parts of React, Solid,\nand Svelte. Created by [@trueadm](https:\u002F\u002Fgithub.com\u002Ftrueadm), who has contributed\nto [Inferno](https:\u002F\u002Fgithub.com\u002Finfernojs\u002Finferno),\n[React](https:\u002F\u002Fgithub.com\u002Ffacebook\u002Freact),\n[Lexical](https:\u002F\u002Fgithub.com\u002Ffacebook\u002Flexical), and\n[Svelte 5](https:\u002F\u002Fgithub.com\u002Fsveltejs\u002Fsvelte).\n\n**Key Philosophy:** Ripple is TS-first with `.tsrx` as its default component file\nextension. This allows seamless TypeScript integration and a unique syntax that\nenhances both human and LLM developer experience.\n\n> **`.tsrx` is also a standalone language:** the same source can now compile to\n> React, Solid, or Ripple via [TSRX](https:\u002F\u002Ftsrx.dev) — a TypeScript language\n> extension that treats Ripple as one of several target runtimes. If you want the\n> authoring ergonomics without committing to Ripple's runtime, start there.\n\n📚 **[Ripple Docs](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs)** | 🎮\n**[Ripple Playground](https:\u002F\u002Fwww.ripple-ts.com\u002Fplayground)** | 🧩\n**[TSRX Website](https:\u002F\u002Ftsrx.dev)**\n\n## Features\n\n- ⚡ **Fine-grained Reactivity**: `track` with lazy destructuring for a unique\n  reactivity system\n- 🔥 **Performance**: Industry-leading rendering speed, bundle size, and memory\n  usage\n- 📦 **Reactive Collections**: `RippleArray`, `RippleObject`, `RippleMap`,\n  `RippleSet` imported from `'ripple'` with full reactivity\n- 🎯 **TypeScript First**: Complete type safety with the default `.tsrx` component\n  extension\n- 🛠️ **Developer Tools**: VSCode extension, Prettier, and ESLint support\n- 🎨 **Scoped Styling**: Component-level CSS with automatic scoping\n\n## 🚀 Quick Start\n\n### Using CLI (Recommended)\n\n```bash\nnpx create-ripple\ncd my-app\nnpm install && npm run dev\n```\n\n### Using Template\n\n```bash\nnpx degit Ripple-TS\u002Fripple\u002Ftemplates\u002Fbasic my-app\ncd my-app\nnpm install && npm run dev\n```\n\n### Add to Existing Project\n\n```bash\nnpm install ripple @ripple-ts\u002Fvite-plugin\n```\n\n> **Note:** You can use `npm`, `pnpm`, `yarn`, or `bun` package managers.\n\n**[→ Full Installation Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fquick-start)**\n\n### Mounting Your App\n\n```ts\n\u002F\u002F index.ts\nimport { mount } from 'ripple';\nimport { App } from '.\u002FApp.tsrx';\n\nmount(App, {\n  props: { title: 'Hello world!' },\n  target: document.getElementById('root'),\n});\n```\n\n## 🔧 VSCode Extension\n\nInstall the\n[Ripple VSCode extension](https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=Ripple-TS.ripple-ts-vscode-plugin)\nfor:\n\n- Syntax highlighting\n- TypeScript integration\n- Real-time diagnostics\n- IntelliSense autocomplete\n\n**[→ Editor Setup Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fquick-start#vs-code)**\n\n## Core Concepts\n\n### Components\n\nDefine components with the `component` keyword. Unlike React, you don't return\nJSX—you write it directly:\n\n```jsx\ncomponent Button(props: { text: string, onClick: () => void }) {\n  \u003Cbutton onClick={props.onClick}>\n    {props.text}\n  \u003C\u002Fbutton>\n}\n\nexport component App() {\n  \u003CButton text=\"Click me\" onClick={() => console.log(\"Clicked!\")} \u002F>\n}\n```\n\n**[→ Component Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fguide\u002Fcomponents)**\n\n### Reactivity\n\nCreate reactive state with `track` and use lazy destructuring (`&[]`) to access\nthe value directly:\n\n```jsx\nimport { track } from 'ripple';\n\nexport component App() {\n  let &[count] = track(0);\n\n  \u003Cdiv>\n    \u003Cp>\"Count: \"{count}\u003C\u002Fp>\n    \u003Cbutton onClick={() => count++}>\"Increment\"\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n}\n```\n\nYou can also pass around the tracked value object from the second argument:\n\n```jsx\nimport { track } from 'ripple';\n\nexport component App() {\n  let &[count, trackedCount] = track(0);\n\n  \u003Cdiv>{count}\u003C\u002Fdiv>\n  \u003CIncrementButton {trackedCount} \u002F>\n}\n```\n\nAlternatively, you can read and write tracked values directly using the `.value`\nproperty on the `Tracked\u003CV>` object:\n\n```jsx\nimport { track } from 'ripple';\n\nexport component App() {\n  const count = track(0);\n\n  \u003Cdiv>{count.value}\u003C\u002Fdiv>\n  \u003Cbutton onClick={() => count.value++}>\"Increment\"\u003C\u002Fbutton>\n}\n```\n\nUsing `&[...]` is preferred in most cases for cleaner code, but `.value` is useful\nwhen you need to keep the `Tracked\u003CV>` object around — for example, when storing\ntracked values in data structures or passing them as `Tracked\u003CT>` props.\n\n**Derived values** automatically update:\n\n```jsx\nimport { track } from 'ripple';\n\nexport component App() {\n  let &[count] = track(0);\n  let &[double] = track(() => count * 2);\n  let &[quadruple] = track(() => double * 2);\n\n  \u003Cdiv>\n    \u003Cp>\"Count: \"{count}\u003C\u002Fp>\n    \u003Cp>\"Double: \"{double}\u003C\u002Fp>\n    \u003Cp>\"Quadruple: \"{quadruple}\u003C\u002Fp>\n    \u003Cbutton onClick={() => count++}>\"Increment\"\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n}\n```\n\n**Reactive collections** with full reactivity:\n\n```jsx\nimport { RippleArray, RippleObject, RippleMap, RippleSet } from 'ripple';\n\nexport component App() {\n  const items = new RippleArray(1, 2, 3);          \u002F\u002F RippleArray\n  const obj = new RippleObject({ a: 1, b: 2 });    \u002F\u002F RippleObject\n  const map = new RippleMap([['k', 'v']]);          \u002F\u002F RippleMap\n  const set = new RippleSet([1, 2, 3]);             \u002F\u002F RippleSet\n\n  \u003Cdiv>\n    \u003Cp>\"Items: \"{items.join(', ')}\u003C\u002Fp>\n    \u003Cp>\"Object: a=\"{obj.a}\", b=\"{obj.b}\", c=\"{obj.c}\u003C\u002Fp>\n    \u003Cbutton onClick={() => items.push(items.length + 1)}>\"Add Item\"\u003C\u002Fbutton>\n    \u003Cbutton onClick={() => obj.c = (obj.c ?? 0) + 1}>\"Increment c\"\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n}\n```\n\n**[→ Reactivity Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fguide\u002Freactivity)**\n\n### Transporting Reactivity\n\nPass the tracked ref (second element) across function boundaries:\n\n```jsx\nimport { track } from 'ripple';\n\nfunction createDouble(&[count]) {\n  return track(() => count * 2);\n}\n\nexport component App() {\n  let &[count, countTracked] = track(0);\n  const &[double] = createDouble(countTracked);\n\n  \u003Cdiv>\n    \u003Cp>\"Double: \"{double}\u003C\u002Fp>\n    \u003Cbutton onClick={() => count++}>\"Increment\"\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n}\n```\n\n**[→ Transporting Reactivity Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fguide\u002Freactivity#transporting-reactivity)**\n\n### Effects & Side Effects\n\n```jsx\nimport { track, effect } from 'ripple';\n\nexport component App() {\n  let &[count] = track(0);\n\n  effect(() => {\n    console.log('Count changed:', count);\n  });\n\n  \u003Cbutton onClick={() => count++}>\"Increment\"\u003C\u002Fbutton>\n}\n```\n\n**[→ Effects & Reactivity Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fguide\u002Freactivity#effects)**\n\n### Control Flow\n\n**Conditionals:**\n\n```jsx\nimport { track } from 'ripple';\n\nexport component App() {\n  let &[condition] = track(true);\n\n  \u003Cdiv>\n    if (condition) {\n      \u003Cdiv>\"True\"\u003C\u002Fdiv>\n    } else {\n      \u003Cdiv>\"False\"\u003C\u002Fdiv>\n    }\n    \u003Cbutton onClick={() => condition = !condition}>\"Toggle\"\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n}\n```\n\n**Loops:**\n\n```jsx\nimport { RippleArray } from 'ripple';\n\nexport component App() {\n  const items = new RippleArray(\n    {id: 1, name: 'Item 1'},\n    {id: 2, name: 'Item 2'},\n    {id: 3, name: 'Item 3'}\n  );\n\n  \u003Cdiv>\n    for (const item of items; index i; key item.id) {\n      \u003Cdiv>{item.name}\" (index: \"{i}\")\"\u003C\u002Fdiv>\n    }\n    \u003Cbutton onClick={() => items.push({id: items.length + 1, name: `Item ${items.length + 1}`})}>\"Add Item\"\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n}\n```\n\n**Error Boundaries:**\n\n```jsx\ncomponent ComponentThatMayFail(props: { shouldFail: boolean }) {\n  if (props.shouldFail) {\n    throw new Error('Component failed!');\n    \"This will never render\"\n  }\n\n  \u003Cdiv>\"Component working fine\"\u003C\u002Fdiv>\n}\n\nimport { track } from 'ripple';\n\nexport component App() {\n  let &[shouldFail] = track(false);\n\n  \u003Cdiv>\n    try {\n      \u003CComponentThatMayFail {shouldFail} \u002F>\n    } catch (e) {\n      \u003Cdiv>\"Error: \"{e.message}\u003C\u002Fdiv>\n    }\n    \u003Cbutton onClick={() => shouldFail = !shouldFail}>\"Toggle Error\"\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n}\n```\n\n**[→ Control Flow Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fguide\u002Fcontrol-flow)**\n\n### DOM Refs\n\nCapture DOM elements with the `{ref fn}` syntax:\n\n```jsx\nexport component App() {\n  \u003Cdiv {ref (node) => console.log(node)}>\"Hello\"\u003C\u002Fdiv>\n}\n```\n\n**[→ DOM Refs Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fguide\u002Fdom-refs)**\n\n### Events\n\nUse React-style event handlers:\n\n```jsx\nimport { track } from 'ripple';\n\nexport component App() {\n  let &[value] = track('');\n\n  \u003Cdiv>\n    \u003Cbutton onClick={() => console.log('Clicked')}>\"Click\"\u003C\u002Fbutton>\n    \u003Cinput onInput={(e) => value = e.target.value} \u002F>\n    \u003Cp>\"You typed: \"{value}\u003C\u002Fp>\n  \u003C\u002Fdiv>\n}\n```\n\n**[→ Events Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fguide\u002Fevents)**\n\n### Styling\n\n**Scoped CSS:**\n\n```jsx\nexport component App() {\n  \u003Cdiv class=\"container\">\"Content\"\u003C\u002Fdiv>\n\n  \u003Cstyle>\n    .container {\n      padding: 1rem;\n      background: lightblue;\n      border-radius: 8px;\n    }\n  \u003C\u002Fstyle>\n}\n```\n\n**Dynamic styles:**\n\n```jsx\nimport { track } from 'ripple';\n\nexport component App() {\n  let &[color] = track('red');\n\n  \u003Cdiv>\n    \u003Cdiv style={{ color, fontWeight: 'bold' }}>\"Styled text\"\u003C\u002Fdiv>\n    \u003Cbutton onClick={() => color = color === 'red' ? 'blue' : 'red'}>\"Toggle Color\"\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n}\n```\n\n**[→ Styling Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fguide\u002Fstyling)**\n\n## Advanced Features\n\n### Context API\n\nShare state across the component tree:\n\n```jsx\nimport { Context, track } from 'ripple';\n\nconst ThemeContext = new Context();\n\ncomponent Child() {\n  const &[theme] = ThemeContext.get();\n  \u003Cdiv>\"Theme: \"{theme}\u003C\u002Fdiv>\n}\n\nexport component App() {\n  let &[theme, themeTracked] = track('light');\n\n  ThemeContext.set(themeTracked);\n\n  \u003Cdiv>\n    \u003CChild \u002F>\n    \u003Cbutton onClick={() => theme = theme === 'light' ? 'dark' : 'light'}>\"Toggle Theme\"\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n}\n```\n\n**[→ State Management Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fguide\u002Fstate-management#context)**\n\n### Portals\n\nRender content outside the component hierarchy:\n\n```jsx\nimport { Portal, track } from 'ripple';\n\nexport component App() {\n  let &[showModal] = track(false);\n\n  \u003Cdiv>\n    \u003Cbutton onClick={() => showModal = !showModal}>\"Toggle Modal\"\u003C\u002Fbutton>\n\n    if (showModal) {\n      \u003CPortal target={document.body}>\n        \u003Cdiv class=\"modal\">\n          \u003Cp>\"Modal content\"\u003C\u002Fp>\n          \u003Cbutton onClick={() => showModal = false}>\"Close\"\u003C\u002Fbutton>\n        \u003C\u002Fdiv>\n      \u003C\u002FPortal>\n    }\n  \u003C\u002Fdiv>\n}\n```\n\n**[→ Portal & Component Guide](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs\u002Fguide\u002Fcomponents#portal-component)**\n\n## Resources\n\n- 📚 **[Full Documentation](https:\u002F\u002Fwww.ripple-ts.com\u002Fdocs)** - Complete guide and\n  API reference\n- 🎮 **[Interactive Playground](https:\u002F\u002Fwww.ripple-ts.com\u002Fplayground)** - Try\n  Ripple in your browser\n- 🧩 **[TSRX Website](https:\u002F\u002Ftsrx.dev)** - Author `.tsrx` once, compile to React,\n  Solid, or Ripple\n- 🐛 **[GitHub Issues](https:\u002F\u002Fgithub.com\u002FRipple-TS\u002Fripple\u002Fissues)** - Report bugs\n  or request features\n- 💬 **[Discord Community](https:\u002F\u002Fdiscord.gg\u002FJBF2ySrh2W)** - Get help and discuss\n  Ripple\n- 📦 **[npm Package](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fripple)** - Install from npm\n\n## Contributing\n\nContributions are welcome! Please see our\n[contributing guidelines](CONTRIBUTING.md).\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n","Ripple 是一个优雅的 TypeScript UI 框架，结合了 React、Solid 和 Svelte 的优点。其核心功能包括细粒度的响应式系统、行业领先的渲染速度和内存使用效率、以及完全类型安全的 `.tsrx` 组件扩展。Ripple 提供了全面的开发工具支持，如 VSCode 扩展、Prettier 和 ESLint，并支持组件级 CSS 自动作用域。适用于需要高性能和良好开发体验的前端项目，特别是对 TypeScript 有较高要求的应用场景。",2,"2026-06-11 03:42:52","high_star"]