diff --git a/README.md b/README.md index 3f2c24a..d2566a0 100644 --- a/README.md +++ b/README.md @@ -14,3 +14,5 @@ 12. [Специальные элементы (Special elements)](https://youtu.be/axGxAHwbYYg) 👉 [Плейлист со всеми частями курса](https://www.youtube.com/playlist?list=PLmfIBo6rTVR5XNcJxu8TwzEvIDUCAhGc6) + +## [Приложение к обучающим YouTube-видео](examples) diff --git a/.gitignore b/all-in-one-project/.gitignore similarity index 100% rename from .gitignore rename to all-in-one-project/.gitignore diff --git a/package-lock.json b/all-in-one-project/package-lock.json similarity index 100% rename from package-lock.json rename to all-in-one-project/package-lock.json diff --git a/package.json b/all-in-one-project/package.json similarity index 100% rename from package.json rename to all-in-one-project/package.json diff --git a/public/favicon.png b/all-in-one-project/public/favicon.png similarity index 100% rename from public/favicon.png rename to all-in-one-project/public/favicon.png diff --git a/public/global.css b/all-in-one-project/public/global.css similarity index 100% rename from public/global.css rename to all-in-one-project/public/global.css diff --git a/public/index.html b/all-in-one-project/public/index.html similarity index 100% rename from public/index.html rename to all-in-one-project/public/index.html diff --git a/rollup.config.js b/all-in-one-project/rollup.config.js similarity index 100% rename from rollup.config.js rename to all-in-one-project/rollup.config.js diff --git a/scripts/setupTypeScript.js b/all-in-one-project/scripts/setupTypeScript.js similarity index 100% rename from scripts/setupTypeScript.js rename to all-in-one-project/scripts/setupTypeScript.js diff --git a/src/AddTodoItem.svelte b/all-in-one-project/src/AddTodoItem.svelte similarity index 100% rename from src/AddTodoItem.svelte rename to all-in-one-project/src/AddTodoItem.svelte diff --git a/src/App.svelte b/all-in-one-project/src/App.svelte similarity index 100% rename from src/App.svelte rename to all-in-one-project/src/App.svelte diff --git a/src/Form.svelte b/all-in-one-project/src/Form.svelte similarity index 100% rename from src/Form.svelte rename to all-in-one-project/src/Form.svelte diff --git a/src/Layouts/BaseLayout.svelte b/all-in-one-project/src/Layouts/BaseLayout.svelte similarity index 100% rename from src/Layouts/BaseLayout.svelte rename to all-in-one-project/src/Layouts/BaseLayout.svelte diff --git a/src/TodoItem.svelte b/all-in-one-project/src/TodoItem.svelte similarity index 100% rename from src/TodoItem.svelte rename to all-in-one-project/src/TodoItem.svelte diff --git a/src/actions/draggable.js b/all-in-one-project/src/actions/draggable.js similarity index 100% rename from src/actions/draggable.js rename to all-in-one-project/src/actions/draggable.js diff --git a/src/components/AddTodoItem.svelte b/all-in-one-project/src/components/AddTodoItem.svelte similarity index 100% rename from src/components/AddTodoItem.svelte rename to all-in-one-project/src/components/AddTodoItem.svelte diff --git a/src/components/Dir.svelte b/all-in-one-project/src/components/Dir.svelte similarity index 100% rename from src/components/Dir.svelte rename to all-in-one-project/src/components/Dir.svelte diff --git a/src/components/Examples.svelte b/all-in-one-project/src/components/Examples.svelte similarity index 100% rename from src/components/Examples.svelte rename to all-in-one-project/src/components/Examples.svelte diff --git a/src/components/File.svelte b/all-in-one-project/src/components/File.svelte similarity index 100% rename from src/components/File.svelte rename to all-in-one-project/src/components/File.svelte diff --git a/src/components/Form.svelte b/all-in-one-project/src/components/Form.svelte similarity index 100% rename from src/components/Form.svelte rename to all-in-one-project/src/components/Form.svelte diff --git a/src/components/TodoItem.svelte b/all-in-one-project/src/components/TodoItem.svelte similarity index 100% rename from src/components/TodoItem.svelte rename to all-in-one-project/src/components/TodoItem.svelte diff --git a/src/components/files.js b/all-in-one-project/src/components/files.js similarity index 100% rename from src/components/files.js rename to all-in-one-project/src/components/files.js diff --git a/src/components/tabs/Tab1.svelte b/all-in-one-project/src/components/tabs/Tab1.svelte similarity index 100% rename from src/components/tabs/Tab1.svelte rename to all-in-one-project/src/components/tabs/Tab1.svelte diff --git a/src/components/tabs/Tab2.svelte b/all-in-one-project/src/components/tabs/Tab2.svelte similarity index 100% rename from src/components/tabs/Tab2.svelte rename to all-in-one-project/src/components/tabs/Tab2.svelte diff --git a/src/components/tabs/Tabs.svelte b/all-in-one-project/src/components/tabs/Tabs.svelte similarity index 100% rename from src/components/tabs/Tabs.svelte rename to all-in-one-project/src/components/tabs/Tabs.svelte diff --git a/src/draggable.js b/all-in-one-project/src/draggable.js similarity index 100% rename from src/draggable.js rename to all-in-one-project/src/draggable.js diff --git a/src/getTodos.js b/all-in-one-project/src/getTodos.js similarity index 100% rename from src/getTodos.js rename to all-in-one-project/src/getTodos.js diff --git a/src/interval.js b/all-in-one-project/src/interval.js similarity index 100% rename from src/interval.js rename to all-in-one-project/src/interval.js diff --git a/src/main.js b/all-in-one-project/src/main.js similarity index 100% rename from src/main.js rename to all-in-one-project/src/main.js diff --git a/src/store.js b/all-in-one-project/src/store.js similarity index 100% rename from src/store.js rename to all-in-one-project/src/store.js diff --git a/src/store/customStore.js b/all-in-one-project/src/store/customStore.js similarity index 100% rename from src/store/customStore.js rename to all-in-one-project/src/store/customStore.js diff --git a/src/store/mousePosition.js b/all-in-one-project/src/store/mousePosition.js similarity index 100% rename from src/store/mousePosition.js rename to all-in-one-project/src/store/mousePosition.js diff --git a/src/store/store.js b/all-in-one-project/src/store/store.js similarity index 100% rename from src/store/store.js rename to all-in-one-project/src/store/store.js diff --git a/src/store/todoStats.js b/all-in-one-project/src/store/todoStats.js similarity index 100% rename from src/store/todoStats.js rename to all-in-one-project/src/store/todoStats.js diff --git a/src/transition.js b/all-in-one-project/src/transition.js similarity index 100% rename from src/transition.js rename to all-in-one-project/src/transition.js diff --git a/src/transitions/skew.js b/all-in-one-project/src/transitions/skew.js similarity index 100% rename from src/transitions/skew.js rename to all-in-one-project/src/transitions/skew.js diff --git a/src/transitions/typewriter.js b/all-in-one-project/src/transitions/typewriter.js similarity index 100% rename from src/transitions/typewriter.js rename to all-in-one-project/src/transitions/typewriter.js diff --git a/src/utils/format.js b/all-in-one-project/src/utils/format.js similarity index 100% rename from src/utils/format.js rename to all-in-one-project/src/utils/format.js diff --git a/src/utils/getTodos.js b/all-in-one-project/src/utils/getTodos.js similarity index 100% rename from src/utils/getTodos.js rename to all-in-one-project/src/utils/getTodos.js diff --git a/src/utils/onInterval.js b/all-in-one-project/src/utils/onInterval.js similarity index 100% rename from src/utils/onInterval.js rename to all-in-one-project/src/utils/onInterval.js diff --git a/src/utils/stat.js b/all-in-one-project/src/utils/stat.js similarity index 100% rename from src/utils/stat.js rename to all-in-one-project/src/utils/stat.js diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..b444fe4 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,14 @@ +# Приложение к обучающим YouTube-видео + +1. [Установка и структура проекта.](projects/video01) +2. [Компонент и его структура.](projects/video02) +3. [Жизненный цикл компонента.](projects/video03) +4. [Синтаксис HTML шаблонов.](projects/video04) +5. [События и обработка событий.](projects/video05) +6. [Привязки (Bindings).](projects/video06) +7. [Хранилище (Store).](projects/video07) +8. [Анимации и переходы (Motion, Transition and Animation).](projects/video08) +9. [Действия и директива use (Actions).](projects/video09) +10. [Слоты - Svelte slots. Context Модуль - Svelte module context.](projects/video10) +11. [API контекста (Context API). Применение CSS классов по условию.](projects/video11) +12. [Специальные элементы.](projects/video12) diff --git a/examples/projects/video01/README.md b/examples/projects/video01/README.md new file mode 100644 index 0000000..f4d55a6 --- /dev/null +++ b/examples/projects/video01/README.md @@ -0,0 +1,25 @@ +# Что такое Svelte и как он устроен? + +[![Что такое Svelte и как он устроен? video](https://img.youtube.com/vi/N4KXC7z---Y/0.jpg)](https://youtu.be/N4KXC7z---Y "Что такое Svelte и как он устроен?") + +## SVELTE +Сайт проекта [Svelte](https://svelte.dev/) + +## Создать новый поект, перейти в папку, установить зависимости и запустить VS Code +`npx degit sveltejs/template svelte-todo && cd svelte-todo && npm install && code .` + +### npx +Удобная команда запуска. + +### degit +[degit](https://github.com/Rich-Harris/degit) - команда копирования git-репозитория. + +## rollup.js +[rollup.js](https://rollupjs.org/) - сборщик модулей JavaScript. + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + diff --git a/examples/projects/video01/code/svelte-todo/.gitignore b/examples/projects/video01/code/svelte-todo/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video01/code/svelte-todo/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video01/code/svelte-todo/README.md b/examples/projects/video01/code/svelte-todo/README.md new file mode 100644 index 0000000..76c32b5 --- /dev/null +++ b/examples/projects/video01/code/svelte-todo/README.md @@ -0,0 +1,109 @@ +*Psst — looking for a more complete solution? Check out [SvelteKit](https://kit.svelte.dev), the official framework for building web applications of all sizes, with a beautiful development experience and flexible filesystem-based routing.* + +*Looking for a shareable component template instead? You can [use SvelteKit for that as well](https://kit.svelte.dev/docs#packaging) or the older [sveltejs/component-template](https://github.com/sveltejs/component-template)* + +--- + +# svelte app + +This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template. + +To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit): + +```bash +npx degit sveltejs/template svelte-app +cd svelte-app +``` + +*Note that you will need to have [Node.js](https://nodejs.org) installed.* + + +## Get started + +Install the dependencies... + +```bash +cd svelte-app +npm install +``` + +...then start [Rollup](https://rollupjs.org): + +```bash +npm run dev +``` + +Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes. + +By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`. + +If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense. + +## Building and running in production mode + +To create an optimised version of the app: + +```bash +npm run build +``` + +You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com). + + +## Single-page app mode + +By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere. + +If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json: + +```js +"start": "sirv public --single" +``` + +## Using TypeScript + +This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with: + +```bash +node scripts/setupTypeScript.js +``` + +Or remove the script via: + +```bash +rm scripts/setupTypeScript.js +``` + +If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte). + +## Deploying to the web + +### With [Vercel](https://vercel.com) + +Install `vercel` if you haven't already: + +```bash +npm install -g vercel +``` + +Then, from within your project folder: + +```bash +cd public +vercel deploy --name my-project +``` + +### With [surge](https://surge.sh/) + +Install `surge` if you haven't already: + +```bash +npm install -g surge +``` + +Then, from within your project folder: + +```bash +npm run build +surge public my-project.surge.sh +``` diff --git a/examples/projects/video01/code/svelte-todo/package.json b/examples/projects/video01/code/svelte-todo/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video01/code/svelte-todo/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video01/code/svelte-todo/public/favicon.png b/examples/projects/video01/code/svelte-todo/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video01/code/svelte-todo/public/favicon.png differ diff --git a/examples/projects/video01/code/svelte-todo/public/global.css b/examples/projects/video01/code/svelte-todo/public/global.css new file mode 100644 index 0000000..bb28a94 --- /dev/null +++ b/examples/projects/video01/code/svelte-todo/public/global.css @@ -0,0 +1,63 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} diff --git a/examples/projects/video01/code/svelte-todo/public/index.html b/examples/projects/video01/code/svelte-todo/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video01/code/svelte-todo/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video01/code/svelte-todo/rollup.config.js b/examples/projects/video01/code/svelte-todo/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video01/code/svelte-todo/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video01/code/svelte-todo/scripts/setupTypeScript.js b/examples/projects/video01/code/svelte-todo/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video01/code/svelte-todo/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+
+ + \ No newline at end of file diff --git a/examples/projects/video01/code/svelte-todo/src/main.js b/examples/projects/video01/code/svelte-todo/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video01/code/svelte-todo/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video02/README.md b/examples/projects/video02/README.md new file mode 100644 index 0000000..6fcd42c --- /dev/null +++ b/examples/projects/video02/README.md @@ -0,0 +1,23 @@ +# Как устроен Компонент в Svelte? + +[![Как устроен Компонент в Svelte? video](https://img.youtube.com/vi/u-_pqJ9ARos/0.jpg)](https://youtu.be/u-_pqJ9ARos "Как устроен Компонент в Svelte?") + +В этом уроке рассмотрим компоненты Svelte, пропс (props, `$$props`, `$$restProps`, `export let prop`), реактивность SvelteJS, блоки `script` и `style`, изоляцию стилей и `:global()` + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) +2. [Пример №2](code/svelte-todo-02) +3. [Пример №3](code/svelte-todo-03) +4. [Пример №4](code/svelte-todo-04) +5. [Пример №5](code/svelte-todo-05) +6. [Пример №6](code/svelte-todo-06) +7. [Пример №7](code/svelte-todo-07) +8. [Пример №8](code/svelte-todo-08) +9. [Пример №9](code/svelte-todo-09) diff --git a/examples/projects/video02/code/svelte-todo-01/.gitignore b/examples/projects/video02/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video02/code/svelte-todo-01/README.md b/examples/projects/video02/code/svelte-todo-01/README.md new file mode 100644 index 0000000..42b2eb5 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-01/README.md @@ -0,0 +1 @@ +Исходный вид проекта. \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-01/package.json b/examples/projects/video02/code/svelte-todo-01/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-01/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video02/code/svelte-todo-01/public/favicon.png b/examples/projects/video02/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video02/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video02/code/svelte-todo-01/public/global.css b/examples/projects/video02/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..bb28a94 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-01/public/global.css @@ -0,0 +1,63 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} diff --git a/examples/projects/video02/code/svelte-todo-01/public/index.html b/examples/projects/video02/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video02/code/svelte-todo-01/rollup.config.js b/examples/projects/video02/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video02/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video02/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-01/src/main.js b/examples/projects/video02/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-01/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-02/.gitignore b/examples/projects/video02/code/svelte-todo-02/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-02/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video02/code/svelte-todo-02/README.md b/examples/projects/video02/code/svelte-todo-02/README.md new file mode 100644 index 0000000..6f589e8 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-02/README.md @@ -0,0 +1,2 @@ +1. Создали компонент `AddTodoItem`. +2. Добавили `AddTodoItem` в основной компонент. \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-02/package.json b/examples/projects/video02/code/svelte-todo-02/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-02/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video02/code/svelte-todo-02/public/favicon.png b/examples/projects/video02/code/svelte-todo-02/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video02/code/svelte-todo-02/public/favicon.png differ diff --git a/examples/projects/video02/code/svelte-todo-02/public/global.css b/examples/projects/video02/code/svelte-todo-02/public/global.css new file mode 100644 index 0000000..bb28a94 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-02/public/global.css @@ -0,0 +1,63 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} diff --git a/examples/projects/video02/code/svelte-todo-02/public/index.html b/examples/projects/video02/code/svelte-todo-02/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-02/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video02/code/svelte-todo-02/rollup.config.js b/examples/projects/video02/code/svelte-todo-02/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-02/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video02/code/svelte-todo-02/scripts/setupTypeScript.js b/examples/projects/video02/code/svelte-todo-02/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-02/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-02/src/components/AddTodoItem.svelte b/examples/projects/video02/code/svelte-todo-02/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..3474da0 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-02/src/components/AddTodoItem.svelte @@ -0,0 +1,20 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-02/src/main.js b/examples/projects/video02/code/svelte-todo-02/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-02/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-03/.gitignore b/examples/projects/video02/code/svelte-todo-03/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-03/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video02/code/svelte-todo-03/README.md b/examples/projects/video02/code/svelte-todo-03/README.md new file mode 100644 index 0000000..2cbe066 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-03/README.md @@ -0,0 +1 @@ +1. Добавили свойство `title` к компоненту `AddTodoItem`. \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-03/package.json b/examples/projects/video02/code/svelte-todo-03/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-03/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video02/code/svelte-todo-03/public/favicon.png b/examples/projects/video02/code/svelte-todo-03/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video02/code/svelte-todo-03/public/favicon.png differ diff --git a/examples/projects/video02/code/svelte-todo-03/public/global.css b/examples/projects/video02/code/svelte-todo-03/public/global.css new file mode 100644 index 0000000..bb28a94 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-03/public/global.css @@ -0,0 +1,63 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} diff --git a/examples/projects/video02/code/svelte-todo-03/public/index.html b/examples/projects/video02/code/svelte-todo-03/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-03/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video02/code/svelte-todo-03/rollup.config.js b/examples/projects/video02/code/svelte-todo-03/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-03/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video02/code/svelte-todo-03/scripts/setupTypeScript.js b/examples/projects/video02/code/svelte-todo-03/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-03/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-03/src/components/AddTodoItem.svelte b/examples/projects/video02/code/svelte-todo-03/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..139e3cd --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-03/src/components/AddTodoItem.svelte @@ -0,0 +1,20 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-03/src/main.js b/examples/projects/video02/code/svelte-todo-03/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-03/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-04/.gitignore b/examples/projects/video02/code/svelte-todo-04/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-04/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video02/code/svelte-todo-04/README.md b/examples/projects/video02/code/svelte-todo-04/README.md new file mode 100644 index 0000000..f80d97d --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-04/README.md @@ -0,0 +1,3 @@ +# Свойства по умолчанию + +1. Проверили, как работает свойство по умолчанию на примере свойства `title` компонента `AddTodoItem`. diff --git a/examples/projects/video02/code/svelte-todo-04/package.json b/examples/projects/video02/code/svelte-todo-04/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-04/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video02/code/svelte-todo-04/public/favicon.png b/examples/projects/video02/code/svelte-todo-04/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video02/code/svelte-todo-04/public/favicon.png differ diff --git a/examples/projects/video02/code/svelte-todo-04/public/global.css b/examples/projects/video02/code/svelte-todo-04/public/global.css new file mode 100644 index 0000000..bb28a94 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-04/public/global.css @@ -0,0 +1,63 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} diff --git a/examples/projects/video02/code/svelte-todo-04/public/index.html b/examples/projects/video02/code/svelte-todo-04/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-04/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video02/code/svelte-todo-04/rollup.config.js b/examples/projects/video02/code/svelte-todo-04/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-04/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video02/code/svelte-todo-04/scripts/setupTypeScript.js b/examples/projects/video02/code/svelte-todo-04/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-04/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-04/src/components/AddTodoItem.svelte b/examples/projects/video02/code/svelte-todo-04/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..139e3cd --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-04/src/components/AddTodoItem.svelte @@ -0,0 +1,20 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-04/src/main.js b/examples/projects/video02/code/svelte-todo-04/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-04/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-05/.gitignore b/examples/projects/video02/code/svelte-todo-05/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-05/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video02/code/svelte-todo-05/README.md b/examples/projects/video02/code/svelte-todo-05/README.md new file mode 100644 index 0000000..c982b97 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-05/README.md @@ -0,0 +1,4 @@ +# Работа с полями + +1. Пример использования вычисляемого поля. +2. Примеры использования свойств. diff --git a/examples/projects/video02/code/svelte-todo-05/package.json b/examples/projects/video02/code/svelte-todo-05/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-05/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video02/code/svelte-todo-05/public/favicon.png b/examples/projects/video02/code/svelte-todo-05/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video02/code/svelte-todo-05/public/favicon.png differ diff --git a/examples/projects/video02/code/svelte-todo-05/public/global.css b/examples/projects/video02/code/svelte-todo-05/public/global.css new file mode 100644 index 0000000..bb28a94 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-05/public/global.css @@ -0,0 +1,63 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} diff --git a/examples/projects/video02/code/svelte-todo-05/public/index.html b/examples/projects/video02/code/svelte-todo-05/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-05/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video02/code/svelte-todo-05/rollup.config.js b/examples/projects/video02/code/svelte-todo-05/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-05/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video02/code/svelte-todo-05/scripts/setupTypeScript.js b/examples/projects/video02/code/svelte-todo-05/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-05/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-05/src/components/AddTodoItem.svelte b/examples/projects/video02/code/svelte-todo-05/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..ab0c408 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-05/src/components/AddTodoItem.svelte @@ -0,0 +1,27 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-05/src/main.js b/examples/projects/video02/code/svelte-todo-05/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-05/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-06/.gitignore b/examples/projects/video02/code/svelte-todo-06/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-06/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video02/code/svelte-todo-06/README.md b/examples/projects/video02/code/svelte-todo-06/README.md new file mode 100644 index 0000000..5a31196 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-06/README.md @@ -0,0 +1,3 @@ +1. Пример сокращенной записи переменной. +2. Пример использования зарезервированного слова $$props. +3. Пример использования зарезервированного слова $$restProps. \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-06/package.json b/examples/projects/video02/code/svelte-todo-06/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-06/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video02/code/svelte-todo-06/public/favicon.png b/examples/projects/video02/code/svelte-todo-06/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video02/code/svelte-todo-06/public/favicon.png differ diff --git a/examples/projects/video02/code/svelte-todo-06/public/global.css b/examples/projects/video02/code/svelte-todo-06/public/global.css new file mode 100644 index 0000000..bb28a94 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-06/public/global.css @@ -0,0 +1,63 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} diff --git a/examples/projects/video02/code/svelte-todo-06/public/index.html b/examples/projects/video02/code/svelte-todo-06/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-06/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video02/code/svelte-todo-06/rollup.config.js b/examples/projects/video02/code/svelte-todo-06/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-06/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video02/code/svelte-todo-06/scripts/setupTypeScript.js b/examples/projects/video02/code/svelte-todo-06/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-06/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-06/src/components/AddTodoItem.svelte b/examples/projects/video02/code/svelte-todo-06/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..caf585e --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-06/src/components/AddTodoItem.svelte @@ -0,0 +1,24 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-06/src/main.js b/examples/projects/video02/code/svelte-todo-06/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-06/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-07/.gitignore b/examples/projects/video02/code/svelte-todo-07/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-07/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video02/code/svelte-todo-07/README.md b/examples/projects/video02/code/svelte-todo-07/README.md new file mode 100644 index 0000000..e7b9b3b --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-07/README.md @@ -0,0 +1,2 @@ +1. Пример сокращенной записи переменной. +2. Демонстрация работы реактивности. Использования Svelte-конструкции ("JavaScript-метки") "$:" \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-07/package.json b/examples/projects/video02/code/svelte-todo-07/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-07/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video02/code/svelte-todo-07/public/favicon.png b/examples/projects/video02/code/svelte-todo-07/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video02/code/svelte-todo-07/public/favicon.png differ diff --git a/examples/projects/video02/code/svelte-todo-07/public/global.css b/examples/projects/video02/code/svelte-todo-07/public/global.css new file mode 100644 index 0000000..bb28a94 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-07/public/global.css @@ -0,0 +1,63 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} diff --git a/examples/projects/video02/code/svelte-todo-07/public/index.html b/examples/projects/video02/code/svelte-todo-07/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-07/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video02/code/svelte-todo-07/rollup.config.js b/examples/projects/video02/code/svelte-todo-07/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-07/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video02/code/svelte-todo-07/scripts/setupTypeScript.js b/examples/projects/video02/code/svelte-todo-07/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-07/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-07/src/components/AddTodoItem.svelte b/examples/projects/video02/code/svelte-todo-07/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..a5c8ed8 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-07/src/components/AddTodoItem.svelte @@ -0,0 +1,29 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-07/src/main.js b/examples/projects/video02/code/svelte-todo-07/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-07/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-08/.gitignore b/examples/projects/video02/code/svelte-todo-08/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-08/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video02/code/svelte-todo-08/README.md b/examples/projects/video02/code/svelte-todo-08/README.md new file mode 100644 index 0000000..c23897e --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-08/README.md @@ -0,0 +1,3 @@ +1. Использования оператора "if" в реактивном выражении. +2. Пример, который может содердать более сложную рекативную вычислительную структуру. +3. Создание рективной переменной. diff --git a/examples/projects/video02/code/svelte-todo-08/package.json b/examples/projects/video02/code/svelte-todo-08/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-08/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video02/code/svelte-todo-08/public/favicon.png b/examples/projects/video02/code/svelte-todo-08/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video02/code/svelte-todo-08/public/favicon.png differ diff --git a/examples/projects/video02/code/svelte-todo-08/public/global.css b/examples/projects/video02/code/svelte-todo-08/public/global.css new file mode 100644 index 0000000..bb28a94 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-08/public/global.css @@ -0,0 +1,63 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} diff --git a/examples/projects/video02/code/svelte-todo-08/public/index.html b/examples/projects/video02/code/svelte-todo-08/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-08/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video02/code/svelte-todo-08/rollup.config.js b/examples/projects/video02/code/svelte-todo-08/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-08/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video02/code/svelte-todo-08/scripts/setupTypeScript.js b/examples/projects/video02/code/svelte-todo-08/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-08/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-08/src/components/AddTodoItem.svelte b/examples/projects/video02/code/svelte-todo-08/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..d8111a8 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-08/src/components/AddTodoItem.svelte @@ -0,0 +1,41 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-08/src/main.js b/examples/projects/video02/code/svelte-todo-08/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-08/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-09/.gitignore b/examples/projects/video02/code/svelte-todo-09/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-09/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video02/code/svelte-todo-09/README.md b/examples/projects/video02/code/svelte-todo-09/README.md new file mode 100644 index 0000000..e4d4841 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-09/README.md @@ -0,0 +1,5 @@ +1. Пример отсутствия реактивности при обновлении массива (метод push). +2. Решения предыдущей задачи - присваивание массиву его обновлённую копию. +3. Пример использования стилей компонентов и их изолированности. + + diff --git a/examples/projects/video02/code/svelte-todo-09/package.json b/examples/projects/video02/code/svelte-todo-09/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-09/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video02/code/svelte-todo-09/public/favicon.png b/examples/projects/video02/code/svelte-todo-09/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video02/code/svelte-todo-09/public/favicon.png differ diff --git a/examples/projects/video02/code/svelte-todo-09/public/global.css b/examples/projects/video02/code/svelte-todo-09/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-09/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video02/code/svelte-todo-09/public/index.html b/examples/projects/video02/code/svelte-todo-09/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-09/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video02/code/svelte-todo-09/rollup.config.js b/examples/projects/video02/code/svelte-todo-09/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-09/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video02/code/svelte-todo-09/scripts/setupTypeScript.js b/examples/projects/video02/code/svelte-todo-09/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-09/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-09/src/components/AddTodoItem.svelte b/examples/projects/video02/code/svelte-todo-09/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..a7c91a9 --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-09/src/components/AddTodoItem.svelte @@ -0,0 +1,35 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video02/code/svelte-todo-09/src/main.js b/examples/projects/video02/code/svelte-todo-09/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video02/code/svelte-todo-09/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video03/README.md b/examples/projects/video03/README.md new file mode 100644 index 0000000..5e674d9 --- /dev/null +++ b/examples/projects/video03/README.md @@ -0,0 +1,22 @@ +# Жизненный цикл Svelte компонента + +[![Жизненный цикл Svelte компонента video](https://img.youtube.com/vi/drgBkaPNpk0/0.jpg)](https://youtu.be/drgBkaPNpk0 "Жизненный цикл Svelte компонента") + +В этом видео рассматриваем методы жизненного цикла компонентов [Svelte](https://svelte.dev/), а именно `onMount`, `onDestroy`, `beforeUpdate`, `afterUpdate`, а также функция `tick`. + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) +2. [Пример №2](code/svelte-todo-02) +3. [Пример №3](code/svelte-todo-03) +4. [Пример №4](code/svelte-todo-04) +5. [Пример №5](code/svelte-todo-05) +6. [Пример №6](code/svelte-todo-06) +7. [Пример №7](code/svelte-todo-07) + diff --git a/examples/projects/video03/code/svelte-todo-01/.gitignore b/examples/projects/video03/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video03/code/svelte-todo-01/README.md b/examples/projects/video03/code/svelte-todo-01/README.md new file mode 100644 index 0000000..9e2d18e --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-01/README.md @@ -0,0 +1,6 @@ +# `onMount` + +1. Демострация использование функции `onMount`. +2. Реализация счётчкика без утечки памяти. + + diff --git a/examples/projects/video03/code/svelte-todo-01/package.json b/examples/projects/video03/code/svelte-todo-01/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-01/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video03/code/svelte-todo-01/public/favicon.png b/examples/projects/video03/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video03/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video03/code/svelte-todo-01/public/global.css b/examples/projects/video03/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-01/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video03/code/svelte-todo-01/public/index.html b/examples/projects/video03/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video03/code/svelte-todo-01/rollup.config.js b/examples/projects/video03/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video03/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video03/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-01/src/components/AddTodoItem.svelte b/examples/projects/video03/code/svelte-todo-01/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..dd6049a --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-01/src/components/AddTodoItem.svelte @@ -0,0 +1,47 @@ + + +{counter} +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-01/src/main.js b/examples/projects/video03/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-01/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-02/.gitignore b/examples/projects/video03/code/svelte-todo-02/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-02/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video03/code/svelte-todo-02/README.md b/examples/projects/video03/code/svelte-todo-02/README.md new file mode 100644 index 0000000..af2ab9f --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-02/README.md @@ -0,0 +1,2 @@ +1. Демострация использование функции onDesctroy. +2. Реализация счётчкика без утечки памяти. \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-02/package.json b/examples/projects/video03/code/svelte-todo-02/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-02/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video03/code/svelte-todo-02/public/favicon.png b/examples/projects/video03/code/svelte-todo-02/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video03/code/svelte-todo-02/public/favicon.png differ diff --git a/examples/projects/video03/code/svelte-todo-02/public/global.css b/examples/projects/video03/code/svelte-todo-02/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-02/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video03/code/svelte-todo-02/public/index.html b/examples/projects/video03/code/svelte-todo-02/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-02/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video03/code/svelte-todo-02/rollup.config.js b/examples/projects/video03/code/svelte-todo-02/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-02/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video03/code/svelte-todo-02/scripts/setupTypeScript.js b/examples/projects/video03/code/svelte-todo-02/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-02/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-02/src/components/AddTodoItem.svelte b/examples/projects/video03/code/svelte-todo-02/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..a7da04d --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-02/src/components/AddTodoItem.svelte @@ -0,0 +1,46 @@ + + +{counter} +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-02/src/main.js b/examples/projects/video03/code/svelte-todo-02/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-02/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-03/.gitignore b/examples/projects/video03/code/svelte-todo-03/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-03/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video03/code/svelte-todo-03/README.md b/examples/projects/video03/code/svelte-todo-03/README.md new file mode 100644 index 0000000..50a247f --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-03/README.md @@ -0,0 +1,4 @@ +1. Рефакторинг. Демострация использование впомогательных JavaScript-функций. +2. Реализация счётчкика без утечки памяти. + + diff --git a/examples/projects/video03/code/svelte-todo-03/package.json b/examples/projects/video03/code/svelte-todo-03/package.json new file mode 100644 index 0000000..03cd455 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-03/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/examples/projects/video03/code/svelte-todo-03/public/favicon.png b/examples/projects/video03/code/svelte-todo-03/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video03/code/svelte-todo-03/public/favicon.png differ diff --git a/examples/projects/video03/code/svelte-todo-03/public/global.css b/examples/projects/video03/code/svelte-todo-03/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-03/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video03/code/svelte-todo-03/public/index.html b/examples/projects/video03/code/svelte-todo-03/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-03/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video03/code/svelte-todo-03/rollup.config.js b/examples/projects/video03/code/svelte-todo-03/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-03/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video03/code/svelte-todo-03/scripts/setupTypeScript.js b/examples/projects/video03/code/svelte-todo-03/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-03/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-03/src/components/AddTodoItem.svelte b/examples/projects/video03/code/svelte-todo-03/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..2880abe --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-03/src/components/AddTodoItem.svelte @@ -0,0 +1,41 @@ + + +{counter} +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-03/src/main.js b/examples/projects/video03/code/svelte-todo-03/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-03/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-03/src/utils/onInterval.js b/examples/projects/video03/code/svelte-todo-03/src/utils/onInterval.js new file mode 100644 index 0000000..48cc3d9 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-03/src/utils/onInterval.js @@ -0,0 +1,8 @@ +import { onDestroy } from 'svelte'; + +// cb - callback-function +// ms - milliseconds +export function onInterval(cb, ms) { + const interval = setInterval(cb, ms); + onDestroy(() => clearInterval(interval)); +} \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-04/.gitignore b/examples/projects/video03/code/svelte-todo-04/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-04/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video03/code/svelte-todo-04/README.md b/examples/projects/video03/code/svelte-todo-04/README.md new file mode 100644 index 0000000..7a14217 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-04/README.md @@ -0,0 +1,4 @@ +1. Эмуляция запроса на сервер. +2. Использование пакета uuid (Уставнока = `npm i uuid`). + + diff --git a/examples/projects/video03/code/svelte-todo-04/package.json b/examples/projects/video03/code/svelte-todo-04/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-04/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video03/code/svelte-todo-04/public/favicon.png b/examples/projects/video03/code/svelte-todo-04/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video03/code/svelte-todo-04/public/favicon.png differ diff --git a/examples/projects/video03/code/svelte-todo-04/public/global.css b/examples/projects/video03/code/svelte-todo-04/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-04/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video03/code/svelte-todo-04/public/index.html b/examples/projects/video03/code/svelte-todo-04/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-04/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video03/code/svelte-todo-04/rollup.config.js b/examples/projects/video03/code/svelte-todo-04/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-04/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video03/code/svelte-todo-04/scripts/setupTypeScript.js b/examples/projects/video03/code/svelte-todo-04/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-04/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-04/src/components/AddTodoItem.svelte b/examples/projects/video03/code/svelte-todo-04/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..e58b754 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-04/src/components/AddTodoItem.svelte @@ -0,0 +1,42 @@ + + +
+ + + +
+ +{JSON.stringify(items, null, 2)} + + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-04/src/main.js b/examples/projects/video03/code/svelte-todo-04/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-04/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-04/src/utils/getTodos.js b/examples/projects/video03/code/svelte-todo-04/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-04/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-05/.gitignore b/examples/projects/video03/code/svelte-todo-05/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-05/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video03/code/svelte-todo-05/README.md b/examples/projects/video03/code/svelte-todo-05/README.md new file mode 100644 index 0000000..dd6b0d0 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-05/README.md @@ -0,0 +1,4 @@ +1. Эмуляция запроса на сервер. +2. Использование `async/await`. + + diff --git a/examples/projects/video03/code/svelte-todo-05/package.json b/examples/projects/video03/code/svelte-todo-05/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-05/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video03/code/svelte-todo-05/public/favicon.png b/examples/projects/video03/code/svelte-todo-05/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video03/code/svelte-todo-05/public/favicon.png differ diff --git a/examples/projects/video03/code/svelte-todo-05/public/global.css b/examples/projects/video03/code/svelte-todo-05/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-05/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video03/code/svelte-todo-05/public/index.html b/examples/projects/video03/code/svelte-todo-05/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-05/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video03/code/svelte-todo-05/rollup.config.js b/examples/projects/video03/code/svelte-todo-05/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-05/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video03/code/svelte-todo-05/scripts/setupTypeScript.js b/examples/projects/video03/code/svelte-todo-05/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-05/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-05/src/components/AddTodoItem.svelte b/examples/projects/video03/code/svelte-todo-05/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..1b08e0e --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-05/src/components/AddTodoItem.svelte @@ -0,0 +1,47 @@ + + +
+ + + +
+ +{JSON.stringify(items, null, 2)} + + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-05/src/main.js b/examples/projects/video03/code/svelte-todo-05/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-05/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-05/src/utils/getTodos.js b/examples/projects/video03/code/svelte-todo-05/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-05/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-06/.gitignore b/examples/projects/video03/code/svelte-todo-06/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-06/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video03/code/svelte-todo-06/README.md b/examples/projects/video03/code/svelte-todo-06/README.md new file mode 100644 index 0000000..1bc7c8f --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-06/README.md @@ -0,0 +1,4 @@ +1. Пример использования элементов жизненного цикла компонента `beforeUpdate`, `afterUpdate`. `beforeUpdate` - планирует calback на запуск перед обновлением DOM, а `afterUpdate` вызывает callback когда DOM синхронизирован с данными. + + + diff --git a/examples/projects/video03/code/svelte-todo-06/package.json b/examples/projects/video03/code/svelte-todo-06/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-06/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video03/code/svelte-todo-06/public/favicon.png b/examples/projects/video03/code/svelte-todo-06/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video03/code/svelte-todo-06/public/favicon.png differ diff --git a/examples/projects/video03/code/svelte-todo-06/public/global.css b/examples/projects/video03/code/svelte-todo-06/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-06/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video03/code/svelte-todo-06/public/index.html b/examples/projects/video03/code/svelte-todo-06/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-06/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video03/code/svelte-todo-06/rollup.config.js b/examples/projects/video03/code/svelte-todo-06/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-06/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video03/code/svelte-todo-06/scripts/setupTypeScript.js b/examples/projects/video03/code/svelte-todo-06/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-06/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-06/src/components/AddTodoItem.svelte b/examples/projects/video03/code/svelte-todo-06/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..d14e4a3 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-06/src/components/AddTodoItem.svelte @@ -0,0 +1,49 @@ + + +
+ + + +
+ +{JSON.stringify(items, null, 2)} + + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-06/src/main.js b/examples/projects/video03/code/svelte-todo-06/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-06/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-06/src/utils/getTodos.js b/examples/projects/video03/code/svelte-todo-06/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-06/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-07/.gitignore b/examples/projects/video03/code/svelte-todo-07/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video03/code/svelte-todo-07/README.md b/examples/projects/video03/code/svelte-todo-07/README.md new file mode 100644 index 0000000..e90edc6 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/README.md @@ -0,0 +1,6 @@ +1. Пример использования функции `tick`. +2. Реализация функционала ввода телефонного номера. Улучшения удобства редактирования текста с помощью функции `tick`. + + + + diff --git a/examples/projects/video03/code/svelte-todo-07/package.json b/examples/projects/video03/code/svelte-todo-07/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video03/code/svelte-todo-07/public/favicon.png b/examples/projects/video03/code/svelte-todo-07/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video03/code/svelte-todo-07/public/favicon.png differ diff --git a/examples/projects/video03/code/svelte-todo-07/public/global.css b/examples/projects/video03/code/svelte-todo-07/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video03/code/svelte-todo-07/public/index.html b/examples/projects/video03/code/svelte-todo-07/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video03/code/svelte-todo-07/rollup.config.js b/examples/projects/video03/code/svelte-todo-07/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video03/code/svelte-todo-07/scripts/setupTypeScript.js b/examples/projects/video03/code/svelte-todo-07/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-07/src/components/AddTodoItem.svelte b/examples/projects/video03/code/svelte-todo-07/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..36f6ce8 --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/src/components/AddTodoItem.svelte @@ -0,0 +1,41 @@ + + +
+ + +
+ + diff --git a/examples/projects/video03/code/svelte-todo-07/src/main.js b/examples/projects/video03/code/svelte-todo-07/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-07/src/utils/format.js b/examples/projects/video03/code/svelte-todo-07/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video03/code/svelte-todo-07/src/utils/getTodos.js b/examples/projects/video03/code/svelte-todo-07/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video03/code/svelte-todo-07/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/README.md b/examples/projects/video04/README.md new file mode 100644 index 0000000..181d066 --- /dev/null +++ b/examples/projects/video04/README.md @@ -0,0 +1,26 @@ +# HTML шаблоны в Svelte + +[![HTML шаблоны в Svelte video](https://img.youtube.com/vi/pOmTYXiF0AU/0.jpg)](https://youtu.be/pOmTYXiF0AU "HTML шаблоны в Svelte") + +В этом уроке рассмотрим cинтаксис HTML-тегов [Svelte](https://svelte.dev/), а именно `{@html}`, `{@debug}`, `{#if}`, `{#each}`, `{#await}`, а также `{#key}`. + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) +2. [Пример №2](code/svelte-todo-02) +3. [Пример №3](code/svelte-todo-03) +4. [Пример №4](code/svelte-todo-04) +5. [Пример №5](code/svelte-todo-05) +6. [Пример №6](code/svelte-todo-06) +7. [Пример №7](code/svelte-todo-07) +8. [Пример №8](code/svelte-todo-08) +9. [Пример №9](code/svelte-todo-09) +10. [Пример №10](code/svelte-todo-10) +11. [Пример №11](code/svelte-todo-11) +12. [Пример №12](code/svelte-todo-12) diff --git a/examples/projects/video04/code/svelte-todo-01/.gitignore b/examples/projects/video04/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-01/README.md b/examples/projects/video04/code/svelte-todo-01/README.md new file mode 100644 index 0000000..fab191e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/README.md @@ -0,0 +1 @@ +# Пример использования `@html` diff --git a/examples/projects/video04/code/svelte-todo-01/package.json b/examples/projects/video04/code/svelte-todo-01/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-01/public/favicon.png b/examples/projects/video04/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-01/public/global.css b/examples/projects/video04/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-01/public/index.html b/examples/projects/video04/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-01/rollup.config.js b/examples/projects/video04/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-01/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-01/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..aeb892c --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/src/components/AddTodoItem.svelte @@ -0,0 +1,41 @@ + + +
+ + +
+ + diff --git a/examples/projects/video04/code/svelte-todo-01/src/main.js b/examples/projects/video04/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-01/src/utils/format.js b/examples/projects/video04/code/svelte-todo-01/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-01/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-01/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-01/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-02/.gitignore b/examples/projects/video04/code/svelte-todo-02/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-02/README.md b/examples/projects/video04/code/svelte-todo-02/README.md new file mode 100644 index 0000000..ac7b16b --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/README.md @@ -0,0 +1 @@ +# Пример использования `@debug` diff --git a/examples/projects/video04/code/svelte-todo-02/package.json b/examples/projects/video04/code/svelte-todo-02/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-02/public/favicon.png b/examples/projects/video04/code/svelte-todo-02/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-02/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-02/public/global.css b/examples/projects/video04/code/svelte-todo-02/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-02/public/index.html b/examples/projects/video04/code/svelte-todo-02/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-02/rollup.config.js b/examples/projects/video04/code/svelte-todo-02/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-02/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-02/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-02/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-02/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..25ad261 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/src/components/AddTodoItem.svelte @@ -0,0 +1,28 @@ + + +
+ +
+ +{@debug items} +{JSON.stringify(items, null, 2)} + + diff --git a/examples/projects/video04/code/svelte-todo-02/src/main.js b/examples/projects/video04/code/svelte-todo-02/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-02/src/utils/format.js b/examples/projects/video04/code/svelte-todo-02/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-02/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-02/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-02/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-03/.gitignore b/examples/projects/video04/code/svelte-todo-03/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-03/README.md b/examples/projects/video04/code/svelte-todo-03/README.md new file mode 100644 index 0000000..c0e01b4 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/README.md @@ -0,0 +1 @@ +# Пример использования оператора {#if} diff --git a/examples/projects/video04/code/svelte-todo-03/package.json b/examples/projects/video04/code/svelte-todo-03/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-03/public/favicon.png b/examples/projects/video04/code/svelte-todo-03/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-03/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-03/public/global.css b/examples/projects/video04/code/svelte-todo-03/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-03/public/index.html b/examples/projects/video04/code/svelte-todo-03/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-03/rollup.config.js b/examples/projects/video04/code/svelte-todo-03/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-03/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-03/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-03/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-03/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..0b8add7 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/src/components/AddTodoItem.svelte @@ -0,0 +1,32 @@ + + +
+ +
+ +{#if items.length === 0} +No items yet. +{/if} +{#if items.length > 0} +{JSON.stringify(items, null, 2)} +{/if} + + diff --git a/examples/projects/video04/code/svelte-todo-03/src/main.js b/examples/projects/video04/code/svelte-todo-03/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-03/src/utils/format.js b/examples/projects/video04/code/svelte-todo-03/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-03/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-03/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-03/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-04/.gitignore b/examples/projects/video04/code/svelte-todo-04/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-04/README.md b/examples/projects/video04/code/svelte-todo-04/README.md new file mode 100644 index 0000000..bb959d4 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/README.md @@ -0,0 +1 @@ +# Демострация использования {#if} {:else} diff --git a/examples/projects/video04/code/svelte-todo-04/package.json b/examples/projects/video04/code/svelte-todo-04/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-04/public/favicon.png b/examples/projects/video04/code/svelte-todo-04/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-04/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-04/public/global.css b/examples/projects/video04/code/svelte-todo-04/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-04/public/index.html b/examples/projects/video04/code/svelte-todo-04/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-04/rollup.config.js b/examples/projects/video04/code/svelte-todo-04/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-04/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-04/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-04/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-04/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..f84e3d3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/src/components/AddTodoItem.svelte @@ -0,0 +1,33 @@ + + +
+ +
+ +{#if items.length === 0} +No items yet. +{:else if items.length === 4} +You have 4 item to do. +{:else} +{JSON.stringify(items, null, 2)} +{/if} + + diff --git a/examples/projects/video04/code/svelte-todo-04/src/main.js b/examples/projects/video04/code/svelte-todo-04/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-04/src/utils/format.js b/examples/projects/video04/code/svelte-todo-04/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-04/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-04/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-04/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-05/.gitignore b/examples/projects/video04/code/svelte-todo-05/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-05/README.md b/examples/projects/video04/code/svelte-todo-05/README.md new file mode 100644 index 0000000..8fb25ea --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/README.md @@ -0,0 +1 @@ +# Пример использования итератора {#each} diff --git a/examples/projects/video04/code/svelte-todo-05/package.json b/examples/projects/video04/code/svelte-todo-05/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-05/public/favicon.png b/examples/projects/video04/code/svelte-todo-05/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-05/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-05/public/global.css b/examples/projects/video04/code/svelte-todo-05/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-05/public/index.html b/examples/projects/video04/code/svelte-todo-05/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-05/rollup.config.js b/examples/projects/video04/code/svelte-todo-05/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-05/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-05/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-05/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-05/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..1e237ed --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/src/components/AddTodoItem.svelte @@ -0,0 +1,20 @@ + + +{#if items.length === 0} + No items yet. +{:else} + {#each items as item} + + {/each} +{/if} + + diff --git a/examples/projects/video04/code/svelte-todo-05/src/components/TodoItem.svelte b/examples/projects/video04/code/svelte-todo-05/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce55d94 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/src/components/TodoItem.svelte @@ -0,0 +1,7 @@ + + +
+

{title}

+
\ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-05/src/main.js b/examples/projects/video04/code/svelte-todo-05/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-05/src/utils/format.js b/examples/projects/video04/code/svelte-todo-05/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-05/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-05/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-05/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-06/.gitignore b/examples/projects/video04/code/svelte-todo-06/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-06/README.md b/examples/projects/video04/code/svelte-todo-06/README.md new file mode 100644 index 0000000..478791d --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/README.md @@ -0,0 +1,4 @@ +# Подробности использования итератора {#each} + +- Использование деструктурирующего создание переменных объекта. +- Использование индекса итератора {#each}, ключа текущего объекта итерации. diff --git a/examples/projects/video04/code/svelte-todo-06/package.json b/examples/projects/video04/code/svelte-todo-06/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-06/public/favicon.png b/examples/projects/video04/code/svelte-todo-06/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-06/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-06/public/global.css b/examples/projects/video04/code/svelte-todo-06/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-06/public/index.html b/examples/projects/video04/code/svelte-todo-06/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-06/rollup.config.js b/examples/projects/video04/code/svelte-todo-06/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-06/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-06/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-06/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-06/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..40b465c --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/src/components/AddTodoItem.svelte @@ -0,0 +1,40 @@ + + +
+ +
+ +{#if items.length === 0} + No items yet. +{:else} + {#each items as { id, text }, index (id)} + + {/each} +{/if} + + diff --git a/examples/projects/video04/code/svelte-todo-06/src/components/TodoItem.svelte b/examples/projects/video04/code/svelte-todo-06/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce55d94 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/src/components/TodoItem.svelte @@ -0,0 +1,7 @@ + + +
+

{title}

+
\ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-06/src/main.js b/examples/projects/video04/code/svelte-todo-06/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-06/src/utils/format.js b/examples/projects/video04/code/svelte-todo-06/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-06/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-06/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-06/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-07/.gitignore b/examples/projects/video04/code/svelte-todo-07/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-07/README.md b/examples/projects/video04/code/svelte-todo-07/README.md new file mode 100644 index 0000000..956b134 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/README.md @@ -0,0 +1,5 @@ +# Подробности использования итератора `{#each}` + +- Использование деструктурирующего создание переменных объекта. +- Использование индекса итератора `{#each}`, ключа текущего объекта итерации. +- Использование `{:else}` в итераторе `{#each}`. diff --git a/examples/projects/video04/code/svelte-todo-07/package.json b/examples/projects/video04/code/svelte-todo-07/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-07/public/favicon.png b/examples/projects/video04/code/svelte-todo-07/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-07/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-07/public/global.css b/examples/projects/video04/code/svelte-todo-07/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-07/public/index.html b/examples/projects/video04/code/svelte-todo-07/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-07/rollup.config.js b/examples/projects/video04/code/svelte-todo-07/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-07/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-07/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-07/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-07/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..635e783 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/src/components/AddTodoItem.svelte @@ -0,0 +1,39 @@ + + +
+ +
+ +{#each items as { id, text }, index (id)} + +{:else} + No items yet. +{/each} + + + diff --git a/examples/projects/video04/code/svelte-todo-07/src/components/TodoItem.svelte b/examples/projects/video04/code/svelte-todo-07/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce55d94 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/src/components/TodoItem.svelte @@ -0,0 +1,7 @@ + + +
+

{title}

+
\ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-07/src/main.js b/examples/projects/video04/code/svelte-todo-07/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-07/src/utils/format.js b/examples/projects/video04/code/svelte-todo-07/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-07/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-07/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-07/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-08/.gitignore b/examples/projects/video04/code/svelte-todo-08/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-08/README.md b/examples/projects/video04/code/svelte-todo-08/README.md new file mode 100644 index 0000000..2392e34 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/README.md @@ -0,0 +1,3 @@ +# Демонстрация работы с блоком `{#await}` + +Он помогает прямо в разметка распоковать `Promise` и показать его содержимое. diff --git a/examples/projects/video04/code/svelte-todo-08/package.json b/examples/projects/video04/code/svelte-todo-08/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-08/public/favicon.png b/examples/projects/video04/code/svelte-todo-08/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-08/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-08/public/global.css b/examples/projects/video04/code/svelte-todo-08/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-08/public/index.html b/examples/projects/video04/code/svelte-todo-08/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-08/rollup.config.js b/examples/projects/video04/code/svelte-todo-08/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-08/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-08/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-08/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-08/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..fc57a9c --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/src/components/AddTodoItem.svelte @@ -0,0 +1,17 @@ + + +{#await items then _items} + {#each _items as { id, text }, index (id)} + + {:else} + No items yet. + {/each} +{/await} diff --git a/examples/projects/video04/code/svelte-todo-08/src/components/TodoItem.svelte b/examples/projects/video04/code/svelte-todo-08/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce55d94 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/src/components/TodoItem.svelte @@ -0,0 +1,7 @@ + + +
+

{title}

+
\ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-08/src/main.js b/examples/projects/video04/code/svelte-todo-08/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-08/src/utils/format.js b/examples/projects/video04/code/svelte-todo-08/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-08/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-08/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-08/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-09/.gitignore b/examples/projects/video04/code/svelte-todo-09/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-09/README.md b/examples/projects/video04/code/svelte-todo-09/README.md new file mode 100644 index 0000000..40d8421 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/README.md @@ -0,0 +1,5 @@ +# Демонстрация работы с блоком `{#await}` + +Упрощение внутреннего содержания блока. +Использование `{:then}`. +Демонстрация использования `{:catch}`. diff --git a/examples/projects/video04/code/svelte-todo-09/package.json b/examples/projects/video04/code/svelte-todo-09/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-09/public/favicon.png b/examples/projects/video04/code/svelte-todo-09/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-09/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-09/public/global.css b/examples/projects/video04/code/svelte-todo-09/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-09/public/index.html b/examples/projects/video04/code/svelte-todo-09/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-09/rollup.config.js b/examples/projects/video04/code/svelte-todo-09/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-09/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-09/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-09/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-09/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..d35f413 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/src/components/AddTodoItem.svelte @@ -0,0 +1,21 @@ + + +{#await items} +

In progress...

+{:then _items} + {#each _items as { id, text }, index (id)} + + {:else} + No items yet. + {/each} +{:catch} + Error +{/await} diff --git a/examples/projects/video04/code/svelte-todo-09/src/components/TodoItem.svelte b/examples/projects/video04/code/svelte-todo-09/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce55d94 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/src/components/TodoItem.svelte @@ -0,0 +1,7 @@ + + +
+

{title}

+
\ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-09/src/main.js b/examples/projects/video04/code/svelte-todo-09/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-09/src/utils/format.js b/examples/projects/video04/code/svelte-todo-09/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-09/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-09/src/utils/getTodos.js new file mode 100644 index 0000000..011201e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-09/src/utils/getTodos.js @@ -0,0 +1,23 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve) => { + setTimeout(() => { + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-10/.gitignore b/examples/projects/video04/code/svelte-todo-10/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-10/README.md b/examples/projects/video04/code/svelte-todo-10/README.md new file mode 100644 index 0000000..42d24e4 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/README.md @@ -0,0 +1,5 @@ +# Демонстрация работы с блоком `{#await}` + +Моделирование ошибки. +Демонстрация использования `{:catch}`. +Использование функции `Promise.reject()`. diff --git a/examples/projects/video04/code/svelte-todo-10/package.json b/examples/projects/video04/code/svelte-todo-10/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-10/public/favicon.png b/examples/projects/video04/code/svelte-todo-10/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-10/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-10/public/global.css b/examples/projects/video04/code/svelte-todo-10/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-10/public/index.html b/examples/projects/video04/code/svelte-todo-10/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-10/rollup.config.js b/examples/projects/video04/code/svelte-todo-10/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-10/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-10/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-10/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-10/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..a761e10 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/src/components/AddTodoItem.svelte @@ -0,0 +1,19 @@ + + +{#await items} +

In progress...

+{:then _items} + {#each _items as { id, text }, index (id)} + + {:else} + No items yet. + {/each} +{:catch} + Error +{/await} diff --git a/examples/projects/video04/code/svelte-todo-10/src/components/TodoItem.svelte b/examples/projects/video04/code/svelte-todo-10/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce55d94 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/src/components/TodoItem.svelte @@ -0,0 +1,7 @@ + + +
+

{title}

+
\ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-10/src/main.js b/examples/projects/video04/code/svelte-todo-10/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-10/src/utils/format.js b/examples/projects/video04/code/svelte-todo-10/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-10/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-10/src/utils/getTodos.js new file mode 100644 index 0000000..8e2d687 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-10/src/utils/getTodos.js @@ -0,0 +1,24 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + reject() + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-11/.gitignore b/examples/projects/video04/code/svelte-todo-11/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-11/README.md b/examples/projects/video04/code/svelte-todo-11/README.md new file mode 100644 index 0000000..ef8feda --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/README.md @@ -0,0 +1,4 @@ +# Демонстрация работы с блоком `{#await}` + +Моделирование ошибки. +Отоброжение сообщения параметра функции `Promise.reject()` в блоке `{#catch}`. diff --git a/examples/projects/video04/code/svelte-todo-11/package.json b/examples/projects/video04/code/svelte-todo-11/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-11/public/favicon.png b/examples/projects/video04/code/svelte-todo-11/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-11/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-11/public/global.css b/examples/projects/video04/code/svelte-todo-11/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-11/public/index.html b/examples/projects/video04/code/svelte-todo-11/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-11/rollup.config.js b/examples/projects/video04/code/svelte-todo-11/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-11/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-11/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-11/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-11/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..3135f7a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/src/components/AddTodoItem.svelte @@ -0,0 +1,19 @@ + + +{#await items} +

In progress...

+{:then _items} + {#each _items as { id, text }, index (id)} + + {:else} + No items yet. + {/each} +{:catch error} + Error: { error.message } +{/await} diff --git a/examples/projects/video04/code/svelte-todo-11/src/components/TodoItem.svelte b/examples/projects/video04/code/svelte-todo-11/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce55d94 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/src/components/TodoItem.svelte @@ -0,0 +1,7 @@ + + +
+

{title}

+
\ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-11/src/main.js b/examples/projects/video04/code/svelte-todo-11/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-11/src/utils/format.js b/examples/projects/video04/code/svelte-todo-11/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-11/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-11/src/utils/getTodos.js new file mode 100644 index 0000000..9586747 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-11/src/utils/getTodos.js @@ -0,0 +1,24 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error('Error 500')) + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-12/.gitignore b/examples/projects/video04/code/svelte-todo-12/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video04/code/svelte-todo-12/README.md b/examples/projects/video04/code/svelte-todo-12/README.md new file mode 100644 index 0000000..3108f46 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/README.md @@ -0,0 +1,4 @@ +# Демонстрация работы с блоком `{#key}` + +Блок `{#key}` служит для пересоздания участка, который находится внутри данного блока, +когда меняется значение отслеживаемой переменной. diff --git a/examples/projects/video04/code/svelte-todo-12/package.json b/examples/projects/video04/code/svelte-todo-12/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video04/code/svelte-todo-12/public/favicon.png b/examples/projects/video04/code/svelte-todo-12/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video04/code/svelte-todo-12/public/favicon.png differ diff --git a/examples/projects/video04/code/svelte-todo-12/public/global.css b/examples/projects/video04/code/svelte-todo-12/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video04/code/svelte-todo-12/public/index.html b/examples/projects/video04/code/svelte-todo-12/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video04/code/svelte-todo-12/rollup.config.js b/examples/projects/video04/code/svelte-todo-12/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video04/code/svelte-todo-12/scripts/setupTypeScript.js b/examples/projects/video04/code/svelte-todo-12/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-12/src/components/AddTodoItem.svelte b/examples/projects/video04/code/svelte-todo-12/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..72a276b --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/src/components/AddTodoItem.svelte @@ -0,0 +1,31 @@ + + +{#await items} +

In progress...

+{:then _items} + {#each _items as { id, text }, index (id)} + + {:else} + No items yet. + {/each} +{:catch error} + Error: { error.message } +{/await} + +{#key items} + {#await items then _items} +
+ {`Number of Items = ${_items.length}`} +
+ {:catch error} +
+ No items +
+ {/await} +{/key} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-12/src/components/TodoItem.svelte b/examples/projects/video04/code/svelte-todo-12/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce55d94 --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/src/components/TodoItem.svelte @@ -0,0 +1,7 @@ + + +
+

{title}

+
\ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-12/src/main.js b/examples/projects/video04/code/svelte-todo-12/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-12/src/utils/format.js b/examples/projects/video04/code/svelte-todo-12/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video04/code/svelte-todo-12/src/utils/getTodos.js b/examples/projects/video04/code/svelte-todo-12/src/utils/getTodos.js new file mode 100644 index 0000000..ffaacee --- /dev/null +++ b/examples/projects/video04/code/svelte-todo-12/src/utils/getTodos.js @@ -0,0 +1,26 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + if(Math.round(Math.random())){ + reject(new Error('Error 500')) + } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video05/README.md b/examples/projects/video05/README.md new file mode 100644 index 0000000..8ca5695 --- /dev/null +++ b/examples/projects/video05/README.md @@ -0,0 +1,19 @@ +# События и обработка событий + +[![Как работать с событиями в Svelte? video](https://img.youtube.com/vi/f1i-9RdxDCc/0.jpg)](https://youtu.be/f1i-9RdxDCc "Как работать с событиями в Svelte?") + +В этом уроке по Svelte рассматриваем работу с событиями в Svelte, а именно директиву `on`, модификаторы событий, переброс событий, `createEventDispatcher` и т.д. + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) +2. [Пример №2](code/svelte-todo-02) +3. [Пример №3](code/svelte-todo-03) +4. [Пример №4](code/svelte-todo-04) +5. [Пример №5](code/svelte-todo-05) diff --git a/examples/projects/video05/code/svelte-todo-01/.gitignore b/examples/projects/video05/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video05/code/svelte-todo-01/README.md b/examples/projects/video05/code/svelte-todo-01/README.md new file mode 100644 index 0000000..b61738e --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/README.md @@ -0,0 +1,4 @@ +# Демонстрация работы с методами `on` + +Добавление событий и вывод результатов работы на консоль. +Стилизация элементов TodoItem. \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-01/package.json b/examples/projects/video05/code/svelte-todo-01/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video05/code/svelte-todo-01/public/favicon.png b/examples/projects/video05/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video05/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video05/code/svelte-todo-01/public/global.css b/examples/projects/video05/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video05/code/svelte-todo-01/public/index.html b/examples/projects/video05/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video05/code/svelte-todo-01/rollup.config.js b/examples/projects/video05/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video05/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video05/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-01/src/components/AddTodoItem.svelte b/examples/projects/video05/code/svelte-todo-01/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..652c2a4 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/src/components/AddTodoItem.svelte @@ -0,0 +1,49 @@ + + +
+ + + +
+ +{#each items as { id, text }, index (id)} + +{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video05/code/svelte-todo-01/src/components/TodoItem.svelte b/examples/projects/video05/code/svelte-todo-01/src/components/TodoItem.svelte new file mode 100644 index 0000000..a0cb317 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/src/components/TodoItem.svelte @@ -0,0 +1,43 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-01/src/main.js b/examples/projects/video05/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-01/src/utils/format.js b/examples/projects/video05/code/svelte-todo-01/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-01/src/utils/getTodos.js b/examples/projects/video05/code/svelte-todo-01/src/utils/getTodos.js new file mode 100644 index 0000000..45366bf --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-01/src/utils/getTodos.js @@ -0,0 +1,26 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-02/.gitignore b/examples/projects/video05/code/svelte-todo-02/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video05/code/svelte-todo-02/README.md b/examples/projects/video05/code/svelte-todo-02/README.md new file mode 100644 index 0000000..a2f6bb4 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/README.md @@ -0,0 +1,5 @@ +# Демонстрация работы с методами `on` + +- Добавление анонимного обработчика события (inline-функцию). +- Добавление нескольких обработчиков событий одному компоненту. +- Примеры использования модификаторов событий. [Документация](https://ru.svelte.dev/docs#on_element_event). diff --git a/examples/projects/video05/code/svelte-todo-02/package.json b/examples/projects/video05/code/svelte-todo-02/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video05/code/svelte-todo-02/public/favicon.png b/examples/projects/video05/code/svelte-todo-02/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video05/code/svelte-todo-02/public/favicon.png differ diff --git a/examples/projects/video05/code/svelte-todo-02/public/global.css b/examples/projects/video05/code/svelte-todo-02/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video05/code/svelte-todo-02/public/index.html b/examples/projects/video05/code/svelte-todo-02/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video05/code/svelte-todo-02/rollup.config.js b/examples/projects/video05/code/svelte-todo-02/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video05/code/svelte-todo-02/scripts/setupTypeScript.js b/examples/projects/video05/code/svelte-todo-02/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-02/src/components/AddTodoItem.svelte b/examples/projects/video05/code/svelte-todo-02/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..652c2a4 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/src/components/AddTodoItem.svelte @@ -0,0 +1,49 @@ + + +
+ + + +
+ +{#each items as { id, text }, index (id)} + +{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video05/code/svelte-todo-02/src/components/TodoItem.svelte b/examples/projects/video05/code/svelte-todo-02/src/components/TodoItem.svelte new file mode 100644 index 0000000..d1193a2 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/src/components/TodoItem.svelte @@ -0,0 +1,46 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-02/src/main.js b/examples/projects/video05/code/svelte-todo-02/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-02/src/utils/format.js b/examples/projects/video05/code/svelte-todo-02/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-02/src/utils/getTodos.js b/examples/projects/video05/code/svelte-todo-02/src/utils/getTodos.js new file mode 100644 index 0000000..45366bf --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-02/src/utils/getTodos.js @@ -0,0 +1,26 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-03/.gitignore b/examples/projects/video05/code/svelte-todo-03/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video05/code/svelte-todo-03/README.md b/examples/projects/video05/code/svelte-todo-03/README.md new file mode 100644 index 0000000..a2f6bb4 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/README.md @@ -0,0 +1,5 @@ +# Демонстрация работы с методами `on` + +- Добавление анонимного обработчика события (inline-функцию). +- Добавление нескольких обработчиков событий одному компоненту. +- Примеры использования модификаторов событий. [Документация](https://ru.svelte.dev/docs#on_element_event). diff --git a/examples/projects/video05/code/svelte-todo-03/package.json b/examples/projects/video05/code/svelte-todo-03/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video05/code/svelte-todo-03/public/favicon.png b/examples/projects/video05/code/svelte-todo-03/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video05/code/svelte-todo-03/public/favicon.png differ diff --git a/examples/projects/video05/code/svelte-todo-03/public/global.css b/examples/projects/video05/code/svelte-todo-03/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video05/code/svelte-todo-03/public/index.html b/examples/projects/video05/code/svelte-todo-03/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video05/code/svelte-todo-03/rollup.config.js b/examples/projects/video05/code/svelte-todo-03/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video05/code/svelte-todo-03/scripts/setupTypeScript.js b/examples/projects/video05/code/svelte-todo-03/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+

Hello {name}!

+

Visit the Svelte tutorial to learn how to build Svelte apps.

+
+ + + + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-03/src/components/AddTodoItem.svelte b/examples/projects/video05/code/svelte-todo-03/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..652c2a4 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/src/components/AddTodoItem.svelte @@ -0,0 +1,49 @@ + + +
+ + + +
+ +{#each items as { id, text }, index (id)} + +{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video05/code/svelte-todo-03/src/components/TodoItem.svelte b/examples/projects/video05/code/svelte-todo-03/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce03f2e --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/src/components/TodoItem.svelte @@ -0,0 +1,45 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-03/src/main.js b/examples/projects/video05/code/svelte-todo-03/src/main.js new file mode 100644 index 0000000..d6cacbb --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/src/main.js @@ -0,0 +1,10 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + props: { + name: 'world' + } +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-03/src/utils/format.js b/examples/projects/video05/code/svelte-todo-03/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-03/src/utils/getTodos.js b/examples/projects/video05/code/svelte-todo-03/src/utils/getTodos.js new file mode 100644 index 0000000..45366bf --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-03/src/utils/getTodos.js @@ -0,0 +1,26 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-04/.gitignore b/examples/projects/video05/code/svelte-todo-04/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video05/code/svelte-todo-04/README.md b/examples/projects/video05/code/svelte-todo-04/README.md new file mode 100644 index 0000000..8137e7f --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/README.md @@ -0,0 +1,5 @@ +# Демонстрация работы с методами `on` + +- Рефакторинг. Перенесение части кода из `AddTodoItem` в `App`. +- Реализация передачи событий от дочерних элементов к родительским. Импорт функции `createEventDispatcher`. Использование события [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). +- Создание компонента `Form`, который объединяет input и button. \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-04/package.json b/examples/projects/video05/code/svelte-todo-04/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video05/code/svelte-todo-04/public/favicon.png b/examples/projects/video05/code/svelte-todo-04/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video05/code/svelte-todo-04/public/favicon.png differ diff --git a/examples/projects/video05/code/svelte-todo-04/public/global.css b/examples/projects/video05/code/svelte-todo-04/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video05/code/svelte-todo-04/public/index.html b/examples/projects/video05/code/svelte-todo-04/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video05/code/svelte-todo-04/rollup.config.js b/examples/projects/video05/code/svelte-todo-04/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video05/code/svelte-todo-04/scripts/setupTypeScript.js b/examples/projects/video05/code/svelte-todo-04/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + +{#each items as { id, text }, index (id)} +
+ +
+{:else} + No items yet. +{/each} + + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-04/src/components/AddTodoItem.svelte b/examples/projects/video05/code/svelte-todo-04/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..1e46a1f --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/src/components/AddTodoItem.svelte @@ -0,0 +1,14 @@ + + +
diff --git a/examples/projects/video05/code/svelte-todo-04/src/components/Form.svelte b/examples/projects/video05/code/svelte-todo-04/src/components/Form.svelte new file mode 100644 index 0000000..9b1b416 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/src/components/Form.svelte @@ -0,0 +1,35 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-04/src/components/TodoItem.svelte b/examples/projects/video05/code/svelte-todo-04/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce03f2e --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/src/components/TodoItem.svelte @@ -0,0 +1,45 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-04/src/main.js b/examples/projects/video05/code/svelte-todo-04/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-04/src/utils/format.js b/examples/projects/video05/code/svelte-todo-04/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-04/src/utils/getTodos.js b/examples/projects/video05/code/svelte-todo-04/src/utils/getTodos.js new file mode 100644 index 0000000..45366bf --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-04/src/utils/getTodos.js @@ -0,0 +1,26 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-05/.gitignore b/examples/projects/video05/code/svelte-todo-05/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video05/code/svelte-todo-05/README.md b/examples/projects/video05/code/svelte-todo-05/README.md new file mode 100644 index 0000000..f09b7ef --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/README.md @@ -0,0 +1,3 @@ +# Демонстрация работы с методами `on` + +- Использование сокращенной записи для проброски события `add` в родительский компонент. \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-05/package.json b/examples/projects/video05/code/svelte-todo-05/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video05/code/svelte-todo-05/public/favicon.png b/examples/projects/video05/code/svelte-todo-05/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video05/code/svelte-todo-05/public/favicon.png differ diff --git a/examples/projects/video05/code/svelte-todo-05/public/global.css b/examples/projects/video05/code/svelte-todo-05/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video05/code/svelte-todo-05/public/index.html b/examples/projects/video05/code/svelte-todo-05/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video05/code/svelte-todo-05/rollup.config.js b/examples/projects/video05/code/svelte-todo-05/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video05/code/svelte-todo-05/scripts/setupTypeScript.js b/examples/projects/video05/code/svelte-todo-05/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + +{#each items as { id, text }, index (id)} +
+ +
+{:else} + No items yet. +{/each} + + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-05/src/components/AddTodoItem.svelte b/examples/projects/video05/code/svelte-todo-05/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..24357c6 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video05/code/svelte-todo-05/src/components/Form.svelte b/examples/projects/video05/code/svelte-todo-05/src/components/Form.svelte new file mode 100644 index 0000000..9b1b416 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/src/components/Form.svelte @@ -0,0 +1,35 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-05/src/components/TodoItem.svelte b/examples/projects/video05/code/svelte-todo-05/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce03f2e --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/src/components/TodoItem.svelte @@ -0,0 +1,45 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-05/src/main.js b/examples/projects/video05/code/svelte-todo-05/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-05/src/utils/format.js b/examples/projects/video05/code/svelte-todo-05/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video05/code/svelte-todo-05/src/utils/getTodos.js b/examples/projects/video05/code/svelte-todo-05/src/utils/getTodos.js new file mode 100644 index 0000000..45366bf --- /dev/null +++ b/examples/projects/video05/code/svelte-todo-05/src/utils/getTodos.js @@ -0,0 +1,26 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video06/README.md b/examples/projects/video06/README.md new file mode 100644 index 0000000..d721f78 --- /dev/null +++ b/examples/projects/video06/README.md @@ -0,0 +1,20 @@ +# Привязки (Bindings) + +[![Байндинги и Привязки - Svelte Bindings video](https://img.youtube.com/vi/hHAszJgyUMc/0.jpg)](https://youtu.be/hHAszJgyUMc "Байндинги и Привязки - Svelte Bindings") + +В этом уроке рассмотрим привязки в Svelte, синтаксис и директиву `bind:`, привязки к компонентам и т.д. + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) +2. [Пример №2](code/svelte-todo-02) +3. [Пример №3](code/svelte-todo-03) +4. [Пример №4](code/svelte-todo-04) +5. [Пример №5](code/svelte-todo-05) +6. [Пример №6](code/svelte-todo-06) diff --git a/examples/projects/video06/code/svelte-todo-01/.gitignore b/examples/projects/video06/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video06/code/svelte-todo-01/README.md b/examples/projects/video06/code/svelte-todo-01/README.md new file mode 100644 index 0000000..e6dc4a6 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/README.md @@ -0,0 +1,11 @@ +# Изменения свойств компонентов с пощью `bind` + +- Дочерние компоненты настраиваются родительскими компонентами. +- Родительские компоненты меняют свой свойсва с помощью событий в дочерних компонентах. +- `bind` - это изменение свойств с помощью событий с меньшим количеством кода. Изменения +будут работать, как в дочерних, так и в родительских компонентах. + +- Добавляем `bind` в компонент `Form` в элемент `input`. + + + diff --git a/examples/projects/video06/code/svelte-todo-01/package.json b/examples/projects/video06/code/svelte-todo-01/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video06/code/svelte-todo-01/public/favicon.png b/examples/projects/video06/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video06/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video06/code/svelte-todo-01/public/global.css b/examples/projects/video06/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video06/code/svelte-todo-01/public/index.html b/examples/projects/video06/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video06/code/svelte-todo-01/rollup.config.js b/examples/projects/video06/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video06/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video06/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + +{#each items as { id, text }, index (id)} +
+ +
+{:else} + No items yet. +{/each} + + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-01/src/components/AddTodoItem.svelte b/examples/projects/video06/code/svelte-todo-01/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..24357c6 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video06/code/svelte-todo-01/src/components/Form.svelte b/examples/projects/video06/code/svelte-todo-01/src/components/Form.svelte new file mode 100644 index 0000000..a4fd973 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/src/components/Form.svelte @@ -0,0 +1,35 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-01/src/components/TodoItem.svelte b/examples/projects/video06/code/svelte-todo-01/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce03f2e --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/src/components/TodoItem.svelte @@ -0,0 +1,45 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-01/src/main.js b/examples/projects/video06/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-01/src/utils/format.js b/examples/projects/video06/code/svelte-todo-01/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-01/src/utils/getTodos.js b/examples/projects/video06/code/svelte-todo-01/src/utils/getTodos.js new file mode 100644 index 0000000..45366bf --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-01/src/utils/getTodos.js @@ -0,0 +1,26 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-02/.gitignore b/examples/projects/video06/code/svelte-todo-02/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video06/code/svelte-todo-02/README.md b/examples/projects/video06/code/svelte-todo-02/README.md new file mode 100644 index 0000000..b4a3659 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/README.md @@ -0,0 +1,6 @@ +# Изменения свойств компонентов с пощью `bind` + +`bind` будет конвертировать значение `value` в зависимости от типа `input`. Если мы установим удалим тип `"number"`, +то значение будет строкового типа. + + diff --git a/examples/projects/video06/code/svelte-todo-02/package.json b/examples/projects/video06/code/svelte-todo-02/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video06/code/svelte-todo-02/public/favicon.png b/examples/projects/video06/code/svelte-todo-02/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video06/code/svelte-todo-02/public/favicon.png differ diff --git a/examples/projects/video06/code/svelte-todo-02/public/global.css b/examples/projects/video06/code/svelte-todo-02/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video06/code/svelte-todo-02/public/index.html b/examples/projects/video06/code/svelte-todo-02/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video06/code/svelte-todo-02/rollup.config.js b/examples/projects/video06/code/svelte-todo-02/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video06/code/svelte-todo-02/scripts/setupTypeScript.js b/examples/projects/video06/code/svelte-todo-02/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + +{#each items as { id, text }, index (id)} +
+ +
+{:else} + No items yet. +{/each} + + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-02/src/components/AddTodoItem.svelte b/examples/projects/video06/code/svelte-todo-02/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..24357c6 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video06/code/svelte-todo-02/src/components/Form.svelte b/examples/projects/video06/code/svelte-todo-02/src/components/Form.svelte new file mode 100644 index 0000000..4f1887b --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/src/components/Form.svelte @@ -0,0 +1,38 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-02/src/components/TodoItem.svelte b/examples/projects/video06/code/svelte-todo-02/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce03f2e --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/src/components/TodoItem.svelte @@ -0,0 +1,45 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-02/src/main.js b/examples/projects/video06/code/svelte-todo-02/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-02/src/utils/format.js b/examples/projects/video06/code/svelte-todo-02/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-02/src/utils/getTodos.js b/examples/projects/video06/code/svelte-todo-02/src/utils/getTodos.js new file mode 100644 index 0000000..45366bf --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-02/src/utils/getTodos.js @@ -0,0 +1,26 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-03/.gitignore b/examples/projects/video06/code/svelte-todo-03/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video06/code/svelte-todo-03/README.md b/examples/projects/video06/code/svelte-todo-03/README.md new file mode 100644 index 0000000..d1d602a --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/README.md @@ -0,0 +1,6 @@ +# Изменения свойств компонентов с пощью `bind` + +`bind` будет конвертировать значение `value` в зависимости от типа `input`. Если мы установим тип `"number"`, +то значение будет ковертировать в число. + + diff --git a/examples/projects/video06/code/svelte-todo-03/package.json b/examples/projects/video06/code/svelte-todo-03/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video06/code/svelte-todo-03/public/favicon.png b/examples/projects/video06/code/svelte-todo-03/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video06/code/svelte-todo-03/public/favicon.png differ diff --git a/examples/projects/video06/code/svelte-todo-03/public/global.css b/examples/projects/video06/code/svelte-todo-03/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video06/code/svelte-todo-03/public/index.html b/examples/projects/video06/code/svelte-todo-03/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video06/code/svelte-todo-03/rollup.config.js b/examples/projects/video06/code/svelte-todo-03/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video06/code/svelte-todo-03/scripts/setupTypeScript.js b/examples/projects/video06/code/svelte-todo-03/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + +{#each items as { id, text }, index (id)} +
+ +
+{:else} + No items yet. +{/each} + + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-03/src/components/AddTodoItem.svelte b/examples/projects/video06/code/svelte-todo-03/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..24357c6 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video06/code/svelte-todo-03/src/components/Form.svelte b/examples/projects/video06/code/svelte-todo-03/src/components/Form.svelte new file mode 100644 index 0000000..3b1d20c --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/src/components/Form.svelte @@ -0,0 +1,37 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-03/src/components/TodoItem.svelte b/examples/projects/video06/code/svelte-todo-03/src/components/TodoItem.svelte new file mode 100644 index 0000000..ce03f2e --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/src/components/TodoItem.svelte @@ -0,0 +1,45 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-03/src/main.js b/examples/projects/video06/code/svelte-todo-03/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-03/src/utils/format.js b/examples/projects/video06/code/svelte-todo-03/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-03/src/utils/getTodos.js b/examples/projects/video06/code/svelte-todo-03/src/utils/getTodos.js new file mode 100644 index 0000000..45366bf --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-03/src/utils/getTodos.js @@ -0,0 +1,26 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + { + id: uuid(), + text: `Todo item ${++counter}` + }, + ]) + }, 1000) + }) +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-04/.gitignore b/examples/projects/video06/code/svelte-todo-04/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video06/code/svelte-todo-04/README.md b/examples/projects/video06/code/svelte-todo-04/README.md new file mode 100644 index 0000000..6b6c459 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/README.md @@ -0,0 +1,7 @@ +# Изменения свойств компонентов с пощью `bind` + +- Добавим поле `done` в компоненте `App`, `getTodos` для каждого значения новой задачи. +- Добавим статистические данные компоненте `App` в форме - "число выполненнных заданий / общее количество заданий". +- Добавим поле `done` в компоненте `TodoItem`. + + diff --git a/examples/projects/video06/code/svelte-todo-04/package.json b/examples/projects/video06/code/svelte-todo-04/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video06/code/svelte-todo-04/public/favicon.png b/examples/projects/video06/code/svelte-todo-04/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video06/code/svelte-todo-04/public/favicon.png differ diff --git a/examples/projects/video06/code/svelte-todo-04/public/global.css b/examples/projects/video06/code/svelte-todo-04/public/global.css new file mode 100644 index 0000000..756a785 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/public/global.css @@ -0,0 +1,66 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} +label { + font-size: 28px; +} diff --git a/examples/projects/video06/code/svelte-todo-04/public/index.html b/examples/projects/video06/code/svelte-todo-04/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video06/code/svelte-todo-04/rollup.config.js b/examples/projects/video06/code/svelte-todo-04/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video06/code/svelte-todo-04/scripts/setupTypeScript.js b/examples/projects/video06/code/svelte-todo-04/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {items.filter(item => item.done).length} / {items.length} +
+ + +{#each items as { id, text, done }, index (id)} +
+ +
+{:else} + No items yet. +{/each} + + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-04/src/components/AddTodoItem.svelte b/examples/projects/video06/code/svelte-todo-04/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..24357c6 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video06/code/svelte-todo-04/src/components/Form.svelte b/examples/projects/video06/code/svelte-todo-04/src/components/Form.svelte new file mode 100644 index 0000000..07df1aa --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/src/components/Form.svelte @@ -0,0 +1,34 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-04/src/components/TodoItem.svelte b/examples/projects/video06/code/svelte-todo-04/src/components/TodoItem.svelte new file mode 100644 index 0000000..aab5229 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/src/components/TodoItem.svelte @@ -0,0 +1,42 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-04/src/main.js b/examples/projects/video06/code/svelte-todo-04/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-04/src/utils/format.js b/examples/projects/video06/code/svelte-todo-04/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-04/src/utils/getTodos.js b/examples/projects/video06/code/svelte-todo-04/src/utils/getTodos.js new file mode 100644 index 0000000..5bcb2c2 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-04/src/utils/getTodos.js @@ -0,0 +1,29 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}`, + done:false + }, + { + id: uuid(), + text: `Todo item ${++counter}`, + done: true + }, + { + id: uuid(), + text: `Todo item ${++counter}`, + done:false + }, + ]) + }, 500) + }) +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-05/.gitignore b/examples/projects/video06/code/svelte-todo-05/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video06/code/svelte-todo-05/README.md b/examples/projects/video06/code/svelte-todo-05/README.md new file mode 100644 index 0000000..5d24a9f --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/README.md @@ -0,0 +1,5 @@ +# Изменения свойств компонентов с пощью `bind` + +- Примеры связывания с помощью `bind`. Создание `Examples.svelte`. + + diff --git a/examples/projects/video06/code/svelte-todo-05/package.json b/examples/projects/video06/code/svelte-todo-05/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video06/code/svelte-todo-05/public/favicon.png b/examples/projects/video06/code/svelte-todo-05/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video06/code/svelte-todo-05/public/favicon.png differ diff --git a/examples/projects/video06/code/svelte-todo-05/public/global.css b/examples/projects/video06/code/svelte-todo-05/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video06/code/svelte-todo-05/public/index.html b/examples/projects/video06/code/svelte-todo-05/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video06/code/svelte-todo-05/rollup.config.js b/examples/projects/video06/code/svelte-todo-05/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video06/code/svelte-todo-05/scripts/setupTypeScript.js b/examples/projects/video06/code/svelte-todo-05/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + + +
+ {items.filter(item => item.done).length} / {items.length} +
+ + +{#each items as { id, text, done }, index (id)} +
+ +
+{:else} + No items yet. +{/each} + + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-05/src/components/AddTodoItem.svelte b/examples/projects/video06/code/svelte-todo-05/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..24357c6 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video06/code/svelte-todo-05/src/components/Examples.svelte b/examples/projects/video06/code/svelte-todo-05/src/components/Examples.svelte new file mode 100644 index 0000000..29c3dc3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/src/components/Examples.svelte @@ -0,0 +1,69 @@ + + +

Choose correct one:

+ +
+ {#each questionsReplies as {id, text} (id)} + + {/each} +
+Reply: {reply} + +
+ +
+ Text value = {textAreaValue} +
+ +
+ +
+ Selected: {text} +
+ +
+ + + +
+ Selected: {multiply_text} +
\ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-05/src/components/Form.svelte b/examples/projects/video06/code/svelte-todo-05/src/components/Form.svelte new file mode 100644 index 0000000..07df1aa --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/src/components/Form.svelte @@ -0,0 +1,34 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-05/src/components/TodoItem.svelte b/examples/projects/video06/code/svelte-todo-05/src/components/TodoItem.svelte new file mode 100644 index 0000000..aab5229 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/src/components/TodoItem.svelte @@ -0,0 +1,42 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-05/src/main.js b/examples/projects/video06/code/svelte-todo-05/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-05/src/utils/format.js b/examples/projects/video06/code/svelte-todo-05/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-05/src/utils/getTodos.js b/examples/projects/video06/code/svelte-todo-05/src/utils/getTodos.js new file mode 100644 index 0000000..5bcb2c2 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-05/src/utils/getTodos.js @@ -0,0 +1,29 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}`, + done:false + }, + { + id: uuid(), + text: `Todo item ${++counter}`, + done: true + }, + { + id: uuid(), + text: `Todo item ${++counter}`, + done:false + }, + ]) + }, 500) + }) +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-06/.gitignore b/examples/projects/video06/code/svelte-todo-06/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video06/code/svelte-todo-06/README.md b/examples/projects/video06/code/svelte-todo-06/README.md new file mode 100644 index 0000000..5019e55 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/README.md @@ -0,0 +1,5 @@ +# Изменения свойств компонентов с пощью `bind` + +- Пример связывания с помощью `bind:this`. +- [Media element bindings](https://svelte.dev/docs#Media_element_bindings). + diff --git a/examples/projects/video06/code/svelte-todo-06/package.json b/examples/projects/video06/code/svelte-todo-06/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video06/code/svelte-todo-06/public/favicon.png b/examples/projects/video06/code/svelte-todo-06/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video06/code/svelte-todo-06/public/favicon.png differ diff --git a/examples/projects/video06/code/svelte-todo-06/public/global.css b/examples/projects/video06/code/svelte-todo-06/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video06/code/svelte-todo-06/public/index.html b/examples/projects/video06/code/svelte-todo-06/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video06/code/svelte-todo-06/rollup.config.js b/examples/projects/video06/code/svelte-todo-06/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video06/code/svelte-todo-06/scripts/setupTypeScript.js b/examples/projects/video06/code/svelte-todo-06/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + + +
+ {items.filter(item => item.done).length} / {items.length} +
+ + +{#each items as { id, text, done }, index (id)} +
+ +
+{:else} + No items yet. +{/each} + + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-06/src/components/AddTodoItem.svelte b/examples/projects/video06/code/svelte-todo-06/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..24357c6 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video06/code/svelte-todo-06/src/components/Examples.svelte b/examples/projects/video06/code/svelte-todo-06/src/components/Examples.svelte new file mode 100644 index 0000000..4d2eb05 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/src/components/Examples.svelte @@ -0,0 +1,11 @@ + + +
+ +
\ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-06/src/components/Form.svelte b/examples/projects/video06/code/svelte-todo-06/src/components/Form.svelte new file mode 100644 index 0000000..07df1aa --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/src/components/Form.svelte @@ -0,0 +1,34 @@ + + +
+ + + +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-06/src/components/TodoItem.svelte b/examples/projects/video06/code/svelte-todo-06/src/components/TodoItem.svelte new file mode 100644 index 0000000..aab5229 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/src/components/TodoItem.svelte @@ -0,0 +1,42 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-06/src/main.js b/examples/projects/video06/code/svelte-todo-06/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-06/src/utils/format.js b/examples/projects/video06/code/svelte-todo-06/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video06/code/svelte-todo-06/src/utils/getTodos.js b/examples/projects/video06/code/svelte-todo-06/src/utils/getTodos.js new file mode 100644 index 0000000..5bcb2c2 --- /dev/null +++ b/examples/projects/video06/code/svelte-todo-06/src/utils/getTodos.js @@ -0,0 +1,29 @@ +import { v4 as uuid } from 'uuid'; + +export function getTodos() { + let counter = 0; + return new Promise((resolve, reject) => { + setTimeout(() => { + // if(Math.round(Math.random())){ + // reject(new Error('Error 500')) + // } + resolve([ + { + id: uuid(), + text: `Todo item ${++counter}`, + done:false + }, + { + id: uuid(), + text: `Todo item ${++counter}`, + done: true + }, + { + id: uuid(), + text: `Todo item ${++counter}`, + done:false + }, + ]) + }, 500) + }) +} \ No newline at end of file diff --git a/examples/projects/video07/README.md b/examples/projects/video07/README.md new file mode 100644 index 0000000..5274d69 --- /dev/null +++ b/examples/projects/video07/README.md @@ -0,0 +1,20 @@ +# Хранилище (Store) + +[![Хранилище Svelte Store video](https://img.youtube.com/vi/equxrqhb534/0.jpg)](https://youtu.be/equxrqhb534 "Хранилище Svelte Store") + +В этом уроке рассмотрим `store` в Svelte и разновидности хранилищ: `writable store` (хранилище для записи), `readable store` (хранилище только для чтения), `derived store` (производные хранилища) и `custom store` (пользовательские хранилища). + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) +2. [Пример №2](code/svelte-todo-02) +3. [Пример №3](code/svelte-todo-03) +4. [Пример №4](code/svelte-todo-04) +5. [Пример №5](code/svelte-todo-05) +6. [Пример №6](code/svelte-todo-06) diff --git a/examples/projects/video07/code/svelte-todo-01/.gitignore b/examples/projects/video07/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video07/code/svelte-todo-01/README.md b/examples/projects/video07/code/svelte-todo-01/README.md new file mode 100644 index 0000000..f81cdac --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/README.md @@ -0,0 +1,9 @@ +# `writable store` + +`writable store` - создаёт изменяемое хранилище. +Метод `set` просто устанавливает новое значение. +Метод `update` получает функцию в качестве параметра, у которой входящей параметр - старое значение. Данная функция возвращает новое значение. + +- Рефакторинг. Перенос работы со списками в `store`. "Подписались" (`subscribe`) на обновление. Создали обработчики обновления и удаления элементов списка дел при помощи метода `update`. + +- Реализация сброса (удаление) всех добавленных элементов с помощью функции `set`. diff --git a/examples/projects/video07/code/svelte-todo-01/package.json b/examples/projects/video07/code/svelte-todo-01/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video07/code/svelte-todo-01/public/favicon.png b/examples/projects/video07/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video07/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video07/code/svelte-todo-01/public/global.css b/examples/projects/video07/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video07/code/svelte-todo-01/public/index.html b/examples/projects/video07/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video07/code/svelte-todo-01/rollup.config.js b/examples/projects/video07/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video07/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video07/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {items.filter((item) => item.done).length} / {items.length} +
+ +{#each items as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video07/code/svelte-todo-01/src/components/AddTodoItem.svelte b/examples/projects/video07/code/svelte-todo-01/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video07/code/svelte-todo-01/src/components/Form.svelte b/examples/projects/video07/code/svelte-todo-01/src/components/Form.svelte new file mode 100644 index 0000000..a7bc788 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/src/components/Form.svelte @@ -0,0 +1,37 @@ + + +
+ + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-01/src/components/TodoItem.svelte b/examples/projects/video07/code/svelte-todo-01/src/components/TodoItem.svelte new file mode 100644 index 0000000..2a17d8e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/src/components/TodoItem.svelte @@ -0,0 +1,52 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-01/src/main.js b/examples/projects/video07/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-01/src/store/store.js b/examples/projects/video07/code/svelte-todo-01/src/store/store.js new file mode 100644 index 0000000..4245f65 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/src/store/store.js @@ -0,0 +1,3 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([]); \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-01/src/utils/format.js b/examples/projects/video07/code/svelte-todo-01/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-01/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-02/.gitignore b/examples/projects/video07/code/svelte-todo-02/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video07/code/svelte-todo-02/README.md b/examples/projects/video07/code/svelte-todo-02/README.md new file mode 100644 index 0000000..575f605 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/README.md @@ -0,0 +1,6 @@ +# `writable store` + +Обсуждение второго параметра функции`writable`. Это callback-функция, которая вызывается, когда количество +подписчиков меняется с `0` на `1`. Т.е. когда впервые вызывается функция `subscribe`. Эта callback-функция +возвращает другую функцию, которая вызовется, когда количество подписчиков уменьшиться с `1` до `0`. Она вызовется, когда произойдёт событие `onDestroy`. + diff --git a/examples/projects/video07/code/svelte-todo-02/package.json b/examples/projects/video07/code/svelte-todo-02/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video07/code/svelte-todo-02/public/favicon.png b/examples/projects/video07/code/svelte-todo-02/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video07/code/svelte-todo-02/public/favicon.png differ diff --git a/examples/projects/video07/code/svelte-todo-02/public/global.css b/examples/projects/video07/code/svelte-todo-02/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video07/code/svelte-todo-02/public/index.html b/examples/projects/video07/code/svelte-todo-02/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video07/code/svelte-todo-02/rollup.config.js b/examples/projects/video07/code/svelte-todo-02/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video07/code/svelte-todo-02/scripts/setupTypeScript.js b/examples/projects/video07/code/svelte-todo-02/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {items.filter((item) => item.done).length} / {items.length} +
+ +{#each items as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video07/code/svelte-todo-02/src/components/AddTodoItem.svelte b/examples/projects/video07/code/svelte-todo-02/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video07/code/svelte-todo-02/src/components/Form.svelte b/examples/projects/video07/code/svelte-todo-02/src/components/Form.svelte new file mode 100644 index 0000000..7fc63f7 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/src/components/Form.svelte @@ -0,0 +1,45 @@ + + +
+ + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-02/src/components/TodoItem.svelte b/examples/projects/video07/code/svelte-todo-02/src/components/TodoItem.svelte new file mode 100644 index 0000000..2a17d8e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/src/components/TodoItem.svelte @@ -0,0 +1,52 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-02/src/main.js b/examples/projects/video07/code/svelte-todo-02/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-02/src/store/store.js b/examples/projects/video07/code/svelte-todo-02/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-02/src/utils/format.js b/examples/projects/video07/code/svelte-todo-02/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-02/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-03/.gitignore b/examples/projects/video07/code/svelte-todo-03/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video07/code/svelte-todo-03/README.md b/examples/projects/video07/code/svelte-todo-03/README.md new file mode 100644 index 0000000..4dafc91 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/README.md @@ -0,0 +1,4 @@ +# `writable store` + +Использование `store`-переменных. Демонстрация работы с автоподпиской. + diff --git a/examples/projects/video07/code/svelte-todo-03/package.json b/examples/projects/video07/code/svelte-todo-03/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video07/code/svelte-todo-03/public/favicon.png b/examples/projects/video07/code/svelte-todo-03/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video07/code/svelte-todo-03/public/favicon.png differ diff --git a/examples/projects/video07/code/svelte-todo-03/public/global.css b/examples/projects/video07/code/svelte-todo-03/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video07/code/svelte-todo-03/public/index.html b/examples/projects/video07/code/svelte-todo-03/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video07/code/svelte-todo-03/rollup.config.js b/examples/projects/video07/code/svelte-todo-03/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video07/code/svelte-todo-03/scripts/setupTypeScript.js b/examples/projects/video07/code/svelte-todo-03/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoItems.filter((item) => item.done).length} / {$todoItems.length} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video07/code/svelte-todo-03/src/components/AddTodoItem.svelte b/examples/projects/video07/code/svelte-todo-03/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video07/code/svelte-todo-03/src/components/Form.svelte b/examples/projects/video07/code/svelte-todo-03/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-03/src/components/TodoItem.svelte b/examples/projects/video07/code/svelte-todo-03/src/components/TodoItem.svelte new file mode 100644 index 0000000..2a17d8e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/src/components/TodoItem.svelte @@ -0,0 +1,52 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-03/src/main.js b/examples/projects/video07/code/svelte-todo-03/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-03/src/store/store.js b/examples/projects/video07/code/svelte-todo-03/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-03/src/utils/format.js b/examples/projects/video07/code/svelte-todo-03/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-03/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-04/.gitignore b/examples/projects/video07/code/svelte-todo-04/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video07/code/svelte-todo-04/README.md b/examples/projects/video07/code/svelte-todo-04/README.md new file mode 100644 index 0000000..fd6cd9f --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/README.md @@ -0,0 +1,6 @@ +# `readable store` + +Хранение последнего положения мыши. + +Функция `readable`. Первый аргумент - начальный значения, второй аргумент - функция для изменения данных `store`. + diff --git a/examples/projects/video07/code/svelte-todo-04/package.json b/examples/projects/video07/code/svelte-todo-04/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video07/code/svelte-todo-04/public/favicon.png b/examples/projects/video07/code/svelte-todo-04/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video07/code/svelte-todo-04/public/favicon.png differ diff --git a/examples/projects/video07/code/svelte-todo-04/public/global.css b/examples/projects/video07/code/svelte-todo-04/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video07/code/svelte-todo-04/public/index.html b/examples/projects/video07/code/svelte-todo-04/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video07/code/svelte-todo-04/rollup.config.js b/examples/projects/video07/code/svelte-todo-04/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video07/code/svelte-todo-04/scripts/setupTypeScript.js b/examples/projects/video07/code/svelte-todo-04/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +{JSON.stringify($mousePosition)} + + diff --git a/examples/projects/video07/code/svelte-todo-04/src/components/AddTodoItem.svelte b/examples/projects/video07/code/svelte-todo-04/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video07/code/svelte-todo-04/src/components/Form.svelte b/examples/projects/video07/code/svelte-todo-04/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-04/src/components/TodoItem.svelte b/examples/projects/video07/code/svelte-todo-04/src/components/TodoItem.svelte new file mode 100644 index 0000000..2a17d8e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/src/components/TodoItem.svelte @@ -0,0 +1,52 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-04/src/main.js b/examples/projects/video07/code/svelte-todo-04/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-04/src/store/mousePosition.js b/examples/projects/video07/code/svelte-todo-04/src/store/mousePosition.js new file mode 100644 index 0000000..52f298f --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/src/store/mousePosition.js @@ -0,0 +1,21 @@ +import {readable} from 'svelte/store'; + +export const mousePosition = readable( + { + x: 0, + y: 0 + }, (set) => { + const handler = event => { + set( + { + x: event.clientX, + y: event.clientY + } + ); + }; + + document.addEventListener('mousemove', handler); + + return () => document.removeEventListener('mousemove', handler); + } + ); \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-04/src/store/store.js b/examples/projects/video07/code/svelte-todo-04/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-04/src/utils/format.js b/examples/projects/video07/code/svelte-todo-04/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-04/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-05/.gitignore b/examples/projects/video07/code/svelte-todo-05/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video07/code/svelte-todo-05/README.md b/examples/projects/video07/code/svelte-todo-05/README.md new file mode 100644 index 0000000..c1492cd --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/README.md @@ -0,0 +1,7 @@ +# `derived store` + +`derived store` создаются на основе других хранилищ. +Будем показывать статистические данные по состоянию выполненых дел. + + + diff --git a/examples/projects/video07/code/svelte-todo-05/package.json b/examples/projects/video07/code/svelte-todo-05/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video07/code/svelte-todo-05/public/favicon.png b/examples/projects/video07/code/svelte-todo-05/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video07/code/svelte-todo-05/public/favicon.png differ diff --git a/examples/projects/video07/code/svelte-todo-05/public/global.css b/examples/projects/video07/code/svelte-todo-05/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video07/code/svelte-todo-05/public/index.html b/examples/projects/video07/code/svelte-todo-05/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video07/code/svelte-todo-05/rollup.config.js b/examples/projects/video07/code/svelte-todo-05/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video07/code/svelte-todo-05/scripts/setupTypeScript.js b/examples/projects/video07/code/svelte-todo-05/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video07/code/svelte-todo-05/src/components/AddTodoItem.svelte b/examples/projects/video07/code/svelte-todo-05/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video07/code/svelte-todo-05/src/components/Form.svelte b/examples/projects/video07/code/svelte-todo-05/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-05/src/components/TodoItem.svelte b/examples/projects/video07/code/svelte-todo-05/src/components/TodoItem.svelte new file mode 100644 index 0000000..2a17d8e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/src/components/TodoItem.svelte @@ -0,0 +1,52 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-05/src/main.js b/examples/projects/video07/code/svelte-todo-05/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-05/src/store/store.js b/examples/projects/video07/code/svelte-todo-05/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-05/src/store/todoStats.js b/examples/projects/video07/code/svelte-todo-05/src/store/todoStats.js new file mode 100644 index 0000000..1314e2c --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './store'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video07/code/svelte-todo-05/src/utils/format.js b/examples/projects/video07/code/svelte-todo-05/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-05/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-06/.gitignore b/examples/projects/video07/code/svelte-todo-06/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video07/code/svelte-todo-06/README.md b/examples/projects/video07/code/svelte-todo-06/README.md new file mode 100644 index 0000000..51f59d6 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/README.md @@ -0,0 +1,7 @@ +# Функция `get` + +Функция `get` позволяет подписываться на хранилище, получать значение и отписываться. +Эта функция ресурсоёмкая, поэтому её не рекомендуют использовать в критических секциях кода (где важна производительность). + + + diff --git a/examples/projects/video07/code/svelte-todo-06/package.json b/examples/projects/video07/code/svelte-todo-06/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video07/code/svelte-todo-06/public/favicon.png b/examples/projects/video07/code/svelte-todo-06/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video07/code/svelte-todo-06/public/favicon.png differ diff --git a/examples/projects/video07/code/svelte-todo-06/public/global.css b/examples/projects/video07/code/svelte-todo-06/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video07/code/svelte-todo-06/public/index.html b/examples/projects/video07/code/svelte-todo-06/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video07/code/svelte-todo-06/rollup.config.js b/examples/projects/video07/code/svelte-todo-06/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video07/code/svelte-todo-06/scripts/setupTypeScript.js b/examples/projects/video07/code/svelte-todo-06/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+
+ Todo Items: + {JSON.stringify(get(todoItems))} +
+
+ Todo Stats: + {JSON.stringify(get(todoStats))} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video07/code/svelte-todo-06/src/components/AddTodoItem.svelte b/examples/projects/video07/code/svelte-todo-06/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video07/code/svelte-todo-06/src/components/Form.svelte b/examples/projects/video07/code/svelte-todo-06/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-06/src/components/TodoItem.svelte b/examples/projects/video07/code/svelte-todo-06/src/components/TodoItem.svelte new file mode 100644 index 0000000..2a17d8e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/src/components/TodoItem.svelte @@ -0,0 +1,52 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-06/src/main.js b/examples/projects/video07/code/svelte-todo-06/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-06/src/store/store.js b/examples/projects/video07/code/svelte-todo-06/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-06/src/store/todoStats.js b/examples/projects/video07/code/svelte-todo-06/src/store/todoStats.js new file mode 100644 index 0000000..1314e2c --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './store'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video07/code/svelte-todo-06/src/utils/format.js b/examples/projects/video07/code/svelte-todo-06/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-06/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-07/.gitignore b/examples/projects/video07/code/svelte-todo-07/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video07/code/svelte-todo-07/README.md b/examples/projects/video07/code/svelte-todo-07/README.md new file mode 100644 index 0000000..c17139e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/README.md @@ -0,0 +1,7 @@ +# Custom `store` + +Для инкапсуляции работ по обновлению `store` весьма удобно разместить код по работе с ним в отдельный файл и вызывать +только отдельные функции, получая данные. + + + diff --git a/examples/projects/video07/code/svelte-todo-07/package.json b/examples/projects/video07/code/svelte-todo-07/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video07/code/svelte-todo-07/public/favicon.png b/examples/projects/video07/code/svelte-todo-07/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video07/code/svelte-todo-07/public/favicon.png differ diff --git a/examples/projects/video07/code/svelte-todo-07/public/global.css b/examples/projects/video07/code/svelte-todo-07/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video07/code/svelte-todo-07/public/index.html b/examples/projects/video07/code/svelte-todo-07/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video07/code/svelte-todo-07/rollup.config.js b/examples/projects/video07/code/svelte-todo-07/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video07/code/svelte-todo-07/scripts/setupTypeScript.js b/examples/projects/video07/code/svelte-todo-07/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video07/code/svelte-todo-07/src/components/AddTodoItem.svelte b/examples/projects/video07/code/svelte-todo-07/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video07/code/svelte-todo-07/src/components/Form.svelte b/examples/projects/video07/code/svelte-todo-07/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-07/src/components/TodoItem.svelte b/examples/projects/video07/code/svelte-todo-07/src/components/TodoItem.svelte new file mode 100644 index 0000000..2a17d8e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/src/components/TodoItem.svelte @@ -0,0 +1,52 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-07/src/main.js b/examples/projects/video07/code/svelte-todo-07/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-07/src/store/customStore.js b/examples/projects/video07/code/svelte-todo-07/src/store/customStore.js new file mode 100644 index 0000000..cf6d1bb --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/src/store/customStore.js @@ -0,0 +1,43 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-07/src/store/store.js b/examples/projects/video07/code/svelte-todo-07/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video07/code/svelte-todo-07/src/store/todoStats.js b/examples/projects/video07/code/svelte-todo-07/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video07/code/svelte-todo-07/src/utils/format.js b/examples/projects/video07/code/svelte-todo-07/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video07/code/svelte-todo-07/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/README.md b/examples/projects/video08/README.md new file mode 100644 index 0000000..0a62c33 --- /dev/null +++ b/examples/projects/video08/README.md @@ -0,0 +1,54 @@ +# Анимации и переходы (Motion, Transition and Animation) + +[![Анимации и переходы в Svelte - Motion, Transition and Animation video](https://img.youtube.com/vi/tx-o1QNHcCo/0.jpg)](https://youtu.be/tx-o1QNHcCo "Анимации и переходы в Svelte - Motion, Transition and Animation") + +В этом видео рассматриваем анимации в Svelte, а именно анимации значений (Svelte motion), анимации переходов (Svelte Transition), Svelte Animate, директивы transition, in, out и многое другое. + +## Motion +Анимация перехода значений (или просто переход значений). +Анимация атрибутов в зависимости от значения переменной. +``` +import { + tweened, spring +} from `svelte/motion` +``` + +## Transition +Анимация переходов - появление и исчезание. +``` +import { + fade, blur, fly, slide, scale, draw, crossfade +} from `svelte/transition` +``` + +## Animation +Анимация изменения порядка элементов блока each с ключём. +``` +import { + flip +} from `svelte/animate` +``` + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) +2. [Пример №2](code/svelte-todo-02) +3. [Пример №3](code/svelte-todo-03) +4. [Пример №4](code/svelte-todo-04) +5. [Пример №5](code/svelte-todo-05) +6. [Пример №6](code/svelte-todo-06) +7. [Пример №7](code/svelte-todo-07) +8. [Пример №8](code/svelte-todo-08) +9. [Пример №9](code/svelte-todo-09) +10. [Пример №10](code/svelte-todo-10) +11. [Пример №11](code/svelte-todo-11) +12. [Пример №12](code/svelte-todo-12) +13. [Пример №13](code/svelte-todo-13) +14. [Пример №14](code/svelte-todo-14) +15. [Пример №15](code/svelte-todo-15) diff --git a/examples/projects/video08/code/svelte-todo-01/.gitignore b/examples/projects/video08/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-01/README.md b/examples/projects/video08/code/svelte-todo-01/README.md new file mode 100644 index 0000000..9e4075c --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/README.md @@ -0,0 +1,7 @@ +# Svelte Motion . `tweened` + +Изменение цвета по событию. [easing](https://svelte.dev/examples#easing). + + + + diff --git a/examples/projects/video08/code/svelte-todo-01/package.json b/examples/projects/video08/code/svelte-todo-01/package.json new file mode 100644 index 0000000..c39f6ff --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/package.json @@ -0,0 +1,24 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-01/public/favicon.png b/examples/projects/video08/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-01/public/global.css b/examples/projects/video08/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-01/public/index.html b/examples/projects/video08/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-01/rollup.config.js b/examples/projects/video08/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-01/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-01/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-01/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-01/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-01/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-01/src/components/TodoItem.svelte new file mode 100644 index 0000000..43dc264 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/src/components/TodoItem.svelte @@ -0,0 +1,63 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-01/src/main.js b/examples/projects/video08/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-01/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-01/src/store/customStore.js new file mode 100644 index 0000000..cf6d1bb --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/src/store/customStore.js @@ -0,0 +1,43 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-01/src/store/store.js b/examples/projects/video08/code/svelte-todo-01/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-01/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-01/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-01/src/utils/format.js b/examples/projects/video08/code/svelte-todo-01/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-01/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-02/.gitignore b/examples/projects/video08/code/svelte-todo-02/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-02/README.md b/examples/projects/video08/code/svelte-todo-02/README.md new file mode 100644 index 0000000..ca7b9d0 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/README.md @@ -0,0 +1,10 @@ +# Svelte Motion. `tweened` + +Использование функционала библиотеки [d3-interpolate](https://github.com/d3/d3-interpolate). + +Установка [d3-interpolate](https://github.com/d3/d3-interpolate): `npm i d3-interpolate`. + + + + + diff --git a/examples/projects/video08/code/svelte-todo-02/package.json b/examples/projects/video08/code/svelte-todo-02/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-02/public/favicon.png b/examples/projects/video08/code/svelte-todo-02/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-02/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-02/public/global.css b/examples/projects/video08/code/svelte-todo-02/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-02/public/index.html b/examples/projects/video08/code/svelte-todo-02/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-02/rollup.config.js b/examples/projects/video08/code/svelte-todo-02/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-02/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-02/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-02/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-02/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-02/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-02/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-02/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-02/src/components/TodoItem.svelte new file mode 100644 index 0000000..9ae986a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/src/components/TodoItem.svelte @@ -0,0 +1,64 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-02/src/main.js b/examples/projects/video08/code/svelte-todo-02/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-02/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-02/src/store/customStore.js new file mode 100644 index 0000000..cf6d1bb --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/src/store/customStore.js @@ -0,0 +1,43 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-02/src/store/store.js b/examples/projects/video08/code/svelte-todo-02/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-02/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-02/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-02/src/utils/format.js b/examples/projects/video08/code/svelte-todo-02/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-02/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-03/.gitignore b/examples/projects/video08/code/svelte-todo-03/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-03/README.md b/examples/projects/video08/code/svelte-todo-03/README.md new file mode 100644 index 0000000..e61572b --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/README.md @@ -0,0 +1,11 @@ +# Svelte Motion. `tweened` + +Использование функционала библиотеки [d3-interpolate](https://github.com/d3/d3-interpolate). + +Установка [d3-interpolate](https://github.com/d3/d3-interpolate): `npm i d3-interpolate`. + +Использование сокращенной функции `interpolateLab`. + + + + diff --git a/examples/projects/video08/code/svelte-todo-03/package.json b/examples/projects/video08/code/svelte-todo-03/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-03/public/favicon.png b/examples/projects/video08/code/svelte-todo-03/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-03/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-03/public/global.css b/examples/projects/video08/code/svelte-todo-03/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-03/public/index.html b/examples/projects/video08/code/svelte-todo-03/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-03/rollup.config.js b/examples/projects/video08/code/svelte-todo-03/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-03/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-03/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-03/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-03/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-03/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-03/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-03/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-03/src/components/TodoItem.svelte new file mode 100644 index 0000000..529ac7e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/src/components/TodoItem.svelte @@ -0,0 +1,64 @@ + + +
+ +

{title}

+ +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-03/src/main.js b/examples/projects/video08/code/svelte-todo-03/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-03/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-03/src/store/customStore.js new file mode 100644 index 0000000..cf6d1bb --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/src/store/customStore.js @@ -0,0 +1,43 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-03/src/store/store.js b/examples/projects/video08/code/svelte-todo-03/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-03/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-03/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-03/src/utils/format.js b/examples/projects/video08/code/svelte-todo-03/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-03/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-04/.gitignore b/examples/projects/video08/code/svelte-todo-04/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-04/README.md b/examples/projects/video08/code/svelte-todo-04/README.md new file mode 100644 index 0000000..350f0ff --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/README.md @@ -0,0 +1,9 @@ +# Svelte Motion. `spring` + +Использование функционала библиотеки [d3-interpolate](https://github.com/d3/d3-interpolate). + +Реализация плавной анимации. + + + + diff --git a/examples/projects/video08/code/svelte-todo-04/package.json b/examples/projects/video08/code/svelte-todo-04/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-04/public/favicon.png b/examples/projects/video08/code/svelte-todo-04/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-04/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-04/public/global.css b/examples/projects/video08/code/svelte-todo-04/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-04/public/index.html b/examples/projects/video08/code/svelte-todo-04/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-04/rollup.config.js b/examples/projects/video08/code/svelte-todo-04/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-04/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-04/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-04/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-04/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-04/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-04/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-04/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-04/src/components/TodoItem.svelte new file mode 100644 index 0000000..564c7c0 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/src/components/TodoItem.svelte @@ -0,0 +1,102 @@ + +
+
+ +

{title}

+ +
+
+ + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-04/src/main.js b/examples/projects/video08/code/svelte-todo-04/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-04/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-04/src/store/customStore.js new file mode 100644 index 0000000..62c20ae --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/src/store/customStore.js @@ -0,0 +1,46 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-04/src/store/store.js b/examples/projects/video08/code/svelte-todo-04/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-04/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-04/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-04/src/utils/format.js b/examples/projects/video08/code/svelte-todo-04/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-04/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-05/.gitignore b/examples/projects/video08/code/svelte-todo-05/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-05/README.md b/examples/projects/video08/code/svelte-todo-05/README.md new file mode 100644 index 0000000..6904d05 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/README.md @@ -0,0 +1,11 @@ +# Svelte Motion. `spring` + +Использование функционала библиотеки [d3-interpolate](https://github.com/d3/d3-interpolate). + +Установка [d3-interpolate](https://github.com/d3/d3-interpolate): `npm i d3-interpolate`. + +Использование сокращенной функции `interpolateLab`. + + + + diff --git a/examples/projects/video08/code/svelte-todo-05/package.json b/examples/projects/video08/code/svelte-todo-05/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-05/public/favicon.png b/examples/projects/video08/code/svelte-todo-05/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-05/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-05/public/global.css b/examples/projects/video08/code/svelte-todo-05/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-05/public/index.html b/examples/projects/video08/code/svelte-todo-05/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-05/rollup.config.js b/examples/projects/video08/code/svelte-todo-05/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-05/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-05/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-05/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-05/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-05/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-05/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-05/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-05/src/components/TodoItem.svelte new file mode 100644 index 0000000..dd2ec50 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/src/components/TodoItem.svelte @@ -0,0 +1,102 @@ + +
+
+ +

{title}

+ +
+
+ + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-05/src/main.js b/examples/projects/video08/code/svelte-todo-05/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-05/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-05/src/store/customStore.js new file mode 100644 index 0000000..62c20ae --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/src/store/customStore.js @@ -0,0 +1,46 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-05/src/store/store.js b/examples/projects/video08/code/svelte-todo-05/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-05/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-05/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-05/src/utils/format.js b/examples/projects/video08/code/svelte-todo-05/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-05/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-06/.gitignore b/examples/projects/video08/code/svelte-todo-06/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-06/README.md b/examples/projects/video08/code/svelte-todo-06/README.md new file mode 100644 index 0000000..d31e9ba --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/README.md @@ -0,0 +1,6 @@ +# Transition - in/out + + + + + diff --git a/examples/projects/video08/code/svelte-todo-06/package.json b/examples/projects/video08/code/svelte-todo-06/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-06/public/favicon.png b/examples/projects/video08/code/svelte-todo-06/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-06/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-06/public/global.css b/examples/projects/video08/code/svelte-todo-06/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-06/public/index.html b/examples/projects/video08/code/svelte-todo-06/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-06/rollup.config.js b/examples/projects/video08/code/svelte-todo-06/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-06/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-06/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-06/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-06/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-06/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-06/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-06/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-06/src/components/TodoItem.svelte new file mode 100644 index 0000000..74eb83a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/src/components/TodoItem.svelte @@ -0,0 +1,71 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-06/src/main.js b/examples/projects/video08/code/svelte-todo-06/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-06/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-06/src/store/customStore.js new file mode 100644 index 0000000..62c20ae --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/src/store/customStore.js @@ -0,0 +1,46 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-06/src/store/store.js b/examples/projects/video08/code/svelte-todo-06/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-06/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-06/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-06/src/utils/format.js b/examples/projects/video08/code/svelte-todo-06/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-06/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-07/.gitignore b/examples/projects/video08/code/svelte-todo-07/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-07/README.md b/examples/projects/video08/code/svelte-todo-07/README.md new file mode 100644 index 0000000..ac0e97f --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/README.md @@ -0,0 +1,10 @@ +# Svelte Transition + +Появление и исчезание. + +## Стандартные переходы +`fade` - плавное появление нового элемента. [Документация по `fade`](https://svelte.dev/docs#fade) + + + + diff --git a/examples/projects/video08/code/svelte-todo-07/package.json b/examples/projects/video08/code/svelte-todo-07/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-07/public/favicon.png b/examples/projects/video08/code/svelte-todo-07/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-07/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-07/public/global.css b/examples/projects/video08/code/svelte-todo-07/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-07/public/index.html b/examples/projects/video08/code/svelte-todo-07/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-07/rollup.config.js b/examples/projects/video08/code/svelte-todo-07/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-07/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-07/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-07/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-07/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-07/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-07/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-07/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-07/src/components/TodoItem.svelte new file mode 100644 index 0000000..aac923f --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/src/components/TodoItem.svelte @@ -0,0 +1,72 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-07/src/main.js b/examples/projects/video08/code/svelte-todo-07/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-07/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-07/src/store/customStore.js new file mode 100644 index 0000000..62c20ae --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/src/store/customStore.js @@ -0,0 +1,46 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-07/src/store/store.js b/examples/projects/video08/code/svelte-todo-07/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-07/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-07/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-07/src/utils/format.js b/examples/projects/video08/code/svelte-todo-07/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-07/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-08/.gitignore b/examples/projects/video08/code/svelte-todo-08/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-08/README.md b/examples/projects/video08/code/svelte-todo-08/README.md new file mode 100644 index 0000000..cef1a65 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/README.md @@ -0,0 +1,3 @@ +# CSS-transition creation + + diff --git a/examples/projects/video08/code/svelte-todo-08/package.json b/examples/projects/video08/code/svelte-todo-08/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-08/public/favicon.png b/examples/projects/video08/code/svelte-todo-08/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-08/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-08/public/global.css b/examples/projects/video08/code/svelte-todo-08/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-08/public/index.html b/examples/projects/video08/code/svelte-todo-08/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-08/rollup.config.js b/examples/projects/video08/code/svelte-todo-08/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-08/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-08/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-08/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-08/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-08/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-08/src/components/Form.svelte new file mode 100644 index 0000000..abee254 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/src/components/Form.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-08/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-08/src/components/TodoItem.svelte new file mode 100644 index 0000000..5f17fc6 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/src/components/TodoItem.svelte @@ -0,0 +1,73 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-08/src/main.js b/examples/projects/video08/code/svelte-todo-08/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-08/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-08/src/store/customStore.js new file mode 100644 index 0000000..62c20ae --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/src/store/customStore.js @@ -0,0 +1,46 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-08/src/store/store.js b/examples/projects/video08/code/svelte-todo-08/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-08/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-08/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-08/src/transitions/skew.js b/examples/projects/video08/code/svelte-todo-08/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-08/src/utils/format.js b/examples/projects/video08/code/svelte-todo-08/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-08/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-09/.gitignore b/examples/projects/video08/code/svelte-todo-09/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-09/README.md b/examples/projects/video08/code/svelte-todo-09/README.md new file mode 100644 index 0000000..292e88c --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/README.md @@ -0,0 +1,5 @@ +# JavaScript-transition creation + +Запуск анимация с помощью инициализации переменной в функции `onMount`. + + diff --git a/examples/projects/video08/code/svelte-todo-09/package.json b/examples/projects/video08/code/svelte-todo-09/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-09/public/favicon.png b/examples/projects/video08/code/svelte-todo-09/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-09/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-09/public/global.css b/examples/projects/video08/code/svelte-todo-09/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-09/public/index.html b/examples/projects/video08/code/svelte-todo-09/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-09/rollup.config.js b/examples/projects/video08/code/svelte-todo-09/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-09/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-09/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-09/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-09/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-09/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-09/src/components/Form.svelte new file mode 100644 index 0000000..5b54723 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/src/components/Form.svelte @@ -0,0 +1,51 @@ + + +
+ {#if show} + + {/if} + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-09/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-09/src/components/TodoItem.svelte new file mode 100644 index 0000000..5f17fc6 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/src/components/TodoItem.svelte @@ -0,0 +1,73 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-09/src/main.js b/examples/projects/video08/code/svelte-todo-09/src/main.js new file mode 100644 index 0000000..d80e9a3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-09/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-09/src/store/customStore.js new file mode 100644 index 0000000..62c20ae --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/src/store/customStore.js @@ -0,0 +1,46 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-09/src/store/store.js b/examples/projects/video08/code/svelte-todo-09/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-09/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-09/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-09/src/transitions/skew.js b/examples/projects/video08/code/svelte-todo-09/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-09/src/transitions/typewriter.js b/examples/projects/video08/code/svelte-todo-09/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-09/src/utils/format.js b/examples/projects/video08/code/svelte-todo-09/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-09/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-10/.gitignore b/examples/projects/video08/code/svelte-todo-10/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-10/README.md b/examples/projects/video08/code/svelte-todo-10/README.md new file mode 100644 index 0000000..52edddc --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/README.md @@ -0,0 +1,5 @@ +# JavaScript-transition creation + +Использование параметра Svelte-компонента `intro`. + + diff --git a/examples/projects/video08/code/svelte-todo-10/package.json b/examples/projects/video08/code/svelte-todo-10/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-10/public/favicon.png b/examples/projects/video08/code/svelte-todo-10/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-10/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-10/public/global.css b/examples/projects/video08/code/svelte-todo-10/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-10/public/index.html b/examples/projects/video08/code/svelte-todo-10/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-10/rollup.config.js b/examples/projects/video08/code/svelte-todo-10/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-10/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-10/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-10/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-10/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-10/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-10/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-10/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-10/src/components/TodoItem.svelte new file mode 100644 index 0000000..5f17fc6 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/src/components/TodoItem.svelte @@ -0,0 +1,73 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-10/src/main.js b/examples/projects/video08/code/svelte-todo-10/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-10/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-10/src/store/customStore.js new file mode 100644 index 0000000..62c20ae --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/src/store/customStore.js @@ -0,0 +1,46 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-10/src/store/store.js b/examples/projects/video08/code/svelte-todo-10/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-10/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-10/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-10/src/transitions/skew.js b/examples/projects/video08/code/svelte-todo-10/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-10/src/transitions/typewriter.js b/examples/projects/video08/code/svelte-todo-10/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-10/src/utils/format.js b/examples/projects/video08/code/svelte-todo-10/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-10/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-11/.gitignore b/examples/projects/video08/code/svelte-todo-11/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-11/README.md b/examples/projects/video08/code/svelte-todo-11/README.md new file mode 100644 index 0000000..4f257bf --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/README.md @@ -0,0 +1,7 @@ +# Transition. События переходов + +- `on:introstart` - начало анимации при инициализации компонента +- `on:introend` - конец анимации при инициализации компонента +- `on:outrostart` - начало анимации при удалении компонента +- `on:outroend` - конец анимации при удалении компонента + diff --git a/examples/projects/video08/code/svelte-todo-11/package.json b/examples/projects/video08/code/svelte-todo-11/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-11/public/favicon.png b/examples/projects/video08/code/svelte-todo-11/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-11/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-11/public/global.css b/examples/projects/video08/code/svelte-todo-11/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-11/public/index.html b/examples/projects/video08/code/svelte-todo-11/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-11/rollup.config.js b/examples/projects/video08/code/svelte-todo-11/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-11/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-11/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-11/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-11/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-11/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-11/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-11/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-11/src/components/TodoItem.svelte new file mode 100644 index 0000000..6d9e004 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/src/components/TodoItem.svelte @@ -0,0 +1,76 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-11/src/main.js b/examples/projects/video08/code/svelte-todo-11/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-11/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-11/src/store/customStore.js new file mode 100644 index 0000000..62c20ae --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/src/store/customStore.js @@ -0,0 +1,46 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + const store = writable([]); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-11/src/store/store.js b/examples/projects/video08/code/svelte-todo-11/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-11/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-11/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-11/src/transitions/skew.js b/examples/projects/video08/code/svelte-todo-11/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-11/src/transitions/typewriter.js b/examples/projects/video08/code/svelte-todo-11/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-11/src/utils/format.js b/examples/projects/video08/code/svelte-todo-11/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-11/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-12/.gitignore b/examples/projects/video08/code/svelte-todo-12/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-12/README.md b/examples/projects/video08/code/svelte-todo-12/README.md new file mode 100644 index 0000000..a4d44e0 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/README.md @@ -0,0 +1,4 @@ +# Transition - Локальные переходы + + +[`transition:fn|local`](https://svelte.dev/docs#transition_fn) diff --git a/examples/projects/video08/code/svelte-todo-12/package.json b/examples/projects/video08/code/svelte-todo-12/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-12/public/favicon.png b/examples/projects/video08/code/svelte-todo-12/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-12/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-12/public/global.css b/examples/projects/video08/code/svelte-todo-12/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-12/public/index.html b/examples/projects/video08/code/svelte-todo-12/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-12/rollup.config.js b/examples/projects/video08/code/svelte-todo-12/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-12/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-12/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +{#each $todoItems as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+{:else} + No items yet. +{/each} + + diff --git a/examples/projects/video08/code/svelte-todo-12/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-12/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-12/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-12/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-12/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-12/src/components/TodoItem.svelte new file mode 100644 index 0000000..657bb71 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/src/components/TodoItem.svelte @@ -0,0 +1,76 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-12/src/main.js b/examples/projects/video08/code/svelte-todo-12/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-12/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-12/src/store/customStore.js new file mode 100644 index 0000000..14f0a12 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/src/store/customStore.js @@ -0,0 +1,52 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server` + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-12/src/store/store.js b/examples/projects/video08/code/svelte-todo-12/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-12/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-12/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-12/src/transitions/skew.js b/examples/projects/video08/code/svelte-todo-12/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-12/src/transitions/typewriter.js b/examples/projects/video08/code/svelte-todo-12/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-12/src/utils/format.js b/examples/projects/video08/code/svelte-todo-12/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-12/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-13/.gitignore b/examples/projects/video08/code/svelte-todo-13/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-13/README.md b/examples/projects/video08/code/svelte-todo-13/README.md new file mode 100644 index 0000000..0097e1a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/README.md @@ -0,0 +1,7 @@ +# Transition - отложенные переходы + +Отложенные переходы реализован с помощью функции crossfade. +Этот эффект помогат реализовывать переходы элемента из одной части приложения в другую. + +Разделим список на две части - незавершенные задачи и завершенные задачи. + diff --git a/examples/projects/video08/code/svelte-todo-13/package.json b/examples/projects/video08/code/svelte-todo-13/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-13/public/favicon.png b/examples/projects/video08/code/svelte-todo-13/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-13/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-13/public/global.css b/examples/projects/video08/code/svelte-todo-13/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-13/public/index.html b/examples/projects/video08/code/svelte-todo-13/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-13/rollup.config.js b/examples/projects/video08/code/svelte-todo-13/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-13/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-13/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ + +
+ + diff --git a/examples/projects/video08/code/svelte-todo-13/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-13/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-13/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-13/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-13/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-13/src/components/TodoItem.svelte new file mode 100644 index 0000000..4f50508 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/src/components/TodoItem.svelte @@ -0,0 +1,71 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-13/src/main.js b/examples/projects/video08/code/svelte-todo-13/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-13/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-13/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-13/src/store/store.js b/examples/projects/video08/code/svelte-todo-13/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-13/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-13/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-13/src/transitions/skew.js b/examples/projects/video08/code/svelte-todo-13/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-13/src/transitions/typewriter.js b/examples/projects/video08/code/svelte-todo-13/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-13/src/utils/format.js b/examples/projects/video08/code/svelte-todo-13/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-13/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-14/.gitignore b/examples/projects/video08/code/svelte-todo-14/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-14/README.md b/examples/projects/video08/code/svelte-todo-14/README.md new file mode 100644 index 0000000..4516d8f --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/README.md @@ -0,0 +1,7 @@ +# Transition - отложенные переходы + +Отложенные переходы реализован с помощью функции crossfade. +Этот эффект помогат реализовывать переходы элемента из одной части приложения в другую. + +Удалим иформацию об анимации во второй колонке. + diff --git a/examples/projects/video08/code/svelte-todo-14/package.json b/examples/projects/video08/code/svelte-todo-14/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-14/public/favicon.png b/examples/projects/video08/code/svelte-todo-14/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-14/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-14/public/global.css b/examples/projects/video08/code/svelte-todo-14/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-14/public/index.html b/examples/projects/video08/code/svelte-todo-14/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-14/rollup.config.js b/examples/projects/video08/code/svelte-todo-14/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-14/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-14/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ + +
+ + diff --git a/examples/projects/video08/code/svelte-todo-14/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-14/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-14/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-14/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-14/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-14/src/components/TodoItem.svelte new file mode 100644 index 0000000..4f50508 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/src/components/TodoItem.svelte @@ -0,0 +1,71 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-14/src/main.js b/examples/projects/video08/code/svelte-todo-14/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-14/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-14/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-14/src/store/store.js b/examples/projects/video08/code/svelte-todo-14/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-14/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-14/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-14/src/transitions/skew.js b/examples/projects/video08/code/svelte-todo-14/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-14/src/transitions/typewriter.js b/examples/projects/video08/code/svelte-todo-14/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-14/src/utils/format.js b/examples/projects/video08/code/svelte-todo-14/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-14/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-15/.gitignore b/examples/projects/video08/code/svelte-todo-15/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video08/code/svelte-todo-15/README.md b/examples/projects/video08/code/svelte-todo-15/README.md new file mode 100644 index 0000000..8f5bac6 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/README.md @@ -0,0 +1,3 @@ +# Animation + +[flip](https://svelte.dev/docs#flip). diff --git a/examples/projects/video08/code/svelte-todo-15/package.json b/examples/projects/video08/code/svelte-todo-15/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video08/code/svelte-todo-15/public/favicon.png b/examples/projects/video08/code/svelte-todo-15/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video08/code/svelte-todo-15/public/favicon.png differ diff --git a/examples/projects/video08/code/svelte-todo-15/public/global.css b/examples/projects/video08/code/svelte-todo-15/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video08/code/svelte-todo-15/public/index.html b/examples/projects/video08/code/svelte-todo-15/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video08/code/svelte-todo-15/rollup.config.js b/examples/projects/video08/code/svelte-todo-15/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video08/code/svelte-todo-15/scripts/setupTypeScript.js b/examples/projects/video08/code/svelte-todo-15/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ + +
+ + diff --git a/examples/projects/video08/code/svelte-todo-15/src/components/AddTodoItem.svelte b/examples/projects/video08/code/svelte-todo-15/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video08/code/svelte-todo-15/src/components/Form.svelte b/examples/projects/video08/code/svelte-todo-15/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-15/src/components/TodoItem.svelte b/examples/projects/video08/code/svelte-todo-15/src/components/TodoItem.svelte new file mode 100644 index 0000000..4f50508 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/src/components/TodoItem.svelte @@ -0,0 +1,71 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-15/src/main.js b/examples/projects/video08/code/svelte-todo-15/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-15/src/store/customStore.js b/examples/projects/video08/code/svelte-todo-15/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-15/src/store/store.js b/examples/projects/video08/code/svelte-todo-15/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-15/src/store/todoStats.js b/examples/projects/video08/code/svelte-todo-15/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video08/code/svelte-todo-15/src/transitions/skew.js b/examples/projects/video08/code/svelte-todo-15/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-15/src/transitions/typewriter.js b/examples/projects/video08/code/svelte-todo-15/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video08/code/svelte-todo-15/src/utils/format.js b/examples/projects/video08/code/svelte-todo-15/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video08/code/svelte-todo-15/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video09/README.md b/examples/projects/video09/README.md new file mode 100644 index 0000000..2452f1a --- /dev/null +++ b/examples/projects/video09/README.md @@ -0,0 +1,17 @@ +# Действия и директива use (Actions) + +[![Действия и директива use - Svelte Actions](https://img.youtube.com/vi/Eg18v8l1WdM/0.jpg)](https://youtu.be/Eg18v8l1WdM "Действия и директива use - Svelte Actions") + +В этом видео рассматриваем действия в Svelte, для чего они нужно и как ими пользоваться. Добавляем в проект директиву `use`, отправляем события из Действия и реализовываем функции Действий - `destroy` и `update`. + +Действие - это подолнительные возможности элементов. С их помощью можно вызывать всплывающие подсказки и реализовывать дополнительные действия. + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) diff --git a/examples/projects/video09/code/svelte-todo-01/.gitignore b/examples/projects/video09/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video09/code/svelte-todo-01/README.md b/examples/projects/video09/code/svelte-todo-01/README.md new file mode 100644 index 0000000..000b4b3 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/README.md @@ -0,0 +1,5 @@ +# Действия + +Реализуем перемещение элемента по экрану с помощью мыши. На основе этого примера можно сделать загрузгу картинок методом drag-and-drop. + +Действие описывается с помощью директивы `use`. diff --git a/examples/projects/video09/code/svelte-todo-01/package.json b/examples/projects/video09/code/svelte-todo-01/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video09/code/svelte-todo-01/public/favicon.png b/examples/projects/video09/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video09/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video09/code/svelte-todo-01/public/global.css b/examples/projects/video09/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video09/code/svelte-todo-01/public/index.html b/examples/projects/video09/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video09/code/svelte-todo-01/rollup.config.js b/examples/projects/video09/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video09/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video09/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ + +
+ + diff --git a/examples/projects/video09/code/svelte-todo-01/src/actions/draggable.js b/examples/projects/video09/code/svelte-todo-01/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video09/code/svelte-todo-01/src/components/AddTodoItem.svelte b/examples/projects/video09/code/svelte-todo-01/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video09/code/svelte-todo-01/src/components/Form.svelte b/examples/projects/video09/code/svelte-todo-01/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video09/code/svelte-todo-01/src/components/TodoItem.svelte b/examples/projects/video09/code/svelte-todo-01/src/components/TodoItem.svelte new file mode 100644 index 0000000..797d5c2 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/components/TodoItem.svelte @@ -0,0 +1,97 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video09/code/svelte-todo-01/src/main.js b/examples/projects/video09/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video09/code/svelte-todo-01/src/store/customStore.js b/examples/projects/video09/code/svelte-todo-01/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video09/code/svelte-todo-01/src/store/store.js b/examples/projects/video09/code/svelte-todo-01/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video09/code/svelte-todo-01/src/store/todoStats.js b/examples/projects/video09/code/svelte-todo-01/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video09/code/svelte-todo-01/src/transitions/skew.js b/examples/projects/video09/code/svelte-todo-01/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video09/code/svelte-todo-01/src/transitions/typewriter.js b/examples/projects/video09/code/svelte-todo-01/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video09/code/svelte-todo-01/src/utils/format.js b/examples/projects/video09/code/svelte-todo-01/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video09/code/svelte-todo-01/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video10/README.md b/examples/projects/video10/README.md new file mode 100644 index 0000000..92e3e33 --- /dev/null +++ b/examples/projects/video10/README.md @@ -0,0 +1,26 @@ +# Слоты - Svelte slots. Context Модуль - Svelte module context + +[![Слоты - Svelte slots. Context Модуль - Svelte module context](https://img.youtube.com/vi/BmvwzMRUBFM/0.jpg)](https://youtu.be/BmvwzMRUBFM "Слоты - Svelte slots. Context Модуль - Svelte module context") + +В этом видео рассматриваем слоты в Svelte и работу с `script` c `context="module"`. + + + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) +2. [Пример №2](code/svelte-todo-02) +3. [Пример №3](code/svelte-todo-03) +4. [Пример №4](code/svelte-todo-04) +5. [Пример №5](code/svelte-todo-05) +6. [Пример №6](code/svelte-todo-06) +7. [Пример №7](code/svelte-todo-07) +8. [Пример №8](code/svelte-todo-08) +9. [Пример №9](code/svelte-todo-09) +10. [Пример №10](code/svelte-todo-10) diff --git a/examples/projects/video10/code/svelte-todo-01/.gitignore b/examples/projects/video10/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video10/code/svelte-todo-01/README.md b/examples/projects/video10/code/svelte-todo-01/README.md new file mode 100644 index 0000000..0761f72 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/README.md @@ -0,0 +1,7 @@ +# Слоты - Svelte slots + +*Svelte slots* - это возвоможность компонентов иметь вложенные элементы. + +Layout - расположение элементов на странице. + +Создадим компонент BaseLayout, заполним содержанием и импортируем его. \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-01/package.json b/examples/projects/video10/code/svelte-todo-01/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video10/code/svelte-todo-01/public/favicon.png b/examples/projects/video10/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video10/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video10/code/svelte-todo-01/public/global.css b/examples/projects/video10/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video10/code/svelte-todo-01/public/index.html b/examples/projects/video10/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video10/code/svelte-todo-01/rollup.config.js b/examples/projects/video10/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video10/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video10/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video10/code/svelte-todo-01/src/actions/draggable.js b/examples/projects/video10/code/svelte-todo-01/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-01/src/components/AddTodoItem.svelte b/examples/projects/video10/code/svelte-todo-01/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video10/code/svelte-todo-01/src/components/Form.svelte b/examples/projects/video10/code/svelte-todo-01/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-01/src/components/TodoItem.svelte b/examples/projects/video10/code/svelte-todo-01/src/components/TodoItem.svelte new file mode 100644 index 0000000..797d5c2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/components/TodoItem.svelte @@ -0,0 +1,97 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-01/src/layouts/BaseLayout.svelte b/examples/projects/video10/code/svelte-todo-01/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..db4438d --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/layouts/BaseLayout.svelte @@ -0,0 +1,32 @@ +
+
+ Welcome to Todo app! +
+
+ +
+ +
+ + diff --git a/examples/projects/video10/code/svelte-todo-01/src/main.js b/examples/projects/video10/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-01/src/store/customStore.js b/examples/projects/video10/code/svelte-todo-01/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-01/src/store/store.js b/examples/projects/video10/code/svelte-todo-01/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-01/src/store/todoStats.js b/examples/projects/video10/code/svelte-todo-01/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video10/code/svelte-todo-01/src/transitions/skew.js b/examples/projects/video10/code/svelte-todo-01/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-01/src/transitions/typewriter.js b/examples/projects/video10/code/svelte-todo-01/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-01/src/utils/format.js b/examples/projects/video10/code/svelte-todo-01/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-01/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-02/.gitignore b/examples/projects/video10/code/svelte-todo-02/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video10/code/svelte-todo-02/README.md b/examples/projects/video10/code/svelte-todo-02/README.md new file mode 100644 index 0000000..0c7d07a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/README.md @@ -0,0 +1,3 @@ +# Слоты - Svelte slots + +Для публикации содержимого компонента используется тег . \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-02/package.json b/examples/projects/video10/code/svelte-todo-02/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video10/code/svelte-todo-02/public/favicon.png b/examples/projects/video10/code/svelte-todo-02/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video10/code/svelte-todo-02/public/favicon.png differ diff --git a/examples/projects/video10/code/svelte-todo-02/public/global.css b/examples/projects/video10/code/svelte-todo-02/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video10/code/svelte-todo-02/public/index.html b/examples/projects/video10/code/svelte-todo-02/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video10/code/svelte-todo-02/rollup.config.js b/examples/projects/video10/code/svelte-todo-02/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video10/code/svelte-todo-02/scripts/setupTypeScript.js b/examples/projects/video10/code/svelte-todo-02/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video10/code/svelte-todo-02/src/actions/draggable.js b/examples/projects/video10/code/svelte-todo-02/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-02/src/components/AddTodoItem.svelte b/examples/projects/video10/code/svelte-todo-02/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video10/code/svelte-todo-02/src/components/Form.svelte b/examples/projects/video10/code/svelte-todo-02/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-02/src/components/TodoItem.svelte b/examples/projects/video10/code/svelte-todo-02/src/components/TodoItem.svelte new file mode 100644 index 0000000..797d5c2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/components/TodoItem.svelte @@ -0,0 +1,97 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-02/src/layouts/BaseLayout.svelte b/examples/projects/video10/code/svelte-todo-02/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..b745eba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/layouts/BaseLayout.svelte @@ -0,0 +1,32 @@ +
+
+ Welcome to Todo app! +
+
+ +
+ +
+ + diff --git a/examples/projects/video10/code/svelte-todo-02/src/main.js b/examples/projects/video10/code/svelte-todo-02/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-02/src/store/customStore.js b/examples/projects/video10/code/svelte-todo-02/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-02/src/store/store.js b/examples/projects/video10/code/svelte-todo-02/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-02/src/store/todoStats.js b/examples/projects/video10/code/svelte-todo-02/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video10/code/svelte-todo-02/src/transitions/skew.js b/examples/projects/video10/code/svelte-todo-02/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-02/src/transitions/typewriter.js b/examples/projects/video10/code/svelte-todo-02/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-02/src/utils/format.js b/examples/projects/video10/code/svelte-todo-02/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-02/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-03/.gitignore b/examples/projects/video10/code/svelte-todo-03/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video10/code/svelte-todo-03/README.md b/examples/projects/video10/code/svelte-todo-03/README.md new file mode 100644 index 0000000..060fe52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/README.md @@ -0,0 +1,3 @@ +# Слоты - Svelte slots + +Тег можно располагать в любом месте. \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-03/package.json b/examples/projects/video10/code/svelte-todo-03/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video10/code/svelte-todo-03/public/favicon.png b/examples/projects/video10/code/svelte-todo-03/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video10/code/svelte-todo-03/public/favicon.png differ diff --git a/examples/projects/video10/code/svelte-todo-03/public/global.css b/examples/projects/video10/code/svelte-todo-03/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video10/code/svelte-todo-03/public/index.html b/examples/projects/video10/code/svelte-todo-03/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video10/code/svelte-todo-03/rollup.config.js b/examples/projects/video10/code/svelte-todo-03/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video10/code/svelte-todo-03/scripts/setupTypeScript.js b/examples/projects/video10/code/svelte-todo-03/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video10/code/svelte-todo-03/src/actions/draggable.js b/examples/projects/video10/code/svelte-todo-03/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-03/src/components/AddTodoItem.svelte b/examples/projects/video10/code/svelte-todo-03/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video10/code/svelte-todo-03/src/components/Form.svelte b/examples/projects/video10/code/svelte-todo-03/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-03/src/components/TodoItem.svelte b/examples/projects/video10/code/svelte-todo-03/src/components/TodoItem.svelte new file mode 100644 index 0000000..797d5c2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/components/TodoItem.svelte @@ -0,0 +1,97 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-03/src/layouts/BaseLayout.svelte b/examples/projects/video10/code/svelte-todo-03/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..f8d8579 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/layouts/BaseLayout.svelte @@ -0,0 +1,32 @@ +
+
+ +
+
+ Welcome +
+ +
+ + diff --git a/examples/projects/video10/code/svelte-todo-03/src/main.js b/examples/projects/video10/code/svelte-todo-03/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-03/src/store/customStore.js b/examples/projects/video10/code/svelte-todo-03/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-03/src/store/store.js b/examples/projects/video10/code/svelte-todo-03/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-03/src/store/todoStats.js b/examples/projects/video10/code/svelte-todo-03/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video10/code/svelte-todo-03/src/transitions/skew.js b/examples/projects/video10/code/svelte-todo-03/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-03/src/transitions/typewriter.js b/examples/projects/video10/code/svelte-todo-03/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-03/src/utils/format.js b/examples/projects/video10/code/svelte-todo-03/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-03/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-04/.gitignore b/examples/projects/video10/code/svelte-todo-04/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video10/code/svelte-todo-04/README.md b/examples/projects/video10/code/svelte-todo-04/README.md new file mode 100644 index 0000000..acc1db7 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/README.md @@ -0,0 +1,8 @@ +# Слоты - Svelte slots + +Для использования несокольких тегов , данные теги могут иметь названия (имена). + +- `` +- `` + +Тег `` без имени - это ``-тег по умолчанию. \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-04/package.json b/examples/projects/video10/code/svelte-todo-04/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video10/code/svelte-todo-04/public/favicon.png b/examples/projects/video10/code/svelte-todo-04/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video10/code/svelte-todo-04/public/favicon.png differ diff --git a/examples/projects/video10/code/svelte-todo-04/public/global.css b/examples/projects/video10/code/svelte-todo-04/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video10/code/svelte-todo-04/public/index.html b/examples/projects/video10/code/svelte-todo-04/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video10/code/svelte-todo-04/rollup.config.js b/examples/projects/video10/code/svelte-todo-04/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video10/code/svelte-todo-04/scripts/setupTypeScript.js b/examples/projects/video10/code/svelte-todo-04/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video10/code/svelte-todo-04/src/actions/draggable.js b/examples/projects/video10/code/svelte-todo-04/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-04/src/components/AddTodoItem.svelte b/examples/projects/video10/code/svelte-todo-04/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video10/code/svelte-todo-04/src/components/Form.svelte b/examples/projects/video10/code/svelte-todo-04/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-04/src/components/TodoItem.svelte b/examples/projects/video10/code/svelte-todo-04/src/components/TodoItem.svelte new file mode 100644 index 0000000..797d5c2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/components/TodoItem.svelte @@ -0,0 +1,97 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-04/src/layouts/BaseLayout.svelte b/examples/projects/video10/code/svelte-todo-04/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..b2d7044 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/layouts/BaseLayout.svelte @@ -0,0 +1,32 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video10/code/svelte-todo-04/src/main.js b/examples/projects/video10/code/svelte-todo-04/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-04/src/store/customStore.js b/examples/projects/video10/code/svelte-todo-04/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-04/src/store/store.js b/examples/projects/video10/code/svelte-todo-04/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-04/src/store/todoStats.js b/examples/projects/video10/code/svelte-todo-04/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video10/code/svelte-todo-04/src/transitions/skew.js b/examples/projects/video10/code/svelte-todo-04/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-04/src/transitions/typewriter.js b/examples/projects/video10/code/svelte-todo-04/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-04/src/utils/format.js b/examples/projects/video10/code/svelte-todo-04/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-04/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-05/.gitignore b/examples/projects/video10/code/svelte-todo-05/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video10/code/svelte-todo-05/README.md b/examples/projects/video10/code/svelte-todo-05/README.md new file mode 100644 index 0000000..0602712 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/README.md @@ -0,0 +1,12 @@ +# Слоты - Svelte slots + +Пример использования именнованных -тегов. + +Если тег не содержит дочерних данных, то можно добавить информацию по умолчанию в определение тега (в `BaseLayout.svelte`). + +``` + + Thank you! + +``` + diff --git a/examples/projects/video10/code/svelte-todo-05/package.json b/examples/projects/video10/code/svelte-todo-05/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video10/code/svelte-todo-05/public/favicon.png b/examples/projects/video10/code/svelte-todo-05/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video10/code/svelte-todo-05/public/favicon.png differ diff --git a/examples/projects/video10/code/svelte-todo-05/public/global.css b/examples/projects/video10/code/svelte-todo-05/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video10/code/svelte-todo-05/public/index.html b/examples/projects/video10/code/svelte-todo-05/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video10/code/svelte-todo-05/rollup.config.js b/examples/projects/video10/code/svelte-todo-05/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video10/code/svelte-todo-05/scripts/setupTypeScript.js b/examples/projects/video10/code/svelte-todo-05/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ Welcome! +
+ +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video10/code/svelte-todo-05/src/actions/draggable.js b/examples/projects/video10/code/svelte-todo-05/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-05/src/components/AddTodoItem.svelte b/examples/projects/video10/code/svelte-todo-05/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video10/code/svelte-todo-05/src/components/Form.svelte b/examples/projects/video10/code/svelte-todo-05/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-05/src/components/TodoItem.svelte b/examples/projects/video10/code/svelte-todo-05/src/components/TodoItem.svelte new file mode 100644 index 0000000..797d5c2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/components/TodoItem.svelte @@ -0,0 +1,97 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-05/src/layouts/BaseLayout.svelte b/examples/projects/video10/code/svelte-todo-05/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..2143085 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video10/code/svelte-todo-05/src/main.js b/examples/projects/video10/code/svelte-todo-05/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-05/src/store/customStore.js b/examples/projects/video10/code/svelte-todo-05/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-05/src/store/store.js b/examples/projects/video10/code/svelte-todo-05/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-05/src/store/todoStats.js b/examples/projects/video10/code/svelte-todo-05/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video10/code/svelte-todo-05/src/transitions/skew.js b/examples/projects/video10/code/svelte-todo-05/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-05/src/transitions/typewriter.js b/examples/projects/video10/code/svelte-todo-05/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-05/src/utils/format.js b/examples/projects/video10/code/svelte-todo-05/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-05/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-06/.gitignore b/examples/projects/video10/code/svelte-todo-06/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video10/code/svelte-todo-06/README.md b/examples/projects/video10/code/svelte-todo-06/README.md new file mode 100644 index 0000000..0602712 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/README.md @@ -0,0 +1,12 @@ +# Слоты - Svelte slots + +Пример использования именнованных -тегов. + +Если тег не содержит дочерних данных, то можно добавить информацию по умолчанию в определение тега (в `BaseLayout.svelte`). + +``` + + Thank you! + +``` + diff --git a/examples/projects/video10/code/svelte-todo-06/package.json b/examples/projects/video10/code/svelte-todo-06/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video10/code/svelte-todo-06/public/favicon.png b/examples/projects/video10/code/svelte-todo-06/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video10/code/svelte-todo-06/public/favicon.png differ diff --git a/examples/projects/video10/code/svelte-todo-06/public/global.css b/examples/projects/video10/code/svelte-todo-06/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video10/code/svelte-todo-06/public/index.html b/examples/projects/video10/code/svelte-todo-06/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video10/code/svelte-todo-06/rollup.config.js b/examples/projects/video10/code/svelte-todo-06/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video10/code/svelte-todo-06/scripts/setupTypeScript.js b/examples/projects/video10/code/svelte-todo-06/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ Welcome! +
+
+ +
+ +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video10/code/svelte-todo-06/src/actions/draggable.js b/examples/projects/video10/code/svelte-todo-06/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-06/src/components/AddTodoItem.svelte b/examples/projects/video10/code/svelte-todo-06/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video10/code/svelte-todo-06/src/components/Form.svelte b/examples/projects/video10/code/svelte-todo-06/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-06/src/components/TodoItem.svelte b/examples/projects/video10/code/svelte-todo-06/src/components/TodoItem.svelte new file mode 100644 index 0000000..797d5c2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/components/TodoItem.svelte @@ -0,0 +1,97 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-06/src/layouts/BaseLayout.svelte b/examples/projects/video10/code/svelte-todo-06/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..2143085 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video10/code/svelte-todo-06/src/main.js b/examples/projects/video10/code/svelte-todo-06/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-06/src/store/customStore.js b/examples/projects/video10/code/svelte-todo-06/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-06/src/store/store.js b/examples/projects/video10/code/svelte-todo-06/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-06/src/store/todoStats.js b/examples/projects/video10/code/svelte-todo-06/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video10/code/svelte-todo-06/src/transitions/skew.js b/examples/projects/video10/code/svelte-todo-06/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-06/src/transitions/typewriter.js b/examples/projects/video10/code/svelte-todo-06/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-06/src/utils/format.js b/examples/projects/video10/code/svelte-todo-06/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-06/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-07/.gitignore b/examples/projects/video10/code/svelte-todo-07/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video10/code/svelte-todo-07/README.md b/examples/projects/video10/code/svelte-todo-07/README.md new file mode 100644 index 0000000..92bc05c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/README.md @@ -0,0 +1,8 @@ +# Слоты - Svelte slots + +Пример использования именнованных -тегов. + +Установка свойств в теге . + +[svelte-carousel source code](https://github.com/vadimkorr/svelte-carousel) +[svelte-carousel Demo](https://vadimkorr.github.io/svelte-carousel/) \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-07/package.json b/examples/projects/video10/code/svelte-todo-07/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video10/code/svelte-todo-07/public/favicon.png b/examples/projects/video10/code/svelte-todo-07/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video10/code/svelte-todo-07/public/favicon.png differ diff --git a/examples/projects/video10/code/svelte-todo-07/public/global.css b/examples/projects/video10/code/svelte-todo-07/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video10/code/svelte-todo-07/public/index.html b/examples/projects/video10/code/svelte-todo-07/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video10/code/svelte-todo-07/rollup.config.js b/examples/projects/video10/code/svelte-todo-07/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video10/code/svelte-todo-07/scripts/setupTypeScript.js b/examples/projects/video10/code/svelte-todo-07/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {greeting} and Welcome! +
+
+ +
+ +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video10/code/svelte-todo-07/src/actions/draggable.js b/examples/projects/video10/code/svelte-todo-07/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-07/src/components/AddTodoItem.svelte b/examples/projects/video10/code/svelte-todo-07/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video10/code/svelte-todo-07/src/components/Form.svelte b/examples/projects/video10/code/svelte-todo-07/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-07/src/components/TodoItem.svelte b/examples/projects/video10/code/svelte-todo-07/src/components/TodoItem.svelte new file mode 100644 index 0000000..797d5c2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/components/TodoItem.svelte @@ -0,0 +1,97 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-07/src/layouts/BaseLayout.svelte b/examples/projects/video10/code/svelte-todo-07/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video10/code/svelte-todo-07/src/main.js b/examples/projects/video10/code/svelte-todo-07/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-07/src/store/customStore.js b/examples/projects/video10/code/svelte-todo-07/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-07/src/store/store.js b/examples/projects/video10/code/svelte-todo-07/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-07/src/store/todoStats.js b/examples/projects/video10/code/svelte-todo-07/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video10/code/svelte-todo-07/src/transitions/skew.js b/examples/projects/video10/code/svelte-todo-07/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-07/src/transitions/typewriter.js b/examples/projects/video10/code/svelte-todo-07/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-07/src/utils/format.js b/examples/projects/video10/code/svelte-todo-07/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-07/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-08/.gitignore b/examples/projects/video10/code/svelte-todo-08/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video10/code/svelte-todo-08/README.md b/examples/projects/video10/code/svelte-todo-08/README.md new file mode 100644 index 0000000..33b116e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/README.md @@ -0,0 +1,3 @@ +# Слоты - `$$slots` + +Демонстрация содеражания переменной `$$slots`. diff --git a/examples/projects/video10/code/svelte-todo-08/package.json b/examples/projects/video10/code/svelte-todo-08/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video10/code/svelte-todo-08/public/favicon.png b/examples/projects/video10/code/svelte-todo-08/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video10/code/svelte-todo-08/public/favicon.png differ diff --git a/examples/projects/video10/code/svelte-todo-08/public/global.css b/examples/projects/video10/code/svelte-todo-08/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video10/code/svelte-todo-08/public/index.html b/examples/projects/video10/code/svelte-todo-08/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video10/code/svelte-todo-08/rollup.config.js b/examples/projects/video10/code/svelte-todo-08/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video10/code/svelte-todo-08/scripts/setupTypeScript.js b/examples/projects/video10/code/svelte-todo-08/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {greeting} and Welcome! +
+
+ +
+ +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video10/code/svelte-todo-08/src/actions/draggable.js b/examples/projects/video10/code/svelte-todo-08/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-08/src/components/AddTodoItem.svelte b/examples/projects/video10/code/svelte-todo-08/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video10/code/svelte-todo-08/src/components/Form.svelte b/examples/projects/video10/code/svelte-todo-08/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-08/src/components/TodoItem.svelte b/examples/projects/video10/code/svelte-todo-08/src/components/TodoItem.svelte new file mode 100644 index 0000000..797d5c2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/components/TodoItem.svelte @@ -0,0 +1,97 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-08/src/layouts/BaseLayout.svelte b/examples/projects/video10/code/svelte-todo-08/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..96dbeba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/layouts/BaseLayout.svelte @@ -0,0 +1,38 @@ + + +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video10/code/svelte-todo-08/src/main.js b/examples/projects/video10/code/svelte-todo-08/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-08/src/store/customStore.js b/examples/projects/video10/code/svelte-todo-08/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-08/src/store/store.js b/examples/projects/video10/code/svelte-todo-08/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-08/src/store/todoStats.js b/examples/projects/video10/code/svelte-todo-08/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video10/code/svelte-todo-08/src/transitions/skew.js b/examples/projects/video10/code/svelte-todo-08/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-08/src/transitions/typewriter.js b/examples/projects/video10/code/svelte-todo-08/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-08/src/utils/format.js b/examples/projects/video10/code/svelte-todo-08/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-08/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-09/.gitignore b/examples/projects/video10/code/svelte-todo-09/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video10/code/svelte-todo-09/README.md b/examples/projects/video10/code/svelte-todo-09/README.md new file mode 100644 index 0000000..816c35c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/README.md @@ -0,0 +1,5 @@ +# Слоты - `$$slots` + +Демонстрация содеражания переменной `$$slots`. + +Удалим слот `footer`. \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-09/package.json b/examples/projects/video10/code/svelte-todo-09/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video10/code/svelte-todo-09/public/favicon.png b/examples/projects/video10/code/svelte-todo-09/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video10/code/svelte-todo-09/public/favicon.png differ diff --git a/examples/projects/video10/code/svelte-todo-09/public/global.css b/examples/projects/video10/code/svelte-todo-09/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video10/code/svelte-todo-09/public/index.html b/examples/projects/video10/code/svelte-todo-09/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video10/code/svelte-todo-09/rollup.config.js b/examples/projects/video10/code/svelte-todo-09/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video10/code/svelte-todo-09/scripts/setupTypeScript.js b/examples/projects/video10/code/svelte-todo-09/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video10/code/svelte-todo-09/src/actions/draggable.js b/examples/projects/video10/code/svelte-todo-09/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-09/src/components/AddTodoItem.svelte b/examples/projects/video10/code/svelte-todo-09/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video10/code/svelte-todo-09/src/components/Form.svelte b/examples/projects/video10/code/svelte-todo-09/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-09/src/components/TodoItem.svelte b/examples/projects/video10/code/svelte-todo-09/src/components/TodoItem.svelte new file mode 100644 index 0000000..797d5c2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/components/TodoItem.svelte @@ -0,0 +1,97 @@ + + +
+ +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-09/src/layouts/BaseLayout.svelte b/examples/projects/video10/code/svelte-todo-09/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..96dbeba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/layouts/BaseLayout.svelte @@ -0,0 +1,38 @@ + + +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video10/code/svelte-todo-09/src/main.js b/examples/projects/video10/code/svelte-todo-09/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-09/src/store/customStore.js b/examples/projects/video10/code/svelte-todo-09/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-09/src/store/store.js b/examples/projects/video10/code/svelte-todo-09/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-09/src/store/todoStats.js b/examples/projects/video10/code/svelte-todo-09/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video10/code/svelte-todo-09/src/transitions/skew.js b/examples/projects/video10/code/svelte-todo-09/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-09/src/transitions/typewriter.js b/examples/projects/video10/code/svelte-todo-09/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-09/src/utils/format.js b/examples/projects/video10/code/svelte-todo-09/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-09/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-10/.gitignore b/examples/projects/video10/code/svelte-todo-10/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video10/code/svelte-todo-10/README.md b/examples/projects/video10/code/svelte-todo-10/README.md new file mode 100644 index 0000000..3e48449 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/README.md @@ -0,0 +1,32 @@ +# Модули + +Модули позволяют иметь общий код или состояние между компонентами, например между всеми экземплярами одного и того же компонента. + +Бывает полезно запустить один и тот же код для всех экземпляров компонента. + +Модуль это тег ` +``` + +Данный участок кода выполняется только один раз ещё до создания какого-либо компонента, а не при каждой инициализации экземпляра компонента. + +Переменные, которые объявлены в блоке `context="module"` могут быть использованы, как в коде, так и в разметке. Данные переменные не являются реативными. Т.е. присваивание этим переменным новых значений не будут приводить к перерисовке данного компонента. + +## Типы переменных и их особенности + +### script module +не реактивные +доступны между экземплярами одного и того же компонента + +### store +реактивные +доступны во всём приложении + +### context +не реактивные +доступны в компоненте и его потомках + diff --git a/examples/projects/video10/code/svelte-todo-10/package.json b/examples/projects/video10/code/svelte-todo-10/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video10/code/svelte-todo-10/public/favicon.png b/examples/projects/video10/code/svelte-todo-10/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video10/code/svelte-todo-10/public/favicon.png differ diff --git a/examples/projects/video10/code/svelte-todo-10/public/global.css b/examples/projects/video10/code/svelte-todo-10/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video10/code/svelte-todo-10/public/index.html b/examples/projects/video10/code/svelte-todo-10/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video10/code/svelte-todo-10/rollup.config.js b/examples/projects/video10/code/svelte-todo-10/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video10/code/svelte-todo-10/scripts/setupTypeScript.js b/examples/projects/video10/code/svelte-todo-10/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video10/code/svelte-todo-10/src/actions/draggable.js b/examples/projects/video10/code/svelte-todo-10/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-10/src/components/AddTodoItem.svelte b/examples/projects/video10/code/svelte-todo-10/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video10/code/svelte-todo-10/src/components/Form.svelte b/examples/projects/video10/code/svelte-todo-10/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-10/src/components/TodoItem.svelte b/examples/projects/video10/code/svelte-todo-10/src/components/TodoItem.svelte new file mode 100644 index 0000000..eababda --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/components/TodoItem.svelte @@ -0,0 +1,105 @@ + + + + +
+ {state} + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-10/src/layouts/BaseLayout.svelte b/examples/projects/video10/code/svelte-todo-10/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video10/code/svelte-todo-10/src/main.js b/examples/projects/video10/code/svelte-todo-10/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-10/src/store/customStore.js b/examples/projects/video10/code/svelte-todo-10/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-10/src/store/store.js b/examples/projects/video10/code/svelte-todo-10/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-10/src/store/todoStats.js b/examples/projects/video10/code/svelte-todo-10/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video10/code/svelte-todo-10/src/transitions/skew.js b/examples/projects/video10/code/svelte-todo-10/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-10/src/transitions/typewriter.js b/examples/projects/video10/code/svelte-todo-10/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video10/code/svelte-todo-10/src/utils/format.js b/examples/projects/video10/code/svelte-todo-10/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video10/code/svelte-todo-10/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video11/README.md b/examples/projects/video11/README.md new file mode 100644 index 0000000..6ea984f --- /dev/null +++ b/examples/projects/video11/README.md @@ -0,0 +1,26 @@ +# API контекста - Svelte Context API. Применение CSS классов по условию. + +[![API контекста - Svelte Context API](https://img.youtube.com/vi/olyPCoIdgT0/0.jpg)](https://youtu.be/olyPCoIdgT0 "API контекста - Svelte Context API") + +В этом видео рассматриваем возможности контекста Svelte, функции `setContext`, `getContext` и `hasContext`, а также применение CSS классов по условию. + +Контекст даёт возможность компонентам передавать друг другу сообщения без необходимости передавать данные через всю иерархию компонентов, т.е. от родителя к потомкам. + +Любой дочерний компонент может получить значение контекста с помощью функции `getContext` с помощью ключа. В качестве ключа может быть любой тип данных. + +Методы `setContext`и `getContext` должны вызываться только при инициализации компонента. + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) +2. [Пример №2](code/svelte-todo-02) +3. [Пример №3](code/svelte-todo-03) +4. [Пример №4](code/svelte-todo-04) +5. [Пример №5](code/svelte-todo-05) +6. [Пример №6](code/svelte-todo-06) diff --git a/examples/projects/video11/code/svelte-todo-01/.gitignore b/examples/projects/video11/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video11/code/svelte-todo-01/README.md b/examples/projects/video11/code/svelte-todo-01/README.md new file mode 100644 index 0000000..c012153 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/README.md @@ -0,0 +1,16 @@ +# Context API + +## Типы переменных и их особенности + +### script module +не реактивные +доступны между экземплярами одного и того же компонента + +### store +реактивные +доступны во всём приложении + +### context +не реактивные +доступны в компоненте и его потомках + diff --git a/examples/projects/video11/code/svelte-todo-01/package.json b/examples/projects/video11/code/svelte-todo-01/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video11/code/svelte-todo-01/public/favicon.png b/examples/projects/video11/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video11/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video11/code/svelte-todo-01/public/global.css b/examples/projects/video11/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video11/code/svelte-todo-01/public/index.html b/examples/projects/video11/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video11/code/svelte-todo-01/rollup.config.js b/examples/projects/video11/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video11/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video11/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video11/code/svelte-todo-01/src/actions/draggable.js b/examples/projects/video11/code/svelte-todo-01/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-01/src/components/AddTodoItem.svelte b/examples/projects/video11/code/svelte-todo-01/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video11/code/svelte-todo-01/src/components/Form.svelte b/examples/projects/video11/code/svelte-todo-01/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-01/src/components/TodoItem.svelte b/examples/projects/video11/code/svelte-todo-01/src/components/TodoItem.svelte new file mode 100644 index 0000000..083ba16 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + +

{user.name}! You have something to do.

+

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-01/src/layouts/BaseLayout.svelte b/examples/projects/video11/code/svelte-todo-01/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video11/code/svelte-todo-01/src/main.js b/examples/projects/video11/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-01/src/store/customStore.js b/examples/projects/video11/code/svelte-todo-01/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-01/src/store/store.js b/examples/projects/video11/code/svelte-todo-01/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-01/src/store/todoStats.js b/examples/projects/video11/code/svelte-todo-01/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video11/code/svelte-todo-01/src/transitions/skew.js b/examples/projects/video11/code/svelte-todo-01/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-01/src/transitions/typewriter.js b/examples/projects/video11/code/svelte-todo-01/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-01/src/utils/format.js b/examples/projects/video11/code/svelte-todo-01/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-01/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-02/.gitignore b/examples/projects/video11/code/svelte-todo-02/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video11/code/svelte-todo-02/README.md b/examples/projects/video11/code/svelte-todo-02/README.md new file mode 100644 index 0000000..bf619f9 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/README.md @@ -0,0 +1,4 @@ +# Context API + +Передача `store`. + diff --git a/examples/projects/video11/code/svelte-todo-02/package.json b/examples/projects/video11/code/svelte-todo-02/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video11/code/svelte-todo-02/public/favicon.png b/examples/projects/video11/code/svelte-todo-02/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video11/code/svelte-todo-02/public/favicon.png differ diff --git a/examples/projects/video11/code/svelte-todo-02/public/global.css b/examples/projects/video11/code/svelte-todo-02/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video11/code/svelte-todo-02/public/index.html b/examples/projects/video11/code/svelte-todo-02/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video11/code/svelte-todo-02/rollup.config.js b/examples/projects/video11/code/svelte-todo-02/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video11/code/svelte-todo-02/scripts/setupTypeScript.js b/examples/projects/video11/code/svelte-todo-02/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video11/code/svelte-todo-02/src/actions/draggable.js b/examples/projects/video11/code/svelte-todo-02/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-02/src/components/AddTodoItem.svelte b/examples/projects/video11/code/svelte-todo-02/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video11/code/svelte-todo-02/src/components/Form.svelte b/examples/projects/video11/code/svelte-todo-02/src/components/Form.svelte new file mode 100644 index 0000000..d28fc52 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/components/Form.svelte @@ -0,0 +1,47 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-02/src/components/TodoItem.svelte b/examples/projects/video11/code/svelte-todo-02/src/components/TodoItem.svelte new file mode 100644 index 0000000..cc5fd5d --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-02/src/layouts/BaseLayout.svelte b/examples/projects/video11/code/svelte-todo-02/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video11/code/svelte-todo-02/src/main.js b/examples/projects/video11/code/svelte-todo-02/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-02/src/store/customStore.js b/examples/projects/video11/code/svelte-todo-02/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-02/src/store/store.js b/examples/projects/video11/code/svelte-todo-02/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-02/src/store/todoStats.js b/examples/projects/video11/code/svelte-todo-02/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video11/code/svelte-todo-02/src/transitions/skew.js b/examples/projects/video11/code/svelte-todo-02/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-02/src/transitions/typewriter.js b/examples/projects/video11/code/svelte-todo-02/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-02/src/utils/format.js b/examples/projects/video11/code/svelte-todo-02/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-02/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-03/.gitignore b/examples/projects/video11/code/svelte-todo-03/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video11/code/svelte-todo-03/README.md b/examples/projects/video11/code/svelte-todo-03/README.md new file mode 100644 index 0000000..598f525 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/README.md @@ -0,0 +1,4 @@ +# Применение CSS классов по условию + + + diff --git a/examples/projects/video11/code/svelte-todo-03/package.json b/examples/projects/video11/code/svelte-todo-03/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video11/code/svelte-todo-03/public/favicon.png b/examples/projects/video11/code/svelte-todo-03/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video11/code/svelte-todo-03/public/favicon.png differ diff --git a/examples/projects/video11/code/svelte-todo-03/public/global.css b/examples/projects/video11/code/svelte-todo-03/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video11/code/svelte-todo-03/public/index.html b/examples/projects/video11/code/svelte-todo-03/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video11/code/svelte-todo-03/rollup.config.js b/examples/projects/video11/code/svelte-todo-03/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video11/code/svelte-todo-03/scripts/setupTypeScript.js b/examples/projects/video11/code/svelte-todo-03/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video11/code/svelte-todo-03/src/actions/draggable.js b/examples/projects/video11/code/svelte-todo-03/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-03/src/components/AddTodoItem.svelte b/examples/projects/video11/code/svelte-todo-03/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video11/code/svelte-todo-03/src/components/Form.svelte b/examples/projects/video11/code/svelte-todo-03/src/components/Form.svelte new file mode 100644 index 0000000..54c69c3 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/components/Form.svelte @@ -0,0 +1,56 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-03/src/components/TodoItem.svelte b/examples/projects/video11/code/svelte-todo-03/src/components/TodoItem.svelte new file mode 100644 index 0000000..cc5fd5d --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-03/src/layouts/BaseLayout.svelte b/examples/projects/video11/code/svelte-todo-03/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video11/code/svelte-todo-03/src/main.js b/examples/projects/video11/code/svelte-todo-03/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-03/src/store/customStore.js b/examples/projects/video11/code/svelte-todo-03/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-03/src/store/store.js b/examples/projects/video11/code/svelte-todo-03/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-03/src/store/todoStats.js b/examples/projects/video11/code/svelte-todo-03/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video11/code/svelte-todo-03/src/transitions/skew.js b/examples/projects/video11/code/svelte-todo-03/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-03/src/transitions/typewriter.js b/examples/projects/video11/code/svelte-todo-03/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-03/src/utils/format.js b/examples/projects/video11/code/svelte-todo-03/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-03/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-04/.gitignore b/examples/projects/video11/code/svelte-todo-04/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video11/code/svelte-todo-04/README.md b/examples/projects/video11/code/svelte-todo-04/README.md new file mode 100644 index 0000000..ae4a4a4 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/README.md @@ -0,0 +1,6 @@ +# Применение CSS классов по условию + +Сокращенная запись + + + diff --git a/examples/projects/video11/code/svelte-todo-04/package.json b/examples/projects/video11/code/svelte-todo-04/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video11/code/svelte-todo-04/public/favicon.png b/examples/projects/video11/code/svelte-todo-04/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video11/code/svelte-todo-04/public/favicon.png differ diff --git a/examples/projects/video11/code/svelte-todo-04/public/global.css b/examples/projects/video11/code/svelte-todo-04/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video11/code/svelte-todo-04/public/index.html b/examples/projects/video11/code/svelte-todo-04/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video11/code/svelte-todo-04/rollup.config.js b/examples/projects/video11/code/svelte-todo-04/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video11/code/svelte-todo-04/scripts/setupTypeScript.js b/examples/projects/video11/code/svelte-todo-04/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video11/code/svelte-todo-04/src/actions/draggable.js b/examples/projects/video11/code/svelte-todo-04/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-04/src/components/AddTodoItem.svelte b/examples/projects/video11/code/svelte-todo-04/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video11/code/svelte-todo-04/src/components/Form.svelte b/examples/projects/video11/code/svelte-todo-04/src/components/Form.svelte new file mode 100644 index 0000000..bf52585 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/components/Form.svelte @@ -0,0 +1,53 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-04/src/components/TodoItem.svelte b/examples/projects/video11/code/svelte-todo-04/src/components/TodoItem.svelte new file mode 100644 index 0000000..cc5fd5d --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-04/src/layouts/BaseLayout.svelte b/examples/projects/video11/code/svelte-todo-04/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video11/code/svelte-todo-04/src/main.js b/examples/projects/video11/code/svelte-todo-04/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-04/src/store/customStore.js b/examples/projects/video11/code/svelte-todo-04/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-04/src/store/store.js b/examples/projects/video11/code/svelte-todo-04/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-04/src/store/todoStats.js b/examples/projects/video11/code/svelte-todo-04/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video11/code/svelte-todo-04/src/transitions/skew.js b/examples/projects/video11/code/svelte-todo-04/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-04/src/transitions/typewriter.js b/examples/projects/video11/code/svelte-todo-04/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-04/src/utils/format.js b/examples/projects/video11/code/svelte-todo-04/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-04/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-05/.gitignore b/examples/projects/video11/code/svelte-todo-05/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video11/code/svelte-todo-05/README.md b/examples/projects/video11/code/svelte-todo-05/README.md new file mode 100644 index 0000000..ae4a4a4 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/README.md @@ -0,0 +1,6 @@ +# Применение CSS классов по условию + +Сокращенная запись + + + diff --git a/examples/projects/video11/code/svelte-todo-05/package.json b/examples/projects/video11/code/svelte-todo-05/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video11/code/svelte-todo-05/public/favicon.png b/examples/projects/video11/code/svelte-todo-05/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video11/code/svelte-todo-05/public/favicon.png differ diff --git a/examples/projects/video11/code/svelte-todo-05/public/global.css b/examples/projects/video11/code/svelte-todo-05/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video11/code/svelte-todo-05/public/index.html b/examples/projects/video11/code/svelte-todo-05/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video11/code/svelte-todo-05/rollup.config.js b/examples/projects/video11/code/svelte-todo-05/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video11/code/svelte-todo-05/scripts/setupTypeScript.js b/examples/projects/video11/code/svelte-todo-05/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video11/code/svelte-todo-05/src/actions/draggable.js b/examples/projects/video11/code/svelte-todo-05/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-05/src/components/AddTodoItem.svelte b/examples/projects/video11/code/svelte-todo-05/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video11/code/svelte-todo-05/src/components/Form.svelte b/examples/projects/video11/code/svelte-todo-05/src/components/Form.svelte new file mode 100644 index 0000000..e19c5f9 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/components/Form.svelte @@ -0,0 +1,53 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-05/src/components/TodoItem.svelte b/examples/projects/video11/code/svelte-todo-05/src/components/TodoItem.svelte new file mode 100644 index 0000000..cc5fd5d --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-05/src/layouts/BaseLayout.svelte b/examples/projects/video11/code/svelte-todo-05/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video11/code/svelte-todo-05/src/main.js b/examples/projects/video11/code/svelte-todo-05/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-05/src/store/customStore.js b/examples/projects/video11/code/svelte-todo-05/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-05/src/store/store.js b/examples/projects/video11/code/svelte-todo-05/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-05/src/store/todoStats.js b/examples/projects/video11/code/svelte-todo-05/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video11/code/svelte-todo-05/src/transitions/skew.js b/examples/projects/video11/code/svelte-todo-05/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-05/src/transitions/typewriter.js b/examples/projects/video11/code/svelte-todo-05/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-05/src/utils/format.js b/examples/projects/video11/code/svelte-todo-05/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-05/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-06/.gitignore b/examples/projects/video11/code/svelte-todo-06/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video11/code/svelte-todo-06/README.md b/examples/projects/video11/code/svelte-todo-06/README.md new file mode 100644 index 0000000..ae4a4a4 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/README.md @@ -0,0 +1,6 @@ +# Применение CSS классов по условию + +Сокращенная запись + + + diff --git a/examples/projects/video11/code/svelte-todo-06/package.json b/examples/projects/video11/code/svelte-todo-06/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video11/code/svelte-todo-06/public/favicon.png b/examples/projects/video11/code/svelte-todo-06/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video11/code/svelte-todo-06/public/favicon.png differ diff --git a/examples/projects/video11/code/svelte-todo-06/public/global.css b/examples/projects/video11/code/svelte-todo-06/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video11/code/svelte-todo-06/public/index.html b/examples/projects/video11/code/svelte-todo-06/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video11/code/svelte-todo-06/rollup.config.js b/examples/projects/video11/code/svelte-todo-06/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video11/code/svelte-todo-06/scripts/setupTypeScript.js b/examples/projects/video11/code/svelte-todo-06/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video11/code/svelte-todo-06/src/actions/draggable.js b/examples/projects/video11/code/svelte-todo-06/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-06/src/components/AddTodoItem.svelte b/examples/projects/video11/code/svelte-todo-06/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video11/code/svelte-todo-06/src/components/Form.svelte b/examples/projects/video11/code/svelte-todo-06/src/components/Form.svelte new file mode 100644 index 0000000..d96a524 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/components/Form.svelte @@ -0,0 +1,53 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-06/src/components/TodoItem.svelte b/examples/projects/video11/code/svelte-todo-06/src/components/TodoItem.svelte new file mode 100644 index 0000000..cc5fd5d --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-06/src/layouts/BaseLayout.svelte b/examples/projects/video11/code/svelte-todo-06/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video11/code/svelte-todo-06/src/main.js b/examples/projects/video11/code/svelte-todo-06/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-06/src/store/customStore.js b/examples/projects/video11/code/svelte-todo-06/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-06/src/store/store.js b/examples/projects/video11/code/svelte-todo-06/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-06/src/store/todoStats.js b/examples/projects/video11/code/svelte-todo-06/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video11/code/svelte-todo-06/src/transitions/skew.js b/examples/projects/video11/code/svelte-todo-06/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-06/src/transitions/typewriter.js b/examples/projects/video11/code/svelte-todo-06/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video11/code/svelte-todo-06/src/utils/format.js b/examples/projects/video11/code/svelte-todo-06/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video11/code/svelte-todo-06/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video12/README.md b/examples/projects/video12/README.md new file mode 100644 index 0000000..3c41125 --- /dev/null +++ b/examples/projects/video12/README.md @@ -0,0 +1,29 @@ +# Специальные элементы + +[![Специальные элементы](https://img.youtube.com/vi/axGxAHwbYYg/0.jpg)](https://youtu.be/axGxAHwbYYg "Специальные элементы") + +В этом видео рассматриваем специальные элементы в Svelte: + +- +- +- +- +- + +- + + +## Команда запуска приложения +`npm run dev` + +## Адрес приложения +`http://localhost:5000/` + +## Примеры + +1. [Пример №1](code/svelte-todo-01) +2. [Пример №2](code/svelte-todo-02) +3. [Пример №3](code/svelte-todo-03) +4. [Пример №4](code/svelte-todo-04) +5. [Пример №5](code/svelte-todo-05) +6. [Пример №6](code/svelte-todo-06) diff --git a/examples/projects/video12/code/svelte-todo-01/.gitignore b/examples/projects/video12/code/svelte-todo-01/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video12/code/svelte-todo-01/README.md b/examples/projects/video12/code/svelte-todo-01/README.md new file mode 100644 index 0000000..4776446 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/README.md @@ -0,0 +1,3 @@ +# + +Обработчики данного элемента обрабатывают события `body`. diff --git a/examples/projects/video12/code/svelte-todo-01/package.json b/examples/projects/video12/code/svelte-todo-01/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video12/code/svelte-todo-01/public/favicon.png b/examples/projects/video12/code/svelte-todo-01/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video12/code/svelte-todo-01/public/favicon.png differ diff --git a/examples/projects/video12/code/svelte-todo-01/public/global.css b/examples/projects/video12/code/svelte-todo-01/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video12/code/svelte-todo-01/public/index.html b/examples/projects/video12/code/svelte-todo-01/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video12/code/svelte-todo-01/rollup.config.js b/examples/projects/video12/code/svelte-todo-01/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video12/code/svelte-todo-01/scripts/setupTypeScript.js b/examples/projects/video12/code/svelte-todo-01/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video12/code/svelte-todo-01/src/actions/draggable.js b/examples/projects/video12/code/svelte-todo-01/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-01/src/components/AddTodoItem.svelte b/examples/projects/video12/code/svelte-todo-01/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video12/code/svelte-todo-01/src/components/Form.svelte b/examples/projects/video12/code/svelte-todo-01/src/components/Form.svelte new file mode 100644 index 0000000..d96a524 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/components/Form.svelte @@ -0,0 +1,53 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-01/src/components/TodoItem.svelte b/examples/projects/video12/code/svelte-todo-01/src/components/TodoItem.svelte new file mode 100644 index 0000000..cc5fd5d --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-01/src/layouts/BaseLayout.svelte b/examples/projects/video12/code/svelte-todo-01/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video12/code/svelte-todo-01/src/main.js b/examples/projects/video12/code/svelte-todo-01/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-01/src/store/customStore.js b/examples/projects/video12/code/svelte-todo-01/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-01/src/store/store.js b/examples/projects/video12/code/svelte-todo-01/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-01/src/store/todoStats.js b/examples/projects/video12/code/svelte-todo-01/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video12/code/svelte-todo-01/src/transitions/skew.js b/examples/projects/video12/code/svelte-todo-01/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-01/src/transitions/typewriter.js b/examples/projects/video12/code/svelte-todo-01/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-01/src/utils/format.js b/examples/projects/video12/code/svelte-todo-01/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-01/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-02/.gitignore b/examples/projects/video12/code/svelte-todo-02/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video12/code/svelte-todo-02/README.md b/examples/projects/video12/code/svelte-todo-02/README.md new file mode 100644 index 0000000..95651ff --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/README.md @@ -0,0 +1,20 @@ +# + +Будем отслеживать нажатие клавиш. + + +Также можно получать доступ к следующим параментрам экрана: + + + + +scrollX +scrollY + +## Данные только для чтения + +innerWidhth +innerHeight +outerWidhth +outerHeight +online - сокращение для window.navigator.online diff --git a/examples/projects/video12/code/svelte-todo-02/package.json b/examples/projects/video12/code/svelte-todo-02/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video12/code/svelte-todo-02/public/favicon.png b/examples/projects/video12/code/svelte-todo-02/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video12/code/svelte-todo-02/public/favicon.png differ diff --git a/examples/projects/video12/code/svelte-todo-02/public/global.css b/examples/projects/video12/code/svelte-todo-02/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video12/code/svelte-todo-02/public/index.html b/examples/projects/video12/code/svelte-todo-02/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video12/code/svelte-todo-02/rollup.config.js b/examples/projects/video12/code/svelte-todo-02/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video12/code/svelte-todo-02/scripts/setupTypeScript.js b/examples/projects/video12/code/svelte-todo-02/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video12/code/svelte-todo-02/src/actions/draggable.js b/examples/projects/video12/code/svelte-todo-02/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-02/src/components/AddTodoItem.svelte b/examples/projects/video12/code/svelte-todo-02/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video12/code/svelte-todo-02/src/components/Form.svelte b/examples/projects/video12/code/svelte-todo-02/src/components/Form.svelte new file mode 100644 index 0000000..d96a524 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/components/Form.svelte @@ -0,0 +1,53 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-02/src/components/TodoItem.svelte b/examples/projects/video12/code/svelte-todo-02/src/components/TodoItem.svelte new file mode 100644 index 0000000..cc5fd5d --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-02/src/layouts/BaseLayout.svelte b/examples/projects/video12/code/svelte-todo-02/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video12/code/svelte-todo-02/src/main.js b/examples/projects/video12/code/svelte-todo-02/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-02/src/store/customStore.js b/examples/projects/video12/code/svelte-todo-02/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-02/src/store/store.js b/examples/projects/video12/code/svelte-todo-02/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-02/src/store/todoStats.js b/examples/projects/video12/code/svelte-todo-02/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video12/code/svelte-todo-02/src/transitions/skew.js b/examples/projects/video12/code/svelte-todo-02/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-02/src/transitions/typewriter.js b/examples/projects/video12/code/svelte-todo-02/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-02/src/utils/format.js b/examples/projects/video12/code/svelte-todo-02/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-02/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-03/.gitignore b/examples/projects/video12/code/svelte-todo-03/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video12/code/svelte-todo-03/README.md b/examples/projects/video12/code/svelte-todo-03/README.md new file mode 100644 index 0000000..ad1fde2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/README.md @@ -0,0 +1,3 @@ +# + +`` - позволяет вставлять элементы в тег-`head` html-страницы. diff --git a/examples/projects/video12/code/svelte-todo-03/package.json b/examples/projects/video12/code/svelte-todo-03/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video12/code/svelte-todo-03/public/favicon.png b/examples/projects/video12/code/svelte-todo-03/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video12/code/svelte-todo-03/public/favicon.png differ diff --git a/examples/projects/video12/code/svelte-todo-03/public/global.css b/examples/projects/video12/code/svelte-todo-03/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video12/code/svelte-todo-03/public/index.html b/examples/projects/video12/code/svelte-todo-03/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video12/code/svelte-todo-03/rollup.config.js b/examples/projects/video12/code/svelte-todo-03/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video12/code/svelte-todo-03/scripts/setupTypeScript.js b/examples/projects/video12/code/svelte-todo-03/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + Home page + + + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video12/code/svelte-todo-03/src/actions/draggable.js b/examples/projects/video12/code/svelte-todo-03/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-03/src/components/AddTodoItem.svelte b/examples/projects/video12/code/svelte-todo-03/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video12/code/svelte-todo-03/src/components/Form.svelte b/examples/projects/video12/code/svelte-todo-03/src/components/Form.svelte new file mode 100644 index 0000000..d96a524 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/components/Form.svelte @@ -0,0 +1,53 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-03/src/components/TodoItem.svelte b/examples/projects/video12/code/svelte-todo-03/src/components/TodoItem.svelte new file mode 100644 index 0000000..cc5fd5d --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-03/src/layouts/BaseLayout.svelte b/examples/projects/video12/code/svelte-todo-03/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video12/code/svelte-todo-03/src/main.js b/examples/projects/video12/code/svelte-todo-03/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-03/src/store/customStore.js b/examples/projects/video12/code/svelte-todo-03/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-03/src/store/store.js b/examples/projects/video12/code/svelte-todo-03/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-03/src/store/todoStats.js b/examples/projects/video12/code/svelte-todo-03/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video12/code/svelte-todo-03/src/transitions/skew.js b/examples/projects/video12/code/svelte-todo-03/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-03/src/transitions/typewriter.js b/examples/projects/video12/code/svelte-todo-03/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-03/src/utils/format.js b/examples/projects/video12/code/svelte-todo-03/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-03/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/.gitignore b/examples/projects/video12/code/svelte-todo-04/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video12/code/svelte-todo-04/README.md b/examples/projects/video12/code/svelte-todo-04/README.md new file mode 100644 index 0000000..a9f9396 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/README.md @@ -0,0 +1,8 @@ +# + +`` позволяет рекурсивно включать самого себе в свою же разметку при таких условиях, когда мы не можем импортировать компонент сам в себя, +но нам нужно отобразить его в разментке. + +Классический пример - отображение структуры папок. + +`` не может отображаться на верхнем уровне разметки - только в блоках `{#if}` `{#each}`, чтобы избежать бесконечного цикла. \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/package.json b/examples/projects/video12/code/svelte-todo-04/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video12/code/svelte-todo-04/public/favicon.png b/examples/projects/video12/code/svelte-todo-04/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video12/code/svelte-todo-04/public/favicon.png differ diff --git a/examples/projects/video12/code/svelte-todo-04/public/global.css b/examples/projects/video12/code/svelte-todo-04/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video12/code/svelte-todo-04/public/index.html b/examples/projects/video12/code/svelte-todo-04/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video12/code/svelte-todo-04/rollup.config.js b/examples/projects/video12/code/svelte-todo-04/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video12/code/svelte-todo-04/scripts/setupTypeScript.js b/examples/projects/video12/code/svelte-todo-04/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + Home page + + + + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video12/code/svelte-todo-04/src/actions/draggable.js b/examples/projects/video12/code/svelte-todo-04/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/components/AddTodoItem.svelte b/examples/projects/video12/code/svelte-todo-04/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video12/code/svelte-todo-04/src/components/Dir.svelte b/examples/projects/video12/code/svelte-todo-04/src/components/Dir.svelte new file mode 100644 index 0000000..6ceec20 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/components/Dir.svelte @@ -0,0 +1,20 @@ + + +

{name}

+ +
    + {#each files as file} +
  • + {#if file.type === 'dir'} + + {:else} + + {/if} +
  • + {/each} +
\ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/components/File.svelte b/examples/projects/video12/code/svelte-todo-04/src/components/File.svelte new file mode 100644 index 0000000..cf5f0c8 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/components/File.svelte @@ -0,0 +1,5 @@ + + +

{name}

\ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/components/Form.svelte b/examples/projects/video12/code/svelte-todo-04/src/components/Form.svelte new file mode 100644 index 0000000..d96a524 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/components/Form.svelte @@ -0,0 +1,53 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/components/TodoItem.svelte b/examples/projects/video12/code/svelte-todo-04/src/components/TodoItem.svelte new file mode 100644 index 0000000..cc5fd5d --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/components/files.js b/examples/projects/video12/code/svelte-todo-04/src/components/files.js new file mode 100644 index 0000000..acc7d4c --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/components/files.js @@ -0,0 +1,18 @@ +export const files = [{ + type: 'dir', + name:'photos', + files: [{ + type: 'dir', + name: 'nature', + files: [{ + type: 'file', + name: 'nature1.jpg' + },{ + type: 'file', + name: 'nature2.jpg' + }, + ] + } + + ] +}]; \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/layouts/BaseLayout.svelte b/examples/projects/video12/code/svelte-todo-04/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video12/code/svelte-todo-04/src/main.js b/examples/projects/video12/code/svelte-todo-04/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/store/customStore.js b/examples/projects/video12/code/svelte-todo-04/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/store/store.js b/examples/projects/video12/code/svelte-todo-04/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/store/todoStats.js b/examples/projects/video12/code/svelte-todo-04/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video12/code/svelte-todo-04/src/transitions/skew.js b/examples/projects/video12/code/svelte-todo-04/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/transitions/typewriter.js b/examples/projects/video12/code/svelte-todo-04/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-04/src/utils/format.js b/examples/projects/video12/code/svelte-todo-04/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-04/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/.gitignore b/examples/projects/video12/code/svelte-todo-05/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video12/code/svelte-todo-05/README.md b/examples/projects/video12/code/svelte-todo-05/README.md new file mode 100644 index 0000000..10d5717 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/README.md @@ -0,0 +1,6 @@ +# + +`` позволяет отрисовать компонент динамически, когда заранее неизвестно какой компонент нужно отрисовать. +При этом хотелось бы избежать многочиселнных блоков `{#if} ... {:else}` в разметке. + +`` может быть полезен для реализации такого компонента, как, например, `Tabs`. diff --git a/examples/projects/video12/code/svelte-todo-05/package.json b/examples/projects/video12/code/svelte-todo-05/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video12/code/svelte-todo-05/public/favicon.png b/examples/projects/video12/code/svelte-todo-05/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video12/code/svelte-todo-05/public/favicon.png differ diff --git a/examples/projects/video12/code/svelte-todo-05/public/global.css b/examples/projects/video12/code/svelte-todo-05/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video12/code/svelte-todo-05/public/index.html b/examples/projects/video12/code/svelte-todo-05/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video12/code/svelte-todo-05/rollup.config.js b/examples/projects/video12/code/svelte-todo-05/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video12/code/svelte-todo-05/scripts/setupTypeScript.js b/examples/projects/video12/code/svelte-todo-05/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + Home page + + + + + + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video12/code/svelte-todo-05/src/actions/draggable.js b/examples/projects/video12/code/svelte-todo-05/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/components/AddTodoItem.svelte b/examples/projects/video12/code/svelte-todo-05/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video12/code/svelte-todo-05/src/components/Dir.svelte b/examples/projects/video12/code/svelte-todo-05/src/components/Dir.svelte new file mode 100644 index 0000000..6ceec20 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/components/Dir.svelte @@ -0,0 +1,20 @@ + + +

{name}

+ +
    + {#each files as file} +
  • + {#if file.type === 'dir'} + + {:else} + + {/if} +
  • + {/each} +
\ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/components/File.svelte b/examples/projects/video12/code/svelte-todo-05/src/components/File.svelte new file mode 100644 index 0000000..cf5f0c8 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/components/File.svelte @@ -0,0 +1,5 @@ + + +

{name}

\ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/components/Form.svelte b/examples/projects/video12/code/svelte-todo-05/src/components/Form.svelte new file mode 100644 index 0000000..d96a524 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/components/Form.svelte @@ -0,0 +1,53 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/components/TodoItem.svelte b/examples/projects/video12/code/svelte-todo-05/src/components/TodoItem.svelte new file mode 100644 index 0000000..cc5fd5d --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/components/TodoItem.svelte @@ -0,0 +1,101 @@ + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/components/files.js b/examples/projects/video12/code/svelte-todo-05/src/components/files.js new file mode 100644 index 0000000..acc7d4c --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/components/files.js @@ -0,0 +1,18 @@ +export const files = [{ + type: 'dir', + name:'photos', + files: [{ + type: 'dir', + name: 'nature', + files: [{ + type: 'file', + name: 'nature1.jpg' + },{ + type: 'file', + name: 'nature2.jpg' + }, + ] + } + + ] +}]; \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/components/tabs/Tab1.svelte b/examples/projects/video12/code/svelte-todo-05/src/components/tabs/Tab1.svelte new file mode 100644 index 0000000..73da59d --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/components/tabs/Tab1.svelte @@ -0,0 +1 @@ +

===> Tab 1

\ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/components/tabs/Tab2.svelte b/examples/projects/video12/code/svelte-todo-05/src/components/tabs/Tab2.svelte new file mode 100644 index 0000000..e570285 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/components/tabs/Tab2.svelte @@ -0,0 +1,4 @@ + +

===> Tab 2 [{name}]

\ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/components/tabs/Tabs.svelte b/examples/projects/video12/code/svelte-todo-05/src/components/tabs/Tabs.svelte new file mode 100644 index 0000000..ce6aabf --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/components/tabs/Tabs.svelte @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/layouts/BaseLayout.svelte b/examples/projects/video12/code/svelte-todo-05/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video12/code/svelte-todo-05/src/main.js b/examples/projects/video12/code/svelte-todo-05/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/store/customStore.js b/examples/projects/video12/code/svelte-todo-05/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/store/store.js b/examples/projects/video12/code/svelte-todo-05/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/store/todoStats.js b/examples/projects/video12/code/svelte-todo-05/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video12/code/svelte-todo-05/src/transitions/skew.js b/examples/projects/video12/code/svelte-todo-05/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/transitions/typewriter.js b/examples/projects/video12/code/svelte-todo-05/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-05/src/utils/format.js b/examples/projects/video12/code/svelte-todo-05/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-05/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/.gitignore b/examples/projects/video12/code/svelte-todo-06/.gitignore new file mode 100644 index 0000000..da93220 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/examples/projects/video12/code/svelte-todo-06/README.md b/examples/projects/video12/code/svelte-todo-06/README.md new file mode 100644 index 0000000..5edeec2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/README.md @@ -0,0 +1,34 @@ +# + +Позволяет указывать параметры компиляции для каждого отдельного компонента. + +Важная функция `svelte.compile`, которая производит компиляцию компонента, который +превращает его в JavaScript-подуль, который далее экспортируется. + +Некотрые параметры данной функции могут быть переданы с помощью специального элемента ``. + + + +- immutable (по умолчанию) +- accessors (по умолчанию) +- namespace +- tag + +## immutable + +`` - объект не будет изменяться, а при изменении свойств, +будет создаваться новый объект. + +Эта опция улучшает оптимизацию кода. + +## accessors + +`` + +## namespace + +`namespace` - это пространство имён, где компонент будет использован. + +## tag + +`tag` - это имя, с которым будет ассоциироваться созданный компонент. Должен быть написан в нижнем регистре латинскими символами. \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/package.json b/examples/projects/video12/code/svelte-todo-06/package.json new file mode 100644 index 0000000..52f6216 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/package.json @@ -0,0 +1,25 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "d3-interpolate": "^3.0.1", + "sirv-cli": "^1.0.0", + "uuid": "^8.3.2" + } +} diff --git a/examples/projects/video12/code/svelte-todo-06/public/favicon.png b/examples/projects/video12/code/svelte-todo-06/public/favicon.png new file mode 100644 index 0000000..7e6f5eb Binary files /dev/null and b/examples/projects/video12/code/svelte-todo-06/public/favicon.png differ diff --git a/examples/projects/video12/code/svelte-todo-06/public/global.css b/examples/projects/video12/code/svelte-todo-06/public/global.css new file mode 100644 index 0000000..508a502 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/public/global.css @@ -0,0 +1,64 @@ +html, body { + position: relative; + width: 100%; + height: 100%; +} + +body { + color: #333; + margin: 0; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +a { + color: rgb(0,100,200); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:visited { + color: rgb(0,80,160); +} + +label { + display: block; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + -webkit-padding: 0.4em 0; + padding: 0.4em; + margin: 0 0 0.5em 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; +} + +input:disabled { + color: #ccc; +} + +button { + color: #333; + background-color: #f4f4f4; + outline: none; +} + +button:disabled { + color: #999; +} + +button:not(:disabled):active { + background-color: #ddd; +} + +button:focus { + border-color: #666; +} + diff --git a/examples/projects/video12/code/svelte-todo-06/public/index.html b/examples/projects/video12/code/svelte-todo-06/public/index.html new file mode 100644 index 0000000..5da7ed3 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/public/index.html @@ -0,0 +1,18 @@ + + + + + + + Svelte app + + + + + + + + + + + diff --git a/examples/projects/video12/code/svelte-todo-06/rollup.config.js b/examples/projects/video12/code/svelte-todo-06/rollup.config.js new file mode 100644 index 0000000..e8965ec --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/examples/projects/video12/code/svelte-todo-06/scripts/setupTypeScript.js b/examples/projects/video12/code/svelte-todo-06/scripts/setupTypeScript.js new file mode 100644 index 0000000..133658a --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + + + Home page + + + + + + + +
+ {greeting} and Welcome! +
+ + +
+ {$todoStats.doneCount} / {$todoStats.totalCount} +
+ +
+
+ {#each $todoItems.filter(item => item.done === false) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+ {#each $todoItems.filter(item => item.done === true) as { id, text, done }, index (id)} +
+ handleDoneChange(id, event.detail)} + on:remove={() => handleRemove(id)} + /> +
+ {:else} + No items yet. + {/each} +
+ +
+
+ + + diff --git a/examples/projects/video12/code/svelte-todo-06/src/actions/draggable.js b/examples/projects/video12/code/svelte-todo-06/src/actions/draggable.js new file mode 100644 index 0000000..d4d3dba --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/actions/draggable.js @@ -0,0 +1,53 @@ +export function draggable(node, {offset=0}) { + + // on mount + let _offset = offset; + let x = 0; + let y = 0; + + function handleMousedown(event) { + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragstart', { + detail: {x, y}})); + + window.addEventListener('mousemove', handleMousemove); + window.addEventListener('mouseup', handleMouseup); + } + + function handleMousemove(event){ + + const dx = event.clientX - x; + const dy = event.clientY - y; + + x = event.clientX; + y = event.clientY; + + node.dispatchEvent(new CustomEvent('dragmove', { + detail: {x, y, dx, dy}})) + } + + function handleMouseup(event){ + x = event.clientX + _offset; + y = event.clientY + _offset; + node.dispatchEvent(new CustomEvent('dragend', { + detail: {x, y}})); + + window.removeEventListener('mousemove', handleMousemove); + window.removeEventListener('mouseup', handleMouseup); + + } + + + node.addEventListener('mousedown', handleMousedown); + + return { + update(offset){ + _offset = offset; + }, + destroy() { + // on destroy + node.removeEventListener('mousedown', handleMousedown); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/components/AddTodoItem.svelte b/examples/projects/video12/code/svelte-todo-06/src/components/AddTodoItem.svelte new file mode 100644 index 0000000..87df909 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/components/AddTodoItem.svelte @@ -0,0 +1,5 @@ + + + diff --git a/examples/projects/video12/code/svelte-todo-06/src/components/Dir.svelte b/examples/projects/video12/code/svelte-todo-06/src/components/Dir.svelte new file mode 100644 index 0000000..6ceec20 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/components/Dir.svelte @@ -0,0 +1,20 @@ + + +

{name}

+ +
    + {#each files as file} +
  • + {#if file.type === 'dir'} + + {:else} + + {/if} +
  • + {/each} +
\ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/components/File.svelte b/examples/projects/video12/code/svelte-todo-06/src/components/File.svelte new file mode 100644 index 0000000..cf5f0c8 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/components/File.svelte @@ -0,0 +1,5 @@ + + +

{name}

\ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/components/Form.svelte b/examples/projects/video12/code/svelte-todo-06/src/components/Form.svelte new file mode 100644 index 0000000..d96a524 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/components/Form.svelte @@ -0,0 +1,53 @@ + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/components/TodoItem.svelte b/examples/projects/video12/code/svelte-todo-06/src/components/TodoItem.svelte new file mode 100644 index 0000000..27dc59c --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/components/TodoItem.svelte @@ -0,0 +1,104 @@ + + + + + +
+ + + +

{title}

+ +
+ + + + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/components/files.js b/examples/projects/video12/code/svelte-todo-06/src/components/files.js new file mode 100644 index 0000000..acc7d4c --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/components/files.js @@ -0,0 +1,18 @@ +export const files = [{ + type: 'dir', + name:'photos', + files: [{ + type: 'dir', + name: 'nature', + files: [{ + type: 'file', + name: 'nature1.jpg' + },{ + type: 'file', + name: 'nature2.jpg' + }, + ] + } + + ] +}]; \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/components/tabs/Tab1.svelte b/examples/projects/video12/code/svelte-todo-06/src/components/tabs/Tab1.svelte new file mode 100644 index 0000000..73da59d --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/components/tabs/Tab1.svelte @@ -0,0 +1 @@ +

===> Tab 1

\ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/components/tabs/Tab2.svelte b/examples/projects/video12/code/svelte-todo-06/src/components/tabs/Tab2.svelte new file mode 100644 index 0000000..e570285 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/components/tabs/Tab2.svelte @@ -0,0 +1,4 @@ + +

===> Tab 2 [{name}]

\ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/components/tabs/Tabs.svelte b/examples/projects/video12/code/svelte-todo-06/src/components/tabs/Tabs.svelte new file mode 100644 index 0000000..ce6aabf --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/components/tabs/Tabs.svelte @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/layouts/BaseLayout.svelte b/examples/projects/video12/code/svelte-todo-06/src/layouts/BaseLayout.svelte new file mode 100644 index 0000000..cee7f27 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/layouts/BaseLayout.svelte @@ -0,0 +1,34 @@ +
+
+ +
+
+ +
+ +
+ + diff --git a/examples/projects/video12/code/svelte-todo-06/src/main.js b/examples/projects/video12/code/svelte-todo-06/src/main.js new file mode 100644 index 0000000..144b676 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/main.js @@ -0,0 +1,9 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, + intro: true +}, +); + +export default app; \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/store/customStore.js b/examples/projects/video12/code/svelte-todo-06/src/store/customStore.js new file mode 100644 index 0000000..984e740 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/store/customStore.js @@ -0,0 +1,53 @@ +import {writable} from 'svelte/store'; +import { v4 as uuid } from 'uuid'; + +function createTodoStore(){ + + const store = writable( + Array.from({length: 3}, (_, index) =>({ + id: uuid(), + text: `Todo item ${++index} from server`, + done:false + })) + ); + const {subscribe, update} = store; + + return { + subscribe, + + add: (text) => { + update(items => { + return [...items, { + id: uuid(), + text, + done: false, + }, + ]; + }); + + }, + setDone: (id, done) => { + update(items => { + return items.map(item => { + if(item.id === id){ + return { + ...item, done + } + } else { + return item + } + }); + }); + }, + remove: (id) => { + update(items => { + return items.filter(item => item.id !== id ); + }); + }, + set: (items)=>{ + store.set(items); + } + } +} + +export const todoItems = createTodoStore(); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/store/store.js b/examples/projects/video12/code/svelte-todo-06/src/store/store.js new file mode 100644 index 0000000..84f3660 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/store/store.js @@ -0,0 +1,6 @@ +import {writable} from 'svelte/store'; + +export const todoItems = writable([], () => { + console.log('subscribed'); + return () => console.log('unsubscribe'); +}); \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/store/todoStats.js b/examples/projects/video12/code/svelte-todo-06/src/store/todoStats.js new file mode 100644 index 0000000..7b01ad2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/store/todoStats.js @@ -0,0 +1,15 @@ + import {derived} from 'svelte/store'; + import {todoItems} from './customStore'; + + export const todoStats = derived ( + [todoItems], + ([todoItems]) => { + const doneCount = todoItems.filter(item => item.done).length; + const totalCount = todoItems.length; + return { + doneCount, + totalCount, + leftTodoCount: totalCount - doneCount + } + } + ); diff --git a/examples/projects/video12/code/svelte-todo-06/src/transitions/skew.js b/examples/projects/video12/code/svelte-todo-06/src/transitions/skew.js new file mode 100644 index 0000000..f38251c --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/transitions/skew.js @@ -0,0 +1,14 @@ +import {quadIn} from 'svelte/easing'; +// node - элемент, на которую будет применяться эффект +// Options +export function skew(node, {duration}) { + return { + duration, + css: time => { + const eased = quadIn(time); + return ` + transform: scale(${eased}) skewX(${eased * 180}deg); + ` + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/transitions/typewriter.js b/examples/projects/video12/code/svelte-todo-06/src/transitions/typewriter.js new file mode 100644 index 0000000..ed83fe2 --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/transitions/typewriter.js @@ -0,0 +1,21 @@ +export function typewriter(node, { speed = 100 }) { + const isValid = ( + node.childNodes.length === 1 && + node.childNodes[0].nodeType === Node.TEXT_NODE + ); + + if(!isValid) { + throw new Error('Please provide plain text'); + } + + const text = node.textContent; + const duration = text.length * speed; + + return { + duration, + tick: (time) => { + const i = Math.round(text.length * time); + node.textContent = text.slice(0, i); + } + } +} \ No newline at end of file diff --git a/examples/projects/video12/code/svelte-todo-06/src/utils/format.js b/examples/projects/video12/code/svelte-todo-06/src/utils/format.js new file mode 100644 index 0000000..0e4913e --- /dev/null +++ b/examples/projects/video12/code/svelte-todo-06/src/utils/format.js @@ -0,0 +1,13 @@ +export function format(value) { + const formatted = value + .replace(/\D/g, '') + .replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){ + let output = ""; + if (p1) output = `(${p1}`; + if (p2) output += `${p2})`; + if (p3) output += ` ${p3}`; + if (p4) output += ` ${p4}`; + return output; + }); + return formatted; +} \ No newline at end of file