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 и как он устроен?
+
+[](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?
+
+[](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 компонента
+
+[](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
+
+[](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 @@
+# События и обработка событий
+
+[](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)
+
+[](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("
+
+
+
+
+
+{#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("
+
+
+
+
+
\ 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("
+
+
+
+
+
+
+
+{#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)
+
+[](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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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)
+
+[](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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+{: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("
+
+
+
+
+
\ 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("
+
+
+
+
+
\ 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("
+
+
+
+
+
\ 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)
+
+[](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("
+
+
+
+
+
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
+
+[](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("
+
+
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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 классов по условию.
+
+[](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("
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
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://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("
+
+
+
+
+
+
+
+
+
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("
+
+
+
+
+
+
+
+
+
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
+
+
+
+
+
+
+
+
+
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
+
+
+
+
+
+
\ 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
+
+
+
+
+
+
+
+
\ 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
+
+
+
+
+
+
+
+
\ 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