onClick(color) }/>
7 |
8 |
28 |
29 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/router-complex/app-navi.riot:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 | { link.name }
7 |
8 |
9 |
10 |
30 |
31 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/deno/index.ts:
--------------------------------------------------------------------------------
1 | import { Application } from 'https://deno.land/x/oak@v17.1.6/mod.ts'
2 | import { template } from 'https://cdn.pika.dev/lodash-es'
3 | import { renderAsyncFragments } from '@riotjs/ssr'
4 | import RootComponent from './public/app.js'
5 | import routes from './src/routes.ts'
6 | import { toRegexp, match } from '@riotjs/route'
7 |
8 | const app = new Application()
9 | const page = await Deno.readTextFile('./index.html')
10 | const pages = Object.values(routes)
11 |
12 | app.use(async (ctx, next) => {
13 | // quick test to identify static assets
14 | if (ctx.request.url.pathname.includes('.')) return next()
15 |
16 | // generate the initial state
17 | const initialState = {
18 | initialRoute: ctx.request.url.pathname,
19 | base: ctx.request.url.origin,
20 | routes,
21 | }
22 |
23 | // generate the rendered html + css
24 | const { html, css } = await renderAsyncFragments(
25 | 'app',
26 | RootComponent,
27 | initialState,
28 | )
29 |
30 | // send 404 if the current path doesn't match any of the routes
31 | if (
32 | !pages.some((page) => match(initialState.initialRoute, toRegexp(page.path)))
33 | ) {
34 | ctx.response.status = 404
35 | }
36 |
37 | // render the body
38 | ctx.response.body = template(page)({
39 | html,
40 | css,
41 | initialState: JSON.stringify(initialState),
42 | })
43 | })
44 |
45 | app.use(async (context, next) => {
46 | try {
47 | await context.send({
48 | root: `${Deno.cwd()}/`,
49 | index: 'index.html',
50 | })
51 | } catch {
52 | next()
53 | }
54 | })
55 |
56 | console.log('App running on: http://localhost:3000')
57 |
58 | await app.listen({ port: 3000 })
59 |
--------------------------------------------------------------------------------
/router-page-switcher/app.riot:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | { page.title }
6 |
7 |
8 |
9 |
10 | {getPageById(route).title}
11 | {getPageById(route).body}
12 |
13 |
14 |
39 |
40 |
62 |
63 |
--------------------------------------------------------------------------------
/plunker/app.riot:
--------------------------------------------------------------------------------
1 |
2 | Now opening Plunker...
3 |
4 |
14 |
15 |
50 |
51 |
64 |
65 |
--------------------------------------------------------------------------------
/live-editor/live-editor.riot:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
47 |
48 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/router-complex/app-main.riot:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
15 | { page.title }
16 | { page.body }
17 |
18 |
19 |
20 |
21 | {getSubPageDataById(route).title}
22 | {getSubPageDataById(route).body}
23 |
24 |
25 |
26 |
27 |
54 |
55 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/ssr/app/app.riot:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {page.label}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
74 |
75 |
92 |
93 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [![Build Status][travis-image]][travis-url] [![MIT License][license-image]][license-url]
2 |
3 | # Riot Examples
4 |
5 | This is a series of examples designed to showcase the benefits of adopting [Riot](https://riot.js.org). It is made possible by the Riot open source community.
6 |
7 | **Note**: The Riot.js 3 examples are available [here](https://github.com/riot/examples/tree/v3) .
8 |
9 | We have several examples to choose from; each one demonstrates different aspects of Riot:
10 |
11 | ## Basics
12 |
13 | | Example | | |
14 | | :----------------------- | :--------------------------------- | :------------------------------------------------------------------------- |
15 | | Timer | [Source](timer) | [Demo](https://riot.js.org/examples/plunker/?app=timer) |
16 | | Todo | [Source](todo-app) | [Demo](https://riot.js.org/examples/plunker/?app=todo-app) |
17 | | Todo (pre-compiled) | [Source](todo-app-precompiled) | [Demo](https://riot.js.org/examples/todo-app-precompiled/) |
18 | | Color Palette | [Source](color-palette) | [Demo](https://riot.js.org/examples/plunker/?app=color-palette) |
19 | | Hooks | [Source](hooks) | [Demo](https://riot.js.org/examples/plunker/?app=hooks) |
20 | | Router - Page switcher | [Source](router-page-switcher) | [Demo](https://riot.js.org/examples/plunker/?app=router-page-switcher) |
21 | | Animated list reordering | [Source](animated-list-reordering) | [Demo](https://riot.js.org/examples/plunker/?app=animated-list-reordering) |
22 | | Simple modal | [Source](modal) | [Demo](https://riot.js.org/examples/plunker/?app=modal) |
23 | | Live Ajax Search | [Source](live-ajax-search) | [Demo](https://riot.js.org/examples/plunker/?app=live-ajax-search) |
24 |
25 | ## Advanced
26 |
27 | | Example | | |
28 | | :------------------- | :--------------------------- | :--------------------------------------------------------------- |
29 | | TypeScript | [Source](typescript) |
30 | | Router - Complex | [Source](router-complex) | [Demo](https://riot.js.org/examples/plunker/?app=router-complex) |
31 | | Router - History API | [Source](router-history-api) |
32 | | Router - Lazy Routes | [Source](lazy-routes) |
33 | | SSR | [Source](ssr) |
34 | | Deno | [Source](deno) |
35 |
36 | ## Contribute
37 |
38 | If you have an example that you think others could benefit from and you'd like to share it please read the [contributing guidelines](CONTRIBUTING.md) and submit a PR.
39 |
40 | ## Bugs
41 |
42 | If you find something that isn't expected please [create an issue](https://github.com/riot/examples/issues) and we'll get on it. To make it easier to debug please use the [Bug Reporter](https://riot.js.org/examples/plunker/?app=bug-reporter).
43 |
44 | [travis-image]: https://img.shields.io/travis/riot/examples.svg?style=flat-square
45 | [travis-url]: https://travis-ci.org/riot/examples
46 | [license-image]: http://img.shields.io/badge/license-MIT-000000.svg?style=flat-square
47 | [license-url]: LICENSE
48 |
--------------------------------------------------------------------------------
/live-ajax-search/search.riot:
--------------------------------------------------------------------------------
1 |
2 |
3 | Search a movie
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | { state.error }
12 |
13 |
19 |
20 |
65 |
66 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/animated-list-reordering/list.riot:
--------------------------------------------------------------------------------
1 |
2 | Sorting options
3 |
4 | Shuffle
5 |
6 | sortBy('age') }>
7 | Sort by age
8 |
9 | sortBy('name') }>
10 | Sort by Name
11 |
12 |
13 | Add person
14 |
15 |
16 | People Collection
17 |
18 |
19 |
20 | { person.name } - { person.age }
21 |
22 | remove(person.id) }>
23 | Remove person
24 |
25 |
26 |
27 |
28 |
118 |
119 |
175 |
176 |
--------------------------------------------------------------------------------
/deno/src/app.riot:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {page.label}
6 |
7 |
8 |
9 |
10 |
11 | 🚀
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
95 |
96 |
169 |
170 |
--------------------------------------------------------------------------------
/todo-app-precompiled/todo.js:
--------------------------------------------------------------------------------
1 | var todo = {
2 | css: null,
3 | exports: {
4 | onBeforeMount(props, state) {
5 | // initial state
6 | this.state = {
7 | items: props.items,
8 | text: '',
9 | }
10 | },
11 |
12 | edit(e) {
13 | // update only the text state
14 | this.update({
15 | text: e.target.value,
16 | })
17 | },
18 |
19 | add(e) {
20 | e.preventDefault()
21 |
22 | if (this.state.text) {
23 | this.update({
24 | items: [
25 | ...this.state.items, // add a new item
26 | {
27 | title: this.state.text,
28 | },
29 | ],
30 | text: '',
31 | })
32 | }
33 | },
34 |
35 | toggle(item) {
36 | item.done = !item.done // trigger a component update
37 |
38 | this.update()
39 | },
40 | },
41 | template: function (template, expressionTypes, bindingTypes, getComponent) {
42 | return template(
43 | '
',
44 | [
45 | {
46 | redundantAttribute: 'expr0',
47 | selector: '[expr0]',
48 | expressions: [
49 | {
50 | type: expressionTypes.TEXT,
51 | childNodeIndex: 0,
52 | evaluate: function (_scope) {
53 | return _scope.props.title
54 | },
55 | },
56 | ],
57 | },
58 | {
59 | type: bindingTypes.EACH,
60 | getKey: null,
61 | condition: null,
62 | template: template(
63 | '
',
64 | [
65 | {
66 | expressions: [
67 | {
68 | type: expressionTypes.ATTRIBUTE,
69 | name: 'hidden',
70 | evaluate: function (_scope) {
71 | return _scope.item.hidden
72 | },
73 | },
74 | ],
75 | },
76 | {
77 | redundantAttribute: 'expr2',
78 | selector: '[expr2]',
79 | expressions: [
80 | {
81 | type: expressionTypes.TEXT,
82 | childNodeIndex: 1,
83 | evaluate: function (_scope) {
84 | return [_scope.item.title].join('')
85 | },
86 | },
87 | {
88 | type: expressionTypes.ATTRIBUTE,
89 | name: 'class',
90 | evaluate: function (_scope) {
91 | return _scope.item.done ? 'completed' : null
92 | },
93 | },
94 | ],
95 | },
96 | {
97 | redundantAttribute: 'expr3',
98 | selector: '[expr3]',
99 | expressions: [
100 | {
101 | type: expressionTypes.ATTRIBUTE,
102 | name: 'checked',
103 | evaluate: function (_scope) {
104 | return _scope.item.done
105 | },
106 | },
107 | {
108 | type: expressionTypes.EVENT,
109 | name: 'onclick',
110 | evaluate: function (_scope) {
111 | return () => _scope.toggle(_scope.item)
112 | },
113 | },
114 | ],
115 | },
116 | ],
117 | ),
118 | redundantAttribute: 'expr1',
119 | selector: '[expr1]',
120 | itemName: 'item',
121 | indexName: null,
122 | evaluate: function (_scope) {
123 | return _scope.state.items
124 | },
125 | },
126 | {
127 | redundantAttribute: 'expr4',
128 | selector: '[expr4]',
129 | expressions: [
130 | {
131 | type: expressionTypes.EVENT,
132 | name: 'onsubmit',
133 | evaluate: function (_scope) {
134 | return _scope.add
135 | },
136 | },
137 | ],
138 | },
139 | {
140 | redundantAttribute: 'expr5',
141 | selector: '[expr5]',
142 | expressions: [
143 | {
144 | type: expressionTypes.EVENT,
145 | name: 'onkeyup',
146 | evaluate: function (_scope) {
147 | return _scope.edit
148 | },
149 | },
150 | ],
151 | },
152 | {
153 | redundantAttribute: 'expr6',
154 | selector: '[expr6]',
155 | expressions: [
156 | {
157 | type: expressionTypes.TEXT,
158 | childNodeIndex: 0,
159 | evaluate: function (_scope) {
160 | return ['Add #', _scope.state.items.length + 1].join('')
161 | },
162 | },
163 | {
164 | type: expressionTypes.ATTRIBUTE,
165 | name: 'disabled',
166 | evaluate: function (_scope) {
167 | return !_scope.state.text
168 | },
169 | },
170 | ],
171 | },
172 | ],
173 | )
174 | },
175 | name: 'todo',
176 | }
177 |
178 | export default todo
179 |
--------------------------------------------------------------------------------
/deno/deno.lock:
--------------------------------------------------------------------------------
1 | {
2 | "version": "5",
3 | "specifiers": {
4 | "jsr:@oak/commons@1": "1.0.1",
5 | "jsr:@std/assert@1": "1.0.14",
6 | "jsr:@std/bytes@1": "1.0.6",
7 | "jsr:@std/crypto@1": "1.0.5",
8 | "jsr:@std/encoding@1": "1.0.10",
9 | "jsr:@std/encoding@^1.0.10": "1.0.10",
10 | "jsr:@std/http@1": "1.0.20",
11 | "jsr:@std/internal@^1.0.10": "1.0.10",
12 | "jsr:@std/media-types@1": "1.1.0",
13 | "jsr:@std/path@1": "1.1.2"
14 | },
15 | "jsr": {
16 | "@oak/commons@1.0.1": {
17 | "integrity": "889ff210f0b4292591721be07244ecb1b5c118742f5273c70cf30d7cd4184d0c",
18 | "dependencies": [
19 | "jsr:@std/assert",
20 | "jsr:@std/bytes",
21 | "jsr:@std/crypto",
22 | "jsr:@std/encoding@1",
23 | "jsr:@std/http",
24 | "jsr:@std/media-types"
25 | ]
26 | },
27 | "@std/assert@1.0.14": {
28 | "integrity": "68d0d4a43b365abc927f45a9b85c639ea18a9fab96ad92281e493e4ed84abaa4"
29 | },
30 | "@std/bytes@1.0.6": {
31 | "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a"
32 | },
33 | "@std/crypto@1.0.5": {
34 | "integrity": "0dcfbb319fe0bba1bd3af904ceb4f948cde1b92979ec1614528380ed308a3b40"
35 | },
36 | "@std/encoding@1.0.10": {
37 | "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1"
38 | },
39 | "@std/http@1.0.20": {
40 | "integrity": "b5cc33fc001bccce65ed4c51815668c9891c69ccd908295997e983d8f56070a1",
41 | "dependencies": [
42 | "jsr:@std/encoding@^1.0.10"
43 | ]
44 | },
45 | "@std/internal@1.0.10": {
46 | "integrity": "e3be62ce42cab0e177c27698e5d9800122f67b766a0bea6ca4867886cbde8cf7"
47 | },
48 | "@std/media-types@1.1.0": {
49 | "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4"
50 | },
51 | "@std/path@1.1.2": {
52 | "integrity": "c0b13b97dfe06546d5e16bf3966b1cadf92e1cc83e56ba5476ad8b498d9e3038",
53 | "dependencies": [
54 | "jsr:@std/internal"
55 | ]
56 | }
57 | },
58 | "redirects": {
59 | "https://cdn.pika.dev/lodash-es": "https://cdn.skypack.dev/lodash-es"
60 | },
61 | "remote": {
62 | "https://cdn.skypack.dev/-/lodash-es@v4.17.21-Toh2DxDo3SDNcOZcXzc1/dist=es2019,mode=imports/optimized/lodash-es.js": "4a1b35d34b5e0d3ae68aa46ddaabb9700ccecb75b830974db7c46a271f10daa8",
63 | "https://cdn.skypack.dev/lodash-es": "d59c89cfa22b7512b8da88fda322bad35a6a40f2fb6ba7c2c0295105e393451b",
64 | "https://deno.land/x/oak@v17.1.6/application.ts": "69fb6462eed013562ee61239e60ea77e5df3abb2b0df34568593b9774d72e98f",
65 | "https://deno.land/x/oak@v17.1.6/body.ts": "f91d8e0298abbabe6acb543d1090e2a41aa665375918a575d72bd6b98b538e40",
66 | "https://deno.land/x/oak@v17.1.6/context.ts": "e04c3d67d68ee01a279aeded457b0d66255450593dacab22251e7eb0cf6a92e5",
67 | "https://deno.land/x/oak@v17.1.6/deps.ts": "c71a9421d2ead7803468cd40559cf122ee91d4e81e8a3a98706956f6654e2550",
68 | "https://deno.land/x/oak@v17.1.6/http_server_bun.ts": "c7f3eb6464d4f047fcc9335e632ffb6bfc24e5ef7dc9a53017a6e453d4197e4b",
69 | "https://deno.land/x/oak@v17.1.6/http_server_native.ts": "34bab402cc9b6fdf53706699ac2c2ab88faf5c14be2ae18aa105bdc4fd6a8471",
70 | "https://deno.land/x/oak@v17.1.6/http_server_native_request.ts": "aa98a2f4bbf6f7651c62eb0332a95a1b0faff1d76f7a07fa8bd600766eb24488",
71 | "https://deno.land/x/oak@v17.1.6/http_server_node.ts": "bfbf7585fcda5a1464cd0f904ec97cbb4d67367757f3ed8cdc99a590a94b34e1",
72 | "https://deno.land/x/oak@v17.1.6/middleware.ts": "a701caf9d872b93d26759f77c7ad545cb29bc3d197c8375b79b2fbe7e9e60958",
73 | "https://deno.land/x/oak@v17.1.6/middleware/etag.ts": "f5cf8eb2a7c99ae7e11a4e31dc60beda398aec7a08be343e0de6b632f8064e4d",
74 | "https://deno.land/x/oak@v17.1.6/middleware/proxy.ts": "e611b7d45f58a1b2caa1cb6c435774822d7b56aa136b8dbb8691fb52d07c5182",
75 | "https://deno.land/x/oak@v17.1.6/middleware/serve.ts": "66f1e405ac006bfa863e8852092e03951b93dd4ba8381996a719d93d00aa62fe",
76 | "https://deno.land/x/oak@v17.1.6/mod.ts": "1f42341a6138310eceaf7b8e9b72be4d2a913817d1e823090dee4e7d27c68e98",
77 | "https://deno.land/x/oak@v17.1.6/node_shims.ts": "e411aef698dca26dfc577d8581ddab678f528bd52bf681337f3c3bcc73845a0a",
78 | "https://deno.land/x/oak@v17.1.6/request.ts": "eb3cdbb761c04ffc82267b6104c7534662d265054ed3d16b25078dbd00654005",
79 | "https://deno.land/x/oak@v17.1.6/response.ts": "483f8ddd7618325e6ac28f88a3ea9926a09b3c90fa53b481a7a5202d23a0755f",
80 | "https://deno.land/x/oak@v17.1.6/router.ts": "e8eb2f88806dfdd303f3a663fefb7d9e614342bf40738692e9ef4b2243e1bccd",
81 | "https://deno.land/x/oak@v17.1.6/send.ts": "42faed583f218ed85d5da7704f36b385537947ec4de6125e20ad8acbfe8d8f68",
82 | "https://deno.land/x/oak@v17.1.6/testing.ts": "d6489e78d689da08b9896cd0b9b9add243466b407ce6fd63d38e29f8c0a19f5c",
83 | "https://deno.land/x/oak@v17.1.6/types.ts": "0e74c6c46e0fcfddd87e90fe0216c4ae50c73b113e06d3bdc4283afc7b2570d6",
84 | "https://deno.land/x/oak@v17.1.6/utils/clone_state.ts": "5a0784d802b86cc3dbf415dfd286025f03a261b3a8f9b3b6fd671be8e51ff027",
85 | "https://deno.land/x/oak@v17.1.6/utils/consts.ts": "9e14324837558d7af3d4bfc8ba5f13216a0b5d2f8dac14a3a782bc1bbfb756ef",
86 | "https://deno.land/x/oak@v17.1.6/utils/create_promise_with_resolvers.ts": "f7eeaf65ffa7b6cef03b8dc3fa3a3e35ae5553c6abf1a2260d7797e076acd63a",
87 | "https://deno.land/x/oak@v17.1.6/utils/decode.ts": "434802a09534a26cc8b8cd009ecc422b4695d22859021fe34f8093784b2483b7",
88 | "https://deno.land/x/oak@v17.1.6/utils/decode_component.ts": "d68e6da33bf6e733d218c0b7ce7112520640e836f4cfa2760c4aee8facf1c581",
89 | "https://deno.land/x/oak@v17.1.6/utils/encode_url.ts": "16b213d70f5e211fb3633f97c704f9613d2f8033669d59e0c9ca4fc26551fad6",
90 | "https://deno.land/x/oak@v17.1.6/utils/resolve_path.ts": "aa39d54a003b38fee55f340a0cba3f93a7af85b8ddd5fbfb049a98fc0109b36d",
91 | "https://deno.land/x/oak@v17.1.6/utils/streams.ts": "c85ae197f5046d58d5a3e42221254a6c8e63172f9f01b77631e480e1dcc90e05",
92 | "https://deno.land/x/oak@v17.1.6/utils/type_guards.ts": "766b94850c9058a41ad8beac5b6df5a55cd5445bf77a356b520b6cb47f488697"
93 | },
94 | "workspace": {
95 | "packageJson": {
96 | "dependencies": [
97 | "npm:@riotjs/cli@10",
98 | "npm:@riotjs/compiler@10",
99 | "npm:@riotjs/hydrate@10",
100 | "npm:@riotjs/route@10",
101 | "npm:@riotjs/ssr@10",
102 | "npm:@rollup/plugin-commonjs@^28.0.6",
103 | "npm:@rollup/plugin-node-resolve@^16.0.1",
104 | "npm:@rollup/plugin-typescript@^12.1.4",
105 | "npm:erre@^3.0.1",
106 | "npm:riot@10",
107 | "npm:rollup-plugin-riot@10"
108 | ]
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------