mirror of https://github.com/sveltejs/svelte
commit
7912d7c901
@ -1,7 +1,14 @@
|
||||
src/shared
|
||||
shared.js
|
||||
store.js
|
||||
test/test.js
|
||||
test/setup.js
|
||||
**/_actual.js
|
||||
**/expected.js
|
||||
**/expected.js
|
||||
test/*/samples/*/output.js
|
||||
node_modules
|
||||
|
||||
# output files
|
||||
animate/*.js
|
||||
esing/*.js
|
||||
internal/*.js
|
||||
motion/*.js
|
||||
store/*.js
|
||||
transition/*.js
|
||||
index.js
|
||||
compiler.js
|
||||
|
@ -0,0 +1,99 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
rules: {
|
||||
indent: 'off',
|
||||
'no-unused-vars': 'off',
|
||||
semi: [2, 'always'],
|
||||
'keyword-spacing': [2, { before: true, after: true }],
|
||||
'space-before-blocks': [2, 'always'],
|
||||
'no-mixed-spaces-and-tabs': [2, 'smart-tabs'],
|
||||
'no-cond-assign': 0,
|
||||
'object-shorthand': [2, 'always'],
|
||||
'no-const-assign': 2,
|
||||
'no-class-assign': 2,
|
||||
'no-this-before-super': 2,
|
||||
'no-var': 2,
|
||||
'no-unreachable': 2,
|
||||
'valid-typeof': 2,
|
||||
'quote-props': [2, 'as-needed'],
|
||||
'one-var': [2, 'never'],
|
||||
'prefer-arrow-callback': 2,
|
||||
'prefer-const': [2, { destructuring: 'all' }],
|
||||
'arrow-spacing': 2,
|
||||
'no-inner-declarations': 0,
|
||||
'require-atomic-updates': 'off',
|
||||
'@typescript-eslint/indent': [
|
||||
'error',
|
||||
'tab',
|
||||
{
|
||||
SwitchCase: 1,
|
||||
ignoredNodes: ['TemplateLiteral']
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/camelcase': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/array-type': ['error', 'array-simple'],
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/explicit-member-accessibility': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_'
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/no-object-literal-type-assertion': [
|
||||
'error',
|
||||
{
|
||||
allowAsParameter: true
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/no-unused-vars': 'off'
|
||||
},
|
||||
globals: {
|
||||
globalThis: false
|
||||
},
|
||||
env: {
|
||||
es6: true,
|
||||
browser: true,
|
||||
node: true,
|
||||
mocha: true
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:import/errors',
|
||||
'plugin:import/warnings',
|
||||
'plugin:import/typescript',
|
||||
'plugin:@typescript-eslint/recommended'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 9,
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: ['svelte3'],
|
||||
settings: {
|
||||
'import/core-modules': [
|
||||
'svelte',
|
||||
'svelte/internal',
|
||||
'svelte/store',
|
||||
'svelte/easing',
|
||||
'estree'
|
||||
],
|
||||
'svelte3/compiler': require('./compiler')
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.js'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-var-requires': 'off'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['*.svelte'],
|
||||
processor: 'svelte3/svelte3',
|
||||
rules: {
|
||||
'@typescript-eslint/indent': 'off'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
@ -1,44 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"rules": {
|
||||
"indent": [2, "tab", { "SwitchCase": 1 }],
|
||||
"semi": [2, "always"],
|
||||
"keyword-spacing": [2, { "before": true, "after": true }],
|
||||
"space-before-blocks": [2, "always"],
|
||||
"no-mixed-spaces-and-tabs": [2, "smart-tabs"],
|
||||
"no-cond-assign": 0,
|
||||
"no-unused-vars": 2,
|
||||
"object-shorthand": [2, "always"],
|
||||
"no-const-assign": 2,
|
||||
"no-class-assign": 2,
|
||||
"no-this-before-super": 2,
|
||||
"no-var": 2,
|
||||
"no-unreachable": 2,
|
||||
"valid-typeof": 2,
|
||||
"quote-props": [2, "as-needed"],
|
||||
"one-var": [2, "never"],
|
||||
"prefer-arrow-callback": 2,
|
||||
"prefer-const": [2, { "destructuring": "all" }],
|
||||
"arrow-spacing": 2,
|
||||
"no-inner-declarations": 0
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/warnings"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"settings": {
|
||||
"import/core-modules": ["svelte"],
|
||||
"svelte3/extensions": ["html"]
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
[ignore]
|
||||
<PROJECT_ROOT>/dist/.*
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
|
||||
[options]
|
||||
strip_root=true
|
@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: 'New Feature'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. For example: I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**How important is this feature to you?**
|
||||
Note: the more honest and specific you are here the more we will take you seriously.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
@ -0,0 +1,12 @@
|
||||
---
|
||||
name: Questions and help
|
||||
about: If you think you need help with something related to Svelte
|
||||
title: ''
|
||||
labels: 'Question'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
This issue tracker is intended to collect bug reports and feature requests.
|
||||
|
||||
For help with installation, information on how features work, or questions about specific features of Svelte, please come and join us in the [Svelte Discord](https://svelte.dev/chat), or ask your question on [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte). Any issues open for help requests will be closed to keep from clogging up the issue tracker.
|
@ -1,7 +1,8 @@
|
||||
<!--
|
||||
Thank you for creating a pull request. Before submitting, please note the following:
|
||||
|
||||
* If your pull request implements a new feature, please raise an issue to discuss it before sending code. In many cases features are absent for a reason.
|
||||
* This message body should clearly illustrate what problems it solves. If there are related issues, remember to reference them.
|
||||
* Ideally, include a test that fails without this PR but passes with it. PRs will only be merged once they pass CI. (Remember to `npm run lint`!)
|
||||
-->
|
||||
|
||||
### Before submitting the PR, please make sure you do the following
|
||||
- [ ] It's really useful if your PR relates to an outstanding issue, so please reference it in your PR, or create an explanatory one for discussion. In many cases features are absent for a reason.
|
||||
- [ ] This message body should clearly illustrate what problems it solves. If there are related issues, remember to reference them.
|
||||
- [ ] Ideally, include a test that fails without this PR but passes with it. PRs will only be merged once they pass CI. (Remember to `npm run lint`!)
|
||||
### Tests
|
||||
- [ ] Run the tests tests with `npm test` or `yarn test`)
|
||||
|
After Width: | Height: | Size: 46 KiB |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,9 @@
|
||||
/*
|
||||
!/Dockerfile
|
||||
!/package.json
|
||||
!/package-lock.json
|
||||
!/__sapper__
|
||||
/__sapper__/*
|
||||
!/__sapper__/build
|
||||
!/static
|
||||
!/content
|
@ -0,0 +1,12 @@
|
||||
NODE_ENV=
|
||||
|
||||
PORT=
|
||||
BASEURL=
|
||||
DATABASE_URL=
|
||||
GITHUB_CLIENT_ID=
|
||||
GITHUB_CLIENT_SECRET=
|
||||
MAPBOX_ACCESS_TOKEN=
|
||||
|
||||
JWT_EXP=30d
|
||||
JWT_ALG=HS512
|
||||
JWT_KEY=
|
@ -0,0 +1,52 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
rules: {
|
||||
indent: [2, 'tab', { SwitchCase: 1 }],
|
||||
semi: [2, 'always'],
|
||||
'keyword-spacing': [2, { before: true, after: true }],
|
||||
'space-before-blocks': [2, 'always'],
|
||||
'no-mixed-spaces-and-tabs': [2, 'smart-tabs'],
|
||||
'no-cond-assign': 0,
|
||||
'no-unused-vars': 2,
|
||||
'object-shorthand': [2, 'always'],
|
||||
'no-const-assign': 2,
|
||||
'no-class-assign': 2,
|
||||
'no-this-before-super': 2,
|
||||
'no-var': 2,
|
||||
'no-unreachable': 2,
|
||||
'valid-typeof': 2,
|
||||
'quote-props': [2, 'as-needed'],
|
||||
'one-var': [2, 'never'],
|
||||
'prefer-arrow-callback': 2,
|
||||
'prefer-const': [2, { destructuring: 'all' }],
|
||||
'arrow-spacing': 2,
|
||||
'no-inner-declarations': 0,
|
||||
'require-atomic-updates': 0
|
||||
},
|
||||
env: {
|
||||
es6: true,
|
||||
browser: true,
|
||||
node: true,
|
||||
mocha: true
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:import/errors',
|
||||
'plugin:import/warnings'
|
||||
],
|
||||
plugins: ['svelte3'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.svelte'],
|
||||
processor: 'svelte3/svelte3'
|
||||
}
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 9,
|
||||
sourceType: 'module'
|
||||
},
|
||||
settings: {
|
||||
'import/core-modules': ['svelte'],
|
||||
'svelte3/compiler': require('svelte/compiler')
|
||||
}
|
||||
};
|
@ -1,44 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"rules": {
|
||||
"indent": [2, "tab", { "SwitchCase": 1 }],
|
||||
"semi": [2, "always"],
|
||||
"keyword-spacing": [2, { "before": true, "after": true }],
|
||||
"space-before-blocks": [2, "always"],
|
||||
"no-mixed-spaces-and-tabs": [2, "smart-tabs"],
|
||||
"no-cond-assign": 0,
|
||||
"no-unused-vars": 2,
|
||||
"object-shorthand": [2, "always"],
|
||||
"no-const-assign": 2,
|
||||
"no-class-assign": 2,
|
||||
"no-this-before-super": 2,
|
||||
"no-var": 2,
|
||||
"no-unreachable": 2,
|
||||
"valid-typeof": 2,
|
||||
"quote-props": [2, "as-needed"],
|
||||
"one-var": [2, "never"],
|
||||
"prefer-arrow-callback": 2,
|
||||
"prefer-const": [2, { "destructuring": "all" }],
|
||||
"arrow-spacing": 2,
|
||||
"no-inner-declarations": 0
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/warnings"
|
||||
],
|
||||
"plugins": ["svelte3"],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 8,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"settings": {
|
||||
"import/core-modules": ["svelte"]
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
#!include:.dockerignore
|
@ -0,0 +1,19 @@
|
||||
FROM mhart/alpine-node:12
|
||||
|
||||
# install dependencies
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci --production
|
||||
|
||||
###
|
||||
# Only copy over the Node pieces we need
|
||||
# ~> Saves 35MB
|
||||
###
|
||||
FROM mhart/alpine-node:slim-12
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=0 /app .
|
||||
COPY . .
|
||||
|
||||
EXPOSE 3000
|
||||
CMD ["node", "__sapper__/build"]
|
@ -0,0 +1,22 @@
|
||||
HASH := `git rev-parse --short HEAD`
|
||||
|
||||
SERVICE := svelte-website
|
||||
PROJECT := svelte-dev
|
||||
|
||||
IMAGE := gcr.io/$(PROJECT)/$(SERVICE):$(HASH)
|
||||
|
||||
sapper:
|
||||
@echo "\n~> updating template & contributors list"
|
||||
@npm run update
|
||||
@echo "\n~> building Sapper app"
|
||||
@npm run sapper
|
||||
|
||||
|
||||
docker:
|
||||
@echo "\n~> building docker image"
|
||||
@gcloud builds submit -t $(IMAGE)
|
||||
|
||||
|
||||
deploy: sapper docker
|
||||
@echo "\n~> deploying $(SERVICE) to Cloud Run servers"
|
||||
@gcloud beta run deploy $(SERVICE) --allow-unauthenticated --platform managed --region us-central1 --image $(IMAGE) --memory=512Mi
|
@ -0,0 +1,2 @@
|
||||
export const SLUG_PRESERVE_UNICODE = false;
|
||||
export const SLUG_SEPARATOR = '_';
|
@ -0,0 +1,33 @@
|
||||
---
|
||||
title: Setting up your editor
|
||||
description: Instructions for configuring linting and syntax highlighting
|
||||
author: Rich Harris
|
||||
authorURL: https://twitter.com/Rich_Harris
|
||||
draft: true
|
||||
---
|
||||
|
||||
*Coming soon* This post will walk you through setting up your editor so that recognises Svelte files:
|
||||
|
||||
* eslint-plugin-svelte3
|
||||
* svelte-vscode
|
||||
* associating .svelte files with HTML in VSCode, Sublime, Atom, etc etc etc
|
||||
|
||||
## Vim/Neovim
|
||||
|
||||
To treat all `*.svelte` files as HTML, add the following line to your `init.vim`:
|
||||
|
||||
```bash
|
||||
au! BufNewFile,BufRead *.svelte set ft=html
|
||||
```
|
||||
|
||||
To temporarily turn on HTML syntax highlighting for the current buffer, use:
|
||||
|
||||
```bash
|
||||
:set ft=html
|
||||
```
|
||||
|
||||
To set the filetype for a single file, use a [modeline](https://vim.fandom.com/wiki/Modeline_magic):
|
||||
|
||||
```bash
|
||||
<!-- vim: set ft=html :-->
|
||||
```
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Svelte for new developers
|
||||
description: Never used Node.js or the command line? No problem
|
||||
author: Rich Harris
|
||||
authorURL: https://twitter.com/Rich_Harris
|
||||
draft: true
|
||||
---
|
||||
|
||||
*Coming soon* This blog post will walk you through installing Node.js and git and using Terminal.app to clone a project template and start developing with Svelte
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Before we begin
|
||||
---
|
||||
|
||||
> Temporary note: This document is a work-in-progress. Please forgive any missing or misleading parts, and don't be shy about asking for help in the [Discord chatroom](chat). The [tutorial](tutorial) is more complete; start there.
|
||||
|
||||
This page contains detailed API reference documentation. It's intended to be a resource for people who already have some familiarity with Svelte.
|
||||
|
||||
If that's not you (yet), you may prefer to visit the [interactive tutorial](tutorial) or the [examples](examples) before consulting this reference.
|
@ -0,0 +1,258 @@
|
||||
---
|
||||
title: Component format
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
Components are the building blocks of Svelte applications. They are written into `.svelte` files, using a superset of HTML.
|
||||
|
||||
All three sections — script, styles and markup — are optional.
|
||||
|
||||
```html
|
||||
<script>
|
||||
// logic goes here
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* styles go here */
|
||||
</style>
|
||||
|
||||
<!-- markup (zero or more items) goes here -->
|
||||
```
|
||||
|
||||
### <script>
|
||||
|
||||
A `<script>` block contains JavaScript that runs when a component instance is created. Variables declared (or imported) at the top level are 'visible' from the component's markup. There are four additional rules:
|
||||
|
||||
##### 1. `export` creates a component prop
|
||||
|
||||
---
|
||||
|
||||
Svelte uses the `export` keyword to mark a variable declaration as a *property* or *prop*, which means it becomes accessible to consumers of the component (see the section on [attributes and props](docs#Attributes_and_props) for more information).
|
||||
|
||||
```html
|
||||
<script>
|
||||
export let foo;
|
||||
|
||||
// Values that are passed in as props
|
||||
// are immediately available
|
||||
console.log({ foo });
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
You can specify a default value, which will be used if the component's consumer doesn't specify a prop.
|
||||
|
||||
In development mode (see the [compiler options](docs#svelte_compile)), a warning will be printed if no default is provided and the consumer does not specify a value. To squelch this warning, ensure that a default is specified, even if it is `undefined`.
|
||||
|
||||
```html
|
||||
<script>
|
||||
export let bar = 'optional default value';
|
||||
export let baz = undefined;
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
If you export a `const`, `class` or `function`, it is readonly from outside the component. Function *expressions* are valid props, however.
|
||||
|
||||
```html
|
||||
<script>
|
||||
// these are readonly
|
||||
export const thisIs = 'readonly';
|
||||
|
||||
export function greet(name) {
|
||||
alert(`hello ${name}!`);
|
||||
}
|
||||
|
||||
// this is a prop
|
||||
export let format = n => n.toFixed(2);
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
You can use reserved words as prop names.
|
||||
|
||||
```html
|
||||
<script>
|
||||
let className;
|
||||
|
||||
// creates a `class` property, even
|
||||
// though it is a reserved word
|
||||
export { className as class };
|
||||
</script>
|
||||
```
|
||||
|
||||
##### 2. Assignments are 'reactive'
|
||||
|
||||
---
|
||||
|
||||
To change component state and trigger a re-render, just assign to a locally declared variable.
|
||||
|
||||
Update expressions (`count += 1`) and property assignments (`obj.x = y`) have the same effect.
|
||||
|
||||
Because Svelte's reactivity is based on assignments, using array methods like `.push()` and `.splice()` won't automatically trigger updates. Options for getting around this can be found in the [tutorial](tutorial/updating-arrays-and-objects).
|
||||
|
||||
```html
|
||||
<script>
|
||||
let count = 0;
|
||||
|
||||
function handleClick () {
|
||||
// calling this function will trigger an
|
||||
// update if the markup references `count`
|
||||
count = count + 1;
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
##### 3. `$:` marks a statement as reactive
|
||||
|
||||
---
|
||||
|
||||
Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the `$:` [JS label syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). Reactive statements run immediately before the component updates, whenever the values that they depend on have changed.
|
||||
|
||||
```html
|
||||
<script>
|
||||
export let title;
|
||||
|
||||
// this will update `document.title` whenever
|
||||
// the `title` prop changes
|
||||
$: document.title = title;
|
||||
|
||||
$: {
|
||||
console.log(`multiple statements can be combined`);
|
||||
console.log(`the current title is ${title}`);
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
If a statement consists entirely of an assignment to an undeclared variable, Svelte will inject a `let` declaration on your behalf.
|
||||
|
||||
```html
|
||||
<script>
|
||||
export let num;
|
||||
|
||||
// we don't need to declare `squared` and `cubed`
|
||||
// — Svelte does it for us
|
||||
$: squared = num * num;
|
||||
$: cubed = squared * num;
|
||||
</script>
|
||||
```
|
||||
|
||||
##### 4. Prefix stores with `$` to access their values
|
||||
|
||||
---
|
||||
|
||||
A *store* is any object that allows reactive access to a value via a simple *store contract*.
|
||||
|
||||
The [`svelte/store` module](docs#svelte_store) contains minimal store implementations which fulfil this contract. You can use these as the basis for your own stores, or you can implement your stores from scratch.
|
||||
|
||||
A store must contain a `.subscribe` method, which must accept as its argument a subscription function. This subscription function must be immediately and synchronously called with the store's current value upon calling `.subscribe`. All of a store's active subscription functions must later be synchronously called whenever the store's value changes. The `.subscribe` method must also return an unsubscription function. Calling an unsubscription function must stop its subscription, and its corresponding subscription function must not be called again by the store.
|
||||
|
||||
A store may optionally contain a `.set` method, which must accept as its argument a new value for the store, and which synchronously calls all of the store's active subscription functions. Such a store is called a *writable store*.
|
||||
|
||||
```js
|
||||
const unsubscribe = store.subscribe(value => {
|
||||
console.log(value);
|
||||
}); // logs `value`
|
||||
|
||||
// later...
|
||||
unsubscribe();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Any time you have a reference to a store, you can access its value inside a component by prefixing it with the `$` character. This causes Svelte to declare the prefixed variable, and set up a store subscription that will be unsubscribed when appropriate.
|
||||
|
||||
Assignments to `$`-prefixed variables require that the variable be a writable store, and will result in a call to the store's `.set` method.
|
||||
|
||||
Note that the store must be declared at the top level of the component — not inside an `if` block or a function, for example.
|
||||
|
||||
Local variables (that do not represent store values) must *not* have a `$` prefix.
|
||||
|
||||
```html
|
||||
<script>
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
const count = writable(0);
|
||||
console.log($count); // logs 0
|
||||
|
||||
count.set(1);
|
||||
console.log($count); // logs 1
|
||||
|
||||
$count = 2;
|
||||
console.log($count); // logs 2
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
### <script context="module">
|
||||
|
||||
---
|
||||
|
||||
A `<script>` tag with a `context="module"` attribute runs once when the module first evaluates, rather than for each component instance. Values declared in this block are accessible from a regular `<script>` (and the component markup) but not vice versa.
|
||||
|
||||
You can `export` bindings from this block, and they will become exports of the compiled module.
|
||||
|
||||
You cannot `export default`, since the default export is the component itself.
|
||||
|
||||
> Variables defined in `module` scripts are not reactive — reassigning them will not trigger a rerender even though the variable itself will update. For values shared between multiple components, consider using a [store](https://svelte.dev/docs#svelte_store).
|
||||
|
||||
```html
|
||||
<script context="module">
|
||||
let totalComponents = 0;
|
||||
|
||||
// this allows an importer to do e.g.
|
||||
// `import Example, { alertTotal } from './Example.svelte'`
|
||||
export function alertTotal() {
|
||||
alert(totalComponents);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
totalComponents += 1;
|
||||
console.log(`total number of times this component has been created: ${totalComponents}`);
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
### <style>
|
||||
|
||||
---
|
||||
|
||||
CSS inside a `<style>` block will be scoped to that component.
|
||||
|
||||
This works by adding a class to affected elements, which is based on a hash of the component styles (e.g. `svelte-123xyz`).
|
||||
|
||||
```html
|
||||
<style>
|
||||
p {
|
||||
/* this will only affect <p> elements in this component */
|
||||
color: burlywood;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
To apply styles to a selector globally, use the `:global(...)` modifier.
|
||||
|
||||
```html
|
||||
<style>
|
||||
:global(body) {
|
||||
/* this will apply to <body> */
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div :global(strong) {
|
||||
/* this will apply to all <strong> elements, in any
|
||||
component, that are inside <div> elements belonging
|
||||
to this component */
|
||||
color: goldenrod;
|
||||
}
|
||||
</style>
|
||||
```
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,348 @@
|
||||
---
|
||||
title: Compile time
|
||||
---
|
||||
|
||||
Typically, you won't interact with the Svelte compiler directly, but will instead integrate it into your build system using a bundler plugin:
|
||||
|
||||
* [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) for users of [Rollup](https://rollupjs.org)
|
||||
* [svelte-loader](https://github.com/sveltejs/svelte-loader) for users of [webpack](https://webpack.js.org)
|
||||
* [parcel-plugin-svelte](https://github.com/DeMoorJasper/parcel-plugin-svelte) for users of [Parcel](https://parceljs.org/)
|
||||
|
||||
Nonetheless, it's useful to understand how to use the compiler, since bundler plugins generally expose compiler options to you.
|
||||
|
||||
|
||||
|
||||
### `svelte.compile`
|
||||
|
||||
```js
|
||||
result: {
|
||||
js,
|
||||
css,
|
||||
ast,
|
||||
warnings,
|
||||
vars,
|
||||
stats
|
||||
} = svelte.compile(source: string, options?: {...})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
This is where the magic happens. `svelte.compile` takes your component source code, and turns it into a JavaScript module that exports a class.
|
||||
|
||||
```js
|
||||
const svelte = require('svelte/compiler');
|
||||
|
||||
const result = svelte.compile(source, {
|
||||
// options
|
||||
});
|
||||
```
|
||||
|
||||
The following options can be passed to the compiler. None are required:
|
||||
|
||||
<!-- | option | type | default
|
||||
| --- | --- | --- |
|
||||
| `filename` | string | `null`
|
||||
| `name` | string | `"Component"`
|
||||
| `format` | `"esm"` or `"cjs"` | `"esm"`
|
||||
| `generate` | `"dom"` or `"ssr"` | `"dom"`
|
||||
| `dev` | boolean | `false`
|
||||
| `immutable` | boolean | `false`
|
||||
| `hydratable` | boolean | `false`
|
||||
| `legacy` | boolean | `false`
|
||||
| `customElement` | boolean | `false`
|
||||
| `tag` | string | null
|
||||
| `accessors` | boolean | `false`
|
||||
| `css` | boolean | `true`
|
||||
| `preserveComments` | boolean | `false`
|
||||
| `preserveWhitespace` | boolean | `false`
|
||||
| `outputFilename` | string | `null`
|
||||
| `cssOutputFilename` | string | `null`
|
||||
| `sveltePath` | string | `"svelte"` -->
|
||||
|
||||
| option | default | description |
|
||||
| --- | --- | --- |
|
||||
| `filename` | `null` | `string` used for debugging hints and sourcemaps. Your bundler plugin will set it automatically.
|
||||
| `name` | `"Component"` | `string` that sets the name of the resulting JavaScript class (though the compiler will rename it if it would otherwise conflict with other variables in scope). It will normally be inferred from `filename`.
|
||||
| `format` | `"esm"` | If `"esm"`, creates a JavaScript module (with `import` and `export`). If `"cjs"`, creates a CommonJS module (with `require` and `module.exports`), which is useful in some server-side rendering situations or for testing.
|
||||
| `generate` | `"dom"` | If `"dom"`, Svelte emits a JavaScript class for mounting to the DOM. If `"ssr"`, Svelte emits an object with a `render` method suitable for server-side rendering. If `false`, no JavaScript or CSS is returned; just metadata.
|
||||
| `dev` | `false` | If `true`, causes extra code to be added to components that will perform runtime checks and provide debugging information during development.
|
||||
| `immutable` | `false` | If `true`, tells the compiler that you promise not to mutate any objects. This allows it to be less conservative about checking whether values have changed.
|
||||
| `hydratable` | `false` | If `true`, enables the `hydrate: true` runtime option, which allows a component to upgrade existing DOM rather than creating new DOM from scratch.
|
||||
| `legacy` | `false` | If `true`, generates code that will work in IE9 and IE10, which don't support things like `element.dataset`.
|
||||
| `accessors` | `false` | If `true`, getters and setters will be created for the component's props. If `false`, they will only be created for readonly exported values (i.e. those declared with `const`, `class` and `function`). If compiling with `customElement: true` this option defaults to `true`.
|
||||
| `customElement` | `false` | If `true`, tells the compiler to generate a custom element constructor instead of a regular Svelte component.
|
||||
| `tag` | `null` | A `string` that tells Svelte what tag name to register the custom element with. It must be a lowercase alphanumeric string with at least one hyphen, e.g. `"my-element"`.
|
||||
| `css` | `true` | If `true`, styles will be included in the JavaScript class and injected at runtime. It's recommended that you set this to `false` and use the CSS that is statically generated, as it will result in smaller JavaScript bundles and better performance.
|
||||
| `preserveComments` | `false` | If `true`, your HTML comments will be preserved during server-side rendering. By default, they are stripped out.
|
||||
| `preserveWhitespace` | `false` | If `true`, whitespace inside and between elements is kept as you typed it, rather than optimised by Svelte.
|
||||
| `outputFilename` | `null` | A `string` used for your JavaScript sourcemap.
|
||||
| `cssOutputFilename` | `null` | A `string` used for your CSS sourcemap.
|
||||
| `sveltePath` | `"svelte"` | The location of the `svelte` package. Any imports from `svelte` or `svelte/[module]` will be modified accordingly.
|
||||
|
||||
|
||||
---
|
||||
|
||||
The returned `result` object contains the code for your component, along with useful bits of metadata.
|
||||
|
||||
```js
|
||||
const {
|
||||
js,
|
||||
css,
|
||||
ast,
|
||||
warnings,
|
||||
vars,
|
||||
stats
|
||||
} = svelte.compile(source);
|
||||
```
|
||||
|
||||
* `js` and `css` are objects with the following properties:
|
||||
* `code` is a JavaScript string
|
||||
* `map` is a sourcemap with additional `toString()` and `toUrl()` convenience methods
|
||||
* `ast` is an abstract syntax tree representing the structure of your component.
|
||||
* `warnings` is an array of warning objects that were generated during compilation. Each warning has several properties:
|
||||
* `code` is a string identifying the category of warning
|
||||
* `message` describes the issue in human-readable terms
|
||||
* `start` and `end`, if the warning relates to a specific location, are objects with `line`, `column` and `character` properties
|
||||
* `frame`, if applicable, is a string highlighting the offending code with line numbers
|
||||
* `vars` is an array of the component's declarations, used by [eslint-plugin-svelte3](https://github.com/sveltejs/eslint-plugin-svelte3) for example. Each variable has several properties:
|
||||
* `name` is self-explanatory
|
||||
* `export_name` is the name the value is exported as, if it is exported (will match `name` unless you do `export...as`)
|
||||
* `injected` is `true` if the declaration is injected by Svelte, rather than in the code you wrote
|
||||
* `module` is `true` if the value is declared in a `context="module"` script
|
||||
* `mutated` is `true` if the value's properties are assigned to inside the component
|
||||
* `reassigned` is `true` if the value is reassigned inside the component
|
||||
* `referenced` is `true` if the value is used outside the declaration
|
||||
* `writable` is `true` if the value was declared with `let` or `var` (but not `const`, `class` or `function`)
|
||||
* `stats` is an object used by the Svelte developer team for diagnosing the compiler. Avoid relying on it to stay the same!
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
```js
|
||||
compiled: {
|
||||
// `map` is a v3 sourcemap with toString()/toUrl() methods
|
||||
js: { code: string, map: {...} },
|
||||
css: { code: string, map: {...} },
|
||||
ast: {...}, // ESTree-like syntax tree for the component, including HTML, CSS and JS
|
||||
warnings: Array<{
|
||||
code: string,
|
||||
message: string,
|
||||
filename: string,
|
||||
pos: number,
|
||||
start: { line: number, column: number },
|
||||
end: { line: number, column: number },
|
||||
frame: string,
|
||||
toString: () => string
|
||||
}>,
|
||||
vars: Array<{
|
||||
name: string,
|
||||
export_name: string,
|
||||
injected: boolean,
|
||||
module: boolean,
|
||||
mutated: boolean,
|
||||
reassigned: boolean,
|
||||
referenced: boolean,
|
||||
writable: boolean
|
||||
}>,
|
||||
stats: {
|
||||
timings: { [label]: number }
|
||||
}
|
||||
} = svelte.compile(source: string, options?: {...})
|
||||
```
|
||||
|
||||
-->
|
||||
|
||||
|
||||
### `svelte.parse`
|
||||
|
||||
```js
|
||||
ast: object = svelte.parse(
|
||||
source: string,
|
||||
options?: {
|
||||
filename?: string,
|
||||
customElement?: boolean
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
The `parse` function parses a component, returning only its abstract syntax tree. Unlike compiling with the `generate: false` option, this will not perform any validation or other analysis of the component beyond parsing it.
|
||||
|
||||
|
||||
```js
|
||||
const svelte = require('svelte/compiler');
|
||||
|
||||
const ast = svelte.parse(source, { filename: 'App.svelte' });
|
||||
```
|
||||
|
||||
|
||||
### `svelte.preprocess`
|
||||
|
||||
```js
|
||||
result: {
|
||||
code: string,
|
||||
dependencies: Array<string>
|
||||
} = svelte.preprocess(
|
||||
source: string,
|
||||
preprocessors: Array<{
|
||||
markup?: (input: { source: string, filename: string }) => Promise<{
|
||||
code: string,
|
||||
dependencies?: Array<string>
|
||||
}>,
|
||||
script?: (input: { source: string, attributes: Record<string, string>, filename: string }) => Promise<{
|
||||
code: string,
|
||||
dependencies?: Array<string>
|
||||
}>,
|
||||
style?: (input: { source: string, attributes: Record<string, string>, filename: string }) => Promise<{
|
||||
code: string,
|
||||
dependencies?: Array<string>
|
||||
}>
|
||||
}>,
|
||||
options?: {
|
||||
filename?: string
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
The `preprocess` function provides convenient hooks for arbitrarily transforming component source code. For example, it can be used to convert a `<style lang="sass">` block into vanilla CSS.
|
||||
|
||||
The first argument is the component source code. The second is an array of *preprocessors* (or a single preprocessor, if you only have one), where a preprocessor is an object with `markup`, `script` and `style` functions, each of which is optional.
|
||||
|
||||
Each `markup`, `script` or `style` function must return an object (or a Promise that resolves to an object) with a `code` property, representing the transformed source code, and an optional array of `dependencies`.
|
||||
|
||||
The `markup` function receives the entire component source text, along with the component's `filename` if it was specified in the third argument.
|
||||
|
||||
> Preprocessor functions may additionally return a `map` object alongside `code` and `dependencies`, where `map` is a sourcemap representing the transformation. In current versions of Svelte it will be ignored, but future versions of Svelte may take account of preprocessor sourcemaps.
|
||||
|
||||
```js
|
||||
const svelte = require('svelte/compiler');
|
||||
|
||||
const { code } = svelte.preprocess(source, {
|
||||
markup: ({ content, filename }) => {
|
||||
return {
|
||||
code: content.replace(/foo/g, 'bar')
|
||||
};
|
||||
}
|
||||
}, {
|
||||
filename: 'App.svelte'
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
The `script` and `style` functions receive the contents of `<script>` and `<style>` elements respectively. In addition to `filename`, they get an object of the element's attributes.
|
||||
|
||||
If a `dependencies` array is returned, it will be included in the result object. This is used by packages like [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) to watch additional files for changes, in the case where your `<style>` tag has an `@import` (for example).
|
||||
|
||||
```js
|
||||
const svelte = require('svelte/compiler');
|
||||
const sass = require('node-sass');
|
||||
const { dirname } = require('path');
|
||||
|
||||
const { code, dependencies } = svelte.preprocess(source, {
|
||||
style: async ({ content, attributes, filename }) => {
|
||||
// only process <style lang="sass">
|
||||
if (attributes.lang !== 'sass') return;
|
||||
|
||||
const { css, stats } = await new Promise((resolve, reject) => sass.render({
|
||||
file: filename,
|
||||
data: content,
|
||||
includePaths: [
|
||||
dirname(filename),
|
||||
],
|
||||
}, (err, result) => {
|
||||
if (err) reject(err);
|
||||
else resolve(result);
|
||||
}));
|
||||
|
||||
return {
|
||||
code: css.toString(),
|
||||
dependencies: stats.includedFiles
|
||||
};
|
||||
}
|
||||
}, {
|
||||
filename: 'App.svelte'
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Multiple preprocessors can be used together. The output of the first becomes the input to the second. `markup` functions run first, then `script` and `style`.
|
||||
|
||||
```js
|
||||
const svelte = require('svelte/compiler');
|
||||
|
||||
const { code } = svelte.preprocess(source, [
|
||||
{
|
||||
markup: () => {
|
||||
console.log('this runs first');
|
||||
},
|
||||
script: () => {
|
||||
console.log('this runs third');
|
||||
},
|
||||
style: () => {
|
||||
console.log('this runs fifth');
|
||||
}
|
||||
},
|
||||
{
|
||||
markup: () => {
|
||||
console.log('this runs second');
|
||||
},
|
||||
script: () => {
|
||||
console.log('this runs fourth');
|
||||
},
|
||||
style: () => {
|
||||
console.log('this runs sixth');
|
||||
}
|
||||
}
|
||||
], {
|
||||
filename: 'App.svelte'
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### `svelte.walk`
|
||||
|
||||
```js
|
||||
walk(ast: Node, {
|
||||
enter(node: Node, parent: Node, prop: string, index: number)?: void,
|
||||
leave(node: Node, parent: Node, prop: string, index: number)?: void
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
The `walk` function provides a way to walk to abstract syntax trees generated by the parser, using the compiler's own built-in instance of [estree-walker](https://github.com/Rich-Harris/estree-walker).
|
||||
|
||||
The walker takes an abstract syntax tree to walk and an object with two optional methods: `enter` and `leave`. For each node, `enter` is called (if present). Then, unless `this.skip()` is called during `enter`, each of the children are traversed, and then `leave` is called on the node.
|
||||
|
||||
|
||||
```js
|
||||
const svelte = require('svelte/compiler');
|
||||
svelte.walk(ast, {
|
||||
enter(node, parent, prop, index) {
|
||||
do_something(node);
|
||||
if (should_skip_children(node)) {
|
||||
this.skip();
|
||||
}
|
||||
},
|
||||
leave(node, parent, prop, index) {
|
||||
do_something_else(node);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### `svelte.VERSION`
|
||||
|
||||
---
|
||||
|
||||
The current version, as set in package.json.
|
||||
|
||||
```js
|
||||
const svelte = require('svelte/compiler');
|
||||
console.log(`running svelte version ${svelte.VERSION}`);
|
||||
```
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"title": "Adding data"
|
||||
"title": "Hello world"
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
<script>
|
||||
import marked from 'marked';
|
||||
let value = `Some words are *italic*, some are **bold**`;
|
||||
let text = `Some words are *italic*, some are **bold**`;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
textarea { width: 100%; height: 200px; }
|
||||
</style>
|
||||
|
||||
<textarea bind:value></textarea>
|
||||
<textarea bind:value={text}></textarea>
|
||||
|
||||
{@html marked(value)}
|
||||
{@html marked(text)}
|
@ -1,65 +0,0 @@
|
||||
import { quintOut } from 'svelte/easing';
|
||||
|
||||
export default function crossfade({ send, receive, fallback }) {
|
||||
let requested = new Map();
|
||||
let provided = new Map();
|
||||
|
||||
function crossfade(from, node) {
|
||||
const to = node.getBoundingClientRect();
|
||||
const dx = from.left - to.left;
|
||||
const dy = from.top - to.top;
|
||||
|
||||
const style = getComputedStyle(node);
|
||||
const transform = style.transform === 'none' ? '' : style.transform;
|
||||
|
||||
return {
|
||||
duration: 400,
|
||||
easing: quintOut,
|
||||
css: (t, u) => `
|
||||
opacity: ${t};
|
||||
transform: ${transform} translate(${u * dx}px,${u * dy}px);
|
||||
`
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
send(node, params) {
|
||||
provided.set(params.key, {
|
||||
rect: node.getBoundingClientRect()
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (requested.has(params.key)) {
|
||||
const { rect } = requested.get(params.key);
|
||||
requested.delete(params.key);
|
||||
|
||||
return crossfade(rect, node);
|
||||
}
|
||||
|
||||
// if the node is disappearing altogether
|
||||
// (i.e. wasn't claimed by the other list)
|
||||
// then we need to supply an outro
|
||||
provided.delete(params.key);
|
||||
return fallback(node, params);
|
||||
};
|
||||
},
|
||||
|
||||
receive(node, params) {
|
||||
requested.set(params.key, {
|
||||
rect: node.getBoundingClientRect()
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (provided.has(params.key)) {
|
||||
const { rect } = provided.get(params.key);
|
||||
provided.delete(params.key);
|
||||
|
||||
return crossfade(rect, node);
|
||||
}
|
||||
|
||||
requested.delete(params.key);
|
||||
return fallback(node, params);
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
<script>
|
||||
import { interpolateString as interpolate } from 'd3-interpolate';
|
||||
import { tweened } from 'svelte/motion';
|
||||
|
||||
import Grid from './Grid.svelte';
|
||||
import Controls from './Controls.svelte';
|
||||
|
||||
import { eases, types } from './eases.js';
|
||||
|
||||
let current_type = 'In';
|
||||
let current_ease = 'sine';
|
||||
let duration = 2000;
|
||||
let current = eases.get(current_ease)[current_type];
|
||||
let playing = false;
|
||||
let width;
|
||||
|
||||
const ease_path = tweened(current.shape, { interpolate });
|
||||
const time = tweened(0);
|
||||
const value = tweened(1000);
|
||||
|
||||
async function runAnimations() {
|
||||
playing = true;
|
||||
|
||||
value.set(1000, {duration: 0});
|
||||
time.set(0, {duration: 0});
|
||||
|
||||
await ease_path.set(current.shape);
|
||||
await Promise.all([
|
||||
time.set(1000, {duration, easing: x => x}),
|
||||
value.set(0, {duration, easing: current.fn})
|
||||
]);
|
||||
|
||||
playing = false;
|
||||
}
|
||||
|
||||
$: current = eases.get(current_ease)[current_type];
|
||||
$: current && runAnimations();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.easing-vis {
|
||||
display: flex;
|
||||
max-height: 95%;
|
||||
max-width: 800px;
|
||||
margin: auto;
|
||||
padding: 10px;
|
||||
border: 1px solid #333;
|
||||
border-radius: 2px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
margin: 0 20px 0 0;
|
||||
}
|
||||
|
||||
.graph {
|
||||
transform: translate(200px,400px)
|
||||
}
|
||||
|
||||
@media (max-width:600px) {
|
||||
.easing-vis {
|
||||
flex-direction: column;
|
||||
max-height: calc(100% - 3rem);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div bind:offsetWidth={width} class="easing-vis">
|
||||
<svg viewBox="0 0 1400 1802">
|
||||
<g class="canvas">
|
||||
<Grid x={$time} y={$value}/>
|
||||
<g class="graph">
|
||||
<path
|
||||
d={$ease_path}
|
||||
stroke="#333"
|
||||
stroke-width="2"
|
||||
fill="none"
|
||||
/>
|
||||
|
||||
<path d="M0,23.647C0,22.41 27.014,0.407 28.496,0.025C29.978,-0.357 69.188,3.744 70.104,4.744C71.02,5.745 71.02,41.499 70.104,42.5C69.188,43.501 29.978,47.601 28.496,47.219C27.014,46.837 0,24.884 0,23.647Z"
|
||||
fill="#ff3e00"
|
||||
style="transform: translate(1060px, {($value - 24)}px)"
|
||||
/>
|
||||
|
||||
<circle
|
||||
cx="{$time}"
|
||||
cy="{$value}"
|
||||
r="15"
|
||||
fill="#ff3e00"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<Controls
|
||||
{eases}
|
||||
{types}
|
||||
{playing}
|
||||
{width}
|
||||
bind:duration
|
||||
bind:current_ease
|
||||
bind:current_type
|
||||
on:play={runAnimations}
|
||||
/>
|
||||
</div>
|
@ -0,0 +1,186 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let current_ease;
|
||||
export let current_type;
|
||||
export let eases;
|
||||
export let types;
|
||||
export let duration;
|
||||
export let playing;
|
||||
export let width;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
$: mobile = width && width < 600;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.easing-sidebar {
|
||||
width: 11em;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
li {
|
||||
padding: 5px 10px;
|
||||
background: #eee;
|
||||
border-radius: 2px;
|
||||
margin: 3px 0;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
li:hover {
|
||||
background: #676778;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.selected {
|
||||
background: #ff3e00;
|
||||
color: white;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
select {
|
||||
display: inline;
|
||||
padding: 0.2em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.duration {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.duration span {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.duration input {
|
||||
width: 80px;
|
||||
margin: 10px 10px 10px 0 ;
|
||||
}
|
||||
|
||||
.duration button {
|
||||
margin: 10px 5px;
|
||||
}
|
||||
|
||||
.duration .number {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.duration .play {
|
||||
margin: 0 5px 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width:600px) {
|
||||
.easing-types {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.easing-sidebar {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.duration .play {
|
||||
margin-left: auto;
|
||||
width: unset;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 0.9em;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
h3:nth-of-type(2) {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
ul li {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="easing-sidebar">
|
||||
<div class="easing-types">
|
||||
<h3>Ease</h3>
|
||||
{#if mobile}
|
||||
<select bind:value={current_ease}>
|
||||
{#each [...eases] as [name]}
|
||||
<option
|
||||
value={name}
|
||||
class:selected={name === current_ease}
|
||||
>
|
||||
{name}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else}
|
||||
<ul>
|
||||
{#each [...eases] as [name]}
|
||||
<li
|
||||
class:selected={name === current_ease}
|
||||
on:click={() => current_ease = name}
|
||||
>
|
||||
{name}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
<h3>Type</h3>
|
||||
{#if mobile }
|
||||
<select bind:value={current_type}>
|
||||
{#each types as [name, type]}
|
||||
<option
|
||||
value={type}
|
||||
>
|
||||
{name}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else}
|
||||
<ul>
|
||||
{#each types as [name, type]}
|
||||
<li
|
||||
class:selected={type === current_type}
|
||||
on:click={() => current_type = type}
|
||||
>
|
||||
{name}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
<h4>
|
||||
Duration
|
||||
</h4>
|
||||
<div class="duration">
|
||||
<span>
|
||||
<input type="number" bind:value={duration} min="0" step="100"/>
|
||||
<button class="number" on:click={() => duration -= 100}>-</button>
|
||||
<button class="number" on:click={() => duration += 100}>+</button>
|
||||
</span>
|
||||
<button class="play" on:click={() => dispatch('play')}>
|
||||
{playing ? 'Restart' : 'Play'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,62 @@
|
||||
<script>
|
||||
export let x, y;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.grid-line {
|
||||
stroke:#ccc;
|
||||
opacity: 0.5;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.grid-line-xy {
|
||||
stroke: tomato;
|
||||
stroke-width: 2;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:options namespace="svg" />
|
||||
|
||||
<rect
|
||||
x=0
|
||||
y=0
|
||||
width=1400
|
||||
height=1800
|
||||
stroke=#ccc
|
||||
style="opacity: 0.5"
|
||||
fill=none
|
||||
stroke-width=2
|
||||
/>
|
||||
|
||||
{#each { length: 8 } as _, i}
|
||||
{#if i < 6}
|
||||
<path
|
||||
d="M{(i+1) * 200} 0 L{(i+1)*200} 1802"
|
||||
class="grid-line"
|
||||
/>
|
||||
{/if}
|
||||
<path
|
||||
d="M0 {(i+1) * 200} L1400 {(i+1)*200} "
|
||||
class="grid-line"
|
||||
/>
|
||||
{/each}
|
||||
|
||||
<path
|
||||
style="transform: translateX({x+200}px)"
|
||||
d="M0 0 L0 1800"
|
||||
class="grid-line-xy"
|
||||
/>
|
||||
<path
|
||||
style="transform: translateY({y}px)"
|
||||
d="M0 400 L1400 400"
|
||||
class="grid-line-xy"
|
||||
/>
|
||||
<rect
|
||||
x=200
|
||||
y=400
|
||||
width=1000
|
||||
height=1000
|
||||
stroke=#999
|
||||
fill=none
|
||||
stroke-width=2
|
||||
/>
|
@ -0,0 +1,43 @@
|
||||
import * as eases from 'svelte/easing';
|
||||
|
||||
const processed_eases = {};
|
||||
|
||||
for (const ease in eases) {
|
||||
if (ease === "linear") {
|
||||
processed_eases.linear = eases.linear;
|
||||
} else {
|
||||
const name = ease.replace(/In$|InOut$|Out$/, '');
|
||||
const type = ease.match(/In$|InOut$|Out$/)[0];
|
||||
|
||||
if (!(name in processed_eases)) processed_eases[name] = {};
|
||||
processed_eases[name][type] = {};
|
||||
processed_eases[name][type].fn = eases[ease];
|
||||
|
||||
let shape = 'M0 1000';
|
||||
for (let i = 1; i <= 1000; i++) {
|
||||
shape = `${shape} L${(i / 1000) * 1000} ${1000 - eases[ease](i / 1000) * 1000} `;
|
||||
processed_eases[name][type].shape = shape;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const sorted_eases = new Map([
|
||||
['sine', processed_eases.sine],
|
||||
['quad', processed_eases.quad],
|
||||
['cubic', processed_eases.cubic],
|
||||
['quart', processed_eases.quart],
|
||||
['quint', processed_eases.quint],
|
||||
['expo', processed_eases.expo],
|
||||
['circ', processed_eases.circ],
|
||||
['back', processed_eases.back],
|
||||
['elastic', processed_eases.elastic],
|
||||
['bounce', processed_eases.bounce],
|
||||
]);
|
||||
|
||||
export const types = [
|
||||
['Ease In', 'In'],
|
||||
['Ease Out', 'Out'],
|
||||
['Ease In Out', 'InOut']
|
||||
];
|
||||
|
||||
export { sorted_eases as eases };
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Ease Visualiser"
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Easing"
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import ContactCard from './ContactCard.html';
|
||||
import ContactCard from './ContactCard.svelte';
|
||||
</script>
|
||||
|
||||
<ContactCard>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue