mirror of
https://github.com/LukeHagar/website.git
synced 2025-12-06 04:22:07 +00:00
prettier updates
This commit is contained in:
@@ -1,30 +1,30 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
extends: [
|
extends: [
|
||||||
'eslint:recommended',
|
'eslint:recommended',
|
||||||
'plugin:@typescript-eslint/recommended',
|
'plugin:@typescript-eslint/recommended',
|
||||||
'plugin:svelte/recommended',
|
'plugin:svelte/recommended',
|
||||||
'prettier'
|
'prettier'
|
||||||
],
|
],
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
plugins: ['@typescript-eslint'],
|
plugins: ['@typescript-eslint'],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
ecmaVersion: 2020,
|
ecmaVersion: 2020,
|
||||||
extraFileExtensions: ['.svelte']
|
extraFileExtensions: ['.svelte']
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
es2017: true,
|
es2017: true,
|
||||||
node: true
|
node: true
|
||||||
},
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: ['*.svelte'],
|
files: ['*.svelte'],
|
||||||
parser: 'svelte-eslint-parser',
|
parser: 'svelte-eslint-parser',
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: '@typescript-eslint/parser'
|
parser: '@typescript-eslint/parser'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
36
.github/workflows/index.yml
vendored
36
.github/workflows/index.yml
vendored
@@ -1,23 +1,23 @@
|
|||||||
name: Search Index
|
name: Search Index
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
indexing:
|
indexing:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: Indexing
|
name: Indexing
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: 'meilisearch/scrapix'
|
repository: 'meilisearch/scrapix'
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '20.x'
|
node-version: '20.x'
|
||||||
- run: yarn
|
- run: yarn
|
||||||
- run: yarn start -c "$SCRAPIX_CONFIG"
|
- run: yarn start -c "$SCRAPIX_CONFIG"
|
||||||
env:
|
env:
|
||||||
SCRAPIX_CONFIG: ${{ secrets.SCRAPIX_CONFIG }}
|
SCRAPIX_CONFIG: ${{ secrets.SCRAPIX_CONFIG }}
|
||||||
|
|||||||
34
.github/workflows/stale.yml
vendored
34
.github/workflows/stale.yml
vendored
@@ -1,23 +1,23 @@
|
|||||||
name: Mark stale issues
|
name: Mark stale issues
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 0 * * *" # Midnight Runtime
|
- cron: '0 0 * * *' # Midnight Runtime
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v9
|
- uses: actions/stale@v9
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
stale-issue-message: "This issue has been labeled as a 'question', indicating that it requires additional information from the requestor. It has been inactive for 7 days. If no further activity occurs, this issue will be closed in 14 days."
|
stale-issue-message: "This issue has been labeled as a 'question', indicating that it requires additional information from the requestor. It has been inactive for 7 days. If no further activity occurs, this issue will be closed in 14 days."
|
||||||
stale-issue-label: "stale"
|
stale-issue-label: 'stale'
|
||||||
days-before-stale: 7
|
days-before-stale: 7
|
||||||
days-before-close: 14
|
days-before-close: 14
|
||||||
remove-stale-when-updated: true
|
remove-stale-when-updated: true
|
||||||
close-issue-message: "This issue has been closed due to inactivity. If you still require assistance, please provide the requested information."
|
close-issue-message: 'This issue has been closed due to inactivity. If you still require assistance, please provide the requested information.'
|
||||||
close-issue-reason: "not_planned"
|
close-issue-reason: 'not_planned'
|
||||||
operations-per-run: 100
|
operations-per-run: 100
|
||||||
only-labels: "question"
|
only-labels: 'question'
|
||||||
|
|||||||
@@ -5,7 +5,5 @@
|
|||||||
# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart
|
# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- init: pnpm install && pnpm run build
|
- init: pnpm install && pnpm run build
|
||||||
command: pnpm run dev
|
command: pnpm run dev
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
30
CONTENT.md
30
CONTENT.md
@@ -49,9 +49,9 @@ Create ordered (numbered) and unordered (bulleted) lists using 1., \*, or -.
|
|||||||
**Unordered List**:
|
**Unordered List**:
|
||||||
|
|
||||||
```md
|
```md
|
||||||
- Apple
|
- Apple
|
||||||
- Banana
|
- Banana
|
||||||
- Cherry
|
- Cherry
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Links
|
#### Links
|
||||||
@@ -129,15 +129,20 @@ Alternatively, use markdoc tables.
|
|||||||
|
|
||||||
```md
|
```md
|
||||||
{% table %}
|
{% table %}
|
||||||
* Heading 1
|
|
||||||
* Heading 2
|
- Heading 1
|
||||||
|
- Heading 2
|
||||||
|
|
||||||
---
|
---
|
||||||
* Row 1 Cell 1
|
|
||||||
* Row 1 Cell 2
|
- Row 1 Cell 1
|
||||||
|
- Row 1 Cell 2
|
||||||
|
|
||||||
---
|
---
|
||||||
* Row 2 Cell 1
|
|
||||||
* Row 2 cell 2
|
- Row 2 Cell 1
|
||||||
{% /table %}
|
- Row 2 cell 2
|
||||||
|
{% /table %}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Block Quotes
|
#### Block Quotes
|
||||||
@@ -186,7 +191,9 @@ print('test');
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
#### Sections
|
#### Sections
|
||||||
|
|
||||||
Use sections when there is a clear step-by-step format to a page. This is used mainly in journey pages and tutorials.
|
Use sections when there is a clear step-by-step format to a page. This is used mainly in journey pages and tutorials.
|
||||||
|
|
||||||
```md
|
```md
|
||||||
{% section #featured-products-1 step=1 title="Title" %}
|
{% section #featured-products-1 step=1 title="Title" %}
|
||||||
Lorem ipsum dolor sit amet consectetur.
|
Lorem ipsum dolor sit amet consectetur.
|
||||||
@@ -243,6 +250,7 @@ Available sizes are `s`, `m`, `l` and `xl`. Default: `s`.
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Cards
|
#### Cards
|
||||||
|
|
||||||
We use cards when we reference a list of links for navigation
|
We use cards when we reference a list of links for navigation
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -268,6 +276,7 @@ Get started with Appwrite and SvelteKit
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Cards with icons
|
#### Cards with icons
|
||||||
|
|
||||||
We use cards when we reference a list of links for navigation, this variation has icons for extra hints visually.
|
We use cards when we reference a list of links for navigation, this variation has icons for extra hints visually.
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -285,6 +294,7 @@ Configure FCM for push notification to Android and Apple devices.
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Accordions
|
#### Accordions
|
||||||
|
|
||||||
Use accordions to reduce page size and collapse information that's not important when a reader is skilling the page.
|
Use accordions to reduce page size and collapse information that's not important when a reader is skilling the page.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -60,11 +60,11 @@ doc-548-submit-a-pull-request-section-to-contribution-guide
|
|||||||
|
|
||||||
When `TYPE` can be:
|
When `TYPE` can be:
|
||||||
|
|
||||||
- **feat** - is a new feature
|
- **feat** - is a new feature
|
||||||
- **doc** - documentation only changes
|
- **doc** - documentation only changes
|
||||||
- **cicd** - changes related to CI/CD system
|
- **cicd** - changes related to CI/CD system
|
||||||
- **fix** - a bug fix
|
- **fix** - a bug fix
|
||||||
- **refactor** - code change that neither fixes a bug nor adds a feature
|
- **refactor** - code change that neither fixes a bug nor adds a feature
|
||||||
|
|
||||||
**All PRs must include a commit message with a description of the changes made!**
|
**All PRs must include a commit message with a description of the changes made!**
|
||||||
|
|
||||||
|
|||||||
200
STYLE.md
200
STYLE.md
@@ -6,17 +6,17 @@ Read this document carefully before making PRs to the Appwrite Website repo.
|
|||||||
|
|
||||||
The Appwrite documentation is meant to provide general guidance that's:
|
The Appwrite documentation is meant to provide general guidance that's:
|
||||||
|
|
||||||
- Unopinionated
|
- Unopinionated
|
||||||
- Focused on the correct use of Appwrite product
|
- Focused on the correct use of Appwrite product
|
||||||
- Includes examples for all relevant and applicable SDKs
|
- Includes examples for all relevant and applicable SDKs
|
||||||
- Agnostic to the user's implementation and stack.
|
- Agnostic to the user's implementation and stack.
|
||||||
|
|
||||||
Examples of things not fit for docs, and better as a blog or video:
|
Examples of things not fit for docs, and better as a blog or video:
|
||||||
|
|
||||||
- General programming advice
|
- General programming advice
|
||||||
- Opinionated implementation patterns like MVVM, factory methods, etc.
|
- Opinionated implementation patterns like MVVM, factory methods, etc.
|
||||||
- Examples that only include a select subset of Appwrite SDKs.
|
- Examples that only include a select subset of Appwrite SDKs.
|
||||||
- Examples that do not work for all developers using Appwrite, but specific to Appwrite + technology.
|
- Examples that do not work for all developers using Appwrite, but specific to Appwrite + technology.
|
||||||
|
|
||||||
Note that the tutorials and blogs available on the Appwrite blog and docs are meant for these types of information.
|
Note that the tutorials and blogs available on the Appwrite blog and docs are meant for these types of information.
|
||||||
|
|
||||||
@@ -28,39 +28,39 @@ Appwrite's navigation increases in complexity from top down. We expect users to
|
|||||||
|
|
||||||
Introduction Section:
|
Introduction Section:
|
||||||
|
|
||||||
- [Homes](https://appwrite.io/docs)
|
- [Homes](https://appwrite.io/docs)
|
||||||
- [Quick start](https://appwrite.io/docs/quick-start)
|
- [Quick start](https://appwrite.io/docs/quick-start)
|
||||||
- [Tutorial](https://appwrite.io/docs/tutorial)
|
- [Tutorial](https://appwrite.io/docs/tutorial)
|
||||||
- [SDKs](https://appwrite.io/docs/sdks)
|
- [SDKs](https://appwrite.io/docs/sdks)
|
||||||
- [API references](https://appwrite.io/docs/references)
|
- [API references](https://appwrite.io/docs/references)
|
||||||
|
|
||||||
Products section:
|
Products section:
|
||||||
|
|
||||||
- [Auth](https://appwrite.io/docs/products/auth)
|
- [Auth](https://appwrite.io/docs/products/auth)
|
||||||
- [Databases](https://appwrite.io/docs/products/databases)
|
- [Databases](https://appwrite.io/docs/products/databases)
|
||||||
- [Functions](https://appwrite.io/docs/products/functions)
|
- [Functions](https://appwrite.io/docs/products/functions)
|
||||||
- [Storage](https://appwrite.io/docs/products/storage)
|
- [Storage](https://appwrite.io/docs/products/storage)
|
||||||
- [Messaging](https://appwrite.io/docs/products/messaging)
|
- [Messaging](https://appwrite.io/docs/products/messaging)
|
||||||
- [AI](https://appwrite.io/docs/products/ai)
|
- [AI](https://appwrite.io/docs/products/ai)
|
||||||
|
|
||||||
APIs section:
|
APIs section:
|
||||||
|
|
||||||
- [GraphQL](https://appwrite.io/docs/apis/graphql)
|
- [GraphQL](https://appwrite.io/docs/apis/graphql)
|
||||||
- [REST](https://appwrite.io/docs/apis/rest)
|
- [REST](https://appwrite.io/docs/apis/rest)
|
||||||
- [Realtime](https://appwrite.io/docs/apis/realtime)
|
- [Realtime](https://appwrite.io/docs/apis/realtime)
|
||||||
|
|
||||||
Tooling section:
|
Tooling section:
|
||||||
|
|
||||||
- [Command Line](https://appwrite.io/docs/command-line)
|
- [Command Line](https://appwrite.io/docs/command-line)
|
||||||
- [Command center](https://appwrite.io/docs/tooling/command-center)
|
- [Command center](https://appwrite.io/docs/tooling/command-center)
|
||||||
- [Assistant](https://appwrite.io/docs/tooling/assistant)
|
- [Assistant](https://appwrite.io/docs/tooling/assistant)
|
||||||
|
|
||||||
Advanced section:
|
Advanced section:
|
||||||
|
|
||||||
- [Platform](https://appwrite.io/docs/advanced/platform)
|
- [Platform](https://appwrite.io/docs/advanced/platform)
|
||||||
- [Migrations](https://appwrite.io/docs/advanced/migrations)
|
- [Migrations](https://appwrite.io/docs/advanced/migrations)
|
||||||
- [Self-hosting](https://appwrite.io/docs/advanced/self-hosting)
|
- [Self-hosting](https://appwrite.io/docs/advanced/self-hosting)
|
||||||
- [Security](https://appwrite.io/docs/advanced/security)
|
- [Security](https://appwrite.io/docs/advanced/security)
|
||||||
|
|
||||||
Here's the intended purpose and structure of each section.
|
Here's the intended purpose and structure of each section.
|
||||||
|
|
||||||
@@ -70,10 +70,10 @@ This section is focused on introducing what Appwrite is and giving examples to t
|
|||||||
Documentation here is focused on a **single flow** which means a single platform/framework + Appwrite.
|
Documentation here is focused on a **single flow** which means a single platform/framework + Appwrite.
|
||||||
Content here is not specific to a specific product, but usually covers multiple Appwrite products.
|
Content here is not specific to a specific product, but usually covers multiple Appwrite products.
|
||||||
|
|
||||||
- If your tutorial can be followed in about 15 minutes and fits on one page, write it under quick start
|
- If your tutorial can be followed in about 15 minutes and fits on one page, write it under quick start
|
||||||
- If you're writing a long piece of documentation that integrates Appwrite with another technology, with lots of details that's opinionated or isn't relevant for all use cases, write it under tutorial. This is similar to "cook book" at other organizations.
|
- If you're writing a long piece of documentation that integrates Appwrite with another technology, with lots of details that's opinionated or isn't relevant for all use cases, write it under tutorial. This is similar to "cook book" at other organizations.
|
||||||
- If you have information like helpers and methods that are only on SDKs but not the API, they go under SDK
|
- If you have information like helpers and methods that are only on SDKs but not the API, they go under SDK
|
||||||
- API references are generated from source from the appwrite/appwrite repo
|
- API references are generated from source from the appwrite/appwrite repo
|
||||||
|
|
||||||
### Products
|
### Products
|
||||||
|
|
||||||
@@ -82,17 +82,17 @@ Code examples should cover **all available SDKs**.
|
|||||||
|
|
||||||
Each product page has three main sections
|
Each product page has three main sections
|
||||||
|
|
||||||
- Introduction
|
- Introduction
|
||||||
- Overview - Describes at a high level, why you might need this product
|
- Overview - Describes at a high level, why you might need this product
|
||||||
- Quick start - Shows the most basic and quickest example to make something happen with a product. Keep it really short.
|
- Quick start - Shows the most basic and quickest example to make something happen with a product. Keep it really short.
|
||||||
- Concept
|
- Concept
|
||||||
- These pages usually align with sections shown in the product in the Appwrite Console.
|
- These pages usually align with sections shown in the product in the Appwrite Console.
|
||||||
- Focused on describing concepts a user should know, but not actions you might take.
|
- Focused on describing concepts a user should know, but not actions you might take.
|
||||||
- Cover all the details
|
- Cover all the details
|
||||||
- Journeys
|
- Journeys
|
||||||
- These pages focus on common actions and work flows
|
- These pages focus on common actions and work flows
|
||||||
- Detailed examples that span many concepts
|
- Detailed examples that span many concepts
|
||||||
- Like cookbook at other organizations' documentation.
|
- Like cookbook at other organizations' documentation.
|
||||||
|
|
||||||
### APIs section
|
### APIs section
|
||||||
|
|
||||||
@@ -106,10 +106,10 @@ Describes tools that help you work with Appwrite, but are usually non-essential
|
|||||||
|
|
||||||
For information that's not used commonly during the development cycle.
|
For information that's not used commonly during the development cycle.
|
||||||
|
|
||||||
- Platform: covers concepts that apply to the entire Appwrite Cloud platform, like API keys, rate limits, etc.
|
- Platform: covers concepts that apply to the entire Appwrite Cloud platform, like API keys, rate limits, etc.
|
||||||
- Migrations: covers migrations feature of Appwrite that helps you move data around.
|
- Migrations: covers migrations feature of Appwrite that helps you move data around.
|
||||||
- Security: purely information about measures Appwrite use to ensure security of the platform and data.
|
- Security: purely information about measures Appwrite use to ensure security of the platform and data.
|
||||||
- Self-hosting: The Appwrite self-hosted platform is meant to behave identically to Cloud after being configured corrrectly. This section focuses on how to configure Appwrite self-hosted such that it behaves like Cloud.
|
- Self-hosting: The Appwrite self-hosted platform is meant to behave identically to Cloud after being configured corrrectly. This section focuses on how to configure Appwrite self-hosted such that it behaves like Cloud.
|
||||||
|
|
||||||
## Documentation sources
|
## Documentation sources
|
||||||
|
|
||||||
@@ -117,22 +117,22 @@ The Appwrite docs are compiled from different repositories. Here are the signifi
|
|||||||
|
|
||||||
[appwrite/website](https://github.com/appwrite/website):
|
[appwrite/website](https://github.com/appwrite/website):
|
||||||
|
|
||||||
- Tutorials
|
- Tutorials
|
||||||
- Quick starts
|
- Quick starts
|
||||||
- Product, API, Tooling and Advanced sections
|
- Product, API, Tooling and Advanced sections
|
||||||
|
|
||||||
[appwrite/appwrite](https://github.com/appwrite/appwrite):
|
[appwrite/appwrite](https://github.com/appwrite/appwrite):
|
||||||
|
|
||||||
- [API Reference](https://appwrite.io/docs/references) pages
|
- [API Reference](https://appwrite.io/docs/references) pages
|
||||||
- API specification
|
- API specification
|
||||||
- API description
|
- API description
|
||||||
- API endpoint description
|
- API endpoint description
|
||||||
- API request parameters
|
- API request parameters
|
||||||
- API response model
|
- API response model
|
||||||
|
|
||||||
[appwrite/sdk-generator](https://github.com/appwrite/sdk-generator):
|
[appwrite/sdk-generator](https://github.com/appwrite/sdk-generator):
|
||||||
|
|
||||||
- Generated examples
|
- Generated examples
|
||||||
|
|
||||||
## Markdown Style guidelines
|
## Markdown Style guidelines
|
||||||
|
|
||||||
@@ -141,10 +141,10 @@ the tone and voice remains consistent.
|
|||||||
|
|
||||||
### Headings
|
### Headings
|
||||||
|
|
||||||
- All titles, headings, buttons, and labels should be written in **sentence case**. If you're not sure what sentence case should look like, check [APA's style guide](https://apastyle.apa.org/style-grammar-guidelines/capitalization/sentence-case) or check with ChatGPT and other LLMs which reliably converts titles to sentence case.
|
- All titles, headings, buttons, and labels should be written in **sentence case**. If you're not sure what sentence case should look like, check [APA's style guide](https://apastyle.apa.org/style-grammar-guidelines/capitalization/sentence-case) or check with ChatGPT and other LLMs which reliably converts titles to sentence case.
|
||||||
- All headings in a docs page begin with `# Heading` then `## Heading` and `### Heading`. Internally, they're converted to H2 to H4 tags.
|
- All headings in a docs page begin with `# Heading` then `## Heading` and `### Heading`. Internally, they're converted to H2 to H4 tags.
|
||||||
- All headings should have an ID label, for example `# Cool heading {% #cool-heading %}` the `#cool-heading` ID will be used to generate the table of contents and add links to the heading.
|
- All headings should have an ID label, for example `# Cool heading {% #cool-heading %}` the `#cool-heading` ID will be used to generate the table of contents and add links to the heading.
|
||||||
- Prefer verbs over gerunds, for example, say "Create documents" not "Creating documents".
|
- Prefer verbs over gerunds, for example, say "Create documents" not "Creating documents".
|
||||||
|
|
||||||
### Extended Markdoc components
|
### Extended Markdoc components
|
||||||
|
|
||||||
@@ -152,14 +152,14 @@ Appwrite's documentation uses extended markdown syntax. You can find all of the
|
|||||||
|
|
||||||
### Screenshots
|
### Screenshots
|
||||||
|
|
||||||
- When contributing upload original screenshots. The Appwrite design team will edit the screenshot to be consistent with other screenshots in the docs.
|
- When contributing upload original screenshots. The Appwrite design team will edit the screenshot to be consistent with other screenshots in the docs.
|
||||||
- Screenshots must be 16:9
|
- Screenshots must be 16:9
|
||||||
- Screnshots should be taken in a 1400 x 900 view port on 3x DPR in browser developer tools.
|
- Screnshots should be taken in a 1400 x 900 view port on 3x DPR in browser developer tools.
|
||||||
- Use generic and sensible organization, project, and resource names. Avoid names like `test`, `demo`, or `sdlkfj`.
|
- Use generic and sensible organization, project, and resource names. Avoid names like `test`, `demo`, or `sdlkfj`.
|
||||||
- All screenshot should be take from a user named Walter O'Brien. You can change the name of your current user by going to your Appwrite Console and clicking the **top right profile icon** > **Your Account** > **Name**.
|
- All screenshot should be take from a user named Walter O'Brien. You can change the name of your current user by going to your Appwrite Console and clicking the **top right profile icon** > **Your Account** > **Name**.
|
||||||
- Screenshots are stored in the `/images/docs/` folder, in a parent folder that is consistent with the path of the docs that reference the image.
|
- Screenshots are stored in the `/images/docs/` folder, in a parent folder that is consistent with the path of the docs that reference the image.
|
||||||
- All screenshots must be both dark and light mode, with `/path/` holding the lightmode version and `/path/dark/` holding the dark mode version.
|
- All screenshots must be both dark and light mode, with `/path/` holding the lightmode version and `/path/dark/` holding the dark mode version.
|
||||||
- Screenshots should be uploaded as un-edited original. Request help from the Appwrite design team to help you edit and refine your photos according to our guidelines.
|
- Screenshots should be uploaded as un-edited original. Request help from the Appwrite design team to help you edit and refine your photos according to our guidelines.
|
||||||
|
|
||||||
```md
|
```md
|
||||||
{% only_dark %}
|
{% only_dark %}
|
||||||
@@ -180,17 +180,23 @@ It should contain all the pages and headings with in them, maintainers may reque
|
|||||||
|
|
||||||
```md
|
```md
|
||||||
# page 1
|
# page 1
|
||||||
|
|
||||||
## heading a
|
## heading a
|
||||||
## heading b
|
## heading b
|
||||||
...
|
...
|
||||||
|
|
||||||
# page 2
|
# page 2
|
||||||
|
|
||||||
## heading a
|
## heading a
|
||||||
## heading b
|
## heading b
|
||||||
...
|
...
|
||||||
|
|
||||||
# page 3
|
# page 3
|
||||||
|
|
||||||
## heading a
|
## heading a
|
||||||
## heading b
|
## heading b
|
||||||
...
|
...
|
||||||
|
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -204,41 +210,41 @@ Split content such that each piece makes sense without reading dependents or exp
|
|||||||
|
|
||||||
### Release prep
|
### Release prep
|
||||||
|
|
||||||
- [ ] Add new version to [src/lib/utils/references.ts](src/lib/utils/references.ts)
|
- [ ] Add new version to [src/lib/utils/references.ts](src/lib/utils/references.ts)
|
||||||
- [ ] Point Cloud to new version in [src/routes/docs/references/[version]/[platform]/[service]/+page.server.ts](src/routes/docs/references/[version]/[platform]/[service]/+page.server.ts)
|
- [ ] Point Cloud to new version in [src/routes/docs/references/[version]/[platform]/[service]/+page.server.ts](src/routes/docs/references/[version]/[platform]/[service]/+page.server.ts)
|
||||||
- [ ] Update install command in [/workspaces/website/src/routes/docs/advanced/self-hosting/+page.markdoc](/workspaces/website/src/routes/docs/advanced/self-hosting/+page.markdoc)
|
- [ ] Update install command in [/workspaces/website/src/routes/docs/advanced/self-hosting/+page.markdoc](/workspaces/website/src/routes/docs/advanced/self-hosting/+page.markdoc)
|
||||||
- [ ] Update events [src/partials/[product]-events.md](src/partials/)
|
- [ ] Update events [src/partials/[product]-events.md](src/partials/)
|
||||||
- [ ] Update response code [src/routes/docs/advanced/platform/response-codes/+page.markdoc](src/routes/docs/advanced/platform/response-codes/+page.markdoc)
|
- [ ] Update response code [src/routes/docs/advanced/platform/response-codes/+page.markdoc](src/routes/docs/advanced/platform/response-codes/+page.markdoc)
|
||||||
- [ ] Bump latest SDK versions in SDKs page, quick start, and tutorials
|
- [ ] Bump latest SDK versions in SDKs page, quick start, and tutorials
|
||||||
- [ ] Create new sections for new products
|
- [ ] Create new sections for new products
|
||||||
- [ ] Create new concept and journey pages for new features
|
- [ ] Create new concept and journey pages for new features
|
||||||
- [ ] Update docs for breaking changes
|
- [ ] Update docs for breaking changes
|
||||||
|
|
||||||
### Documenting a new API
|
### Documenting a new API
|
||||||
|
|
||||||
- Add a new .md file describing the new API here: <https://github.com/appwrite/appwrite/tree/main/docs/references>
|
- Add a new .md file describing the new API here: <https://github.com/appwrite/appwrite/tree/main/docs/references>
|
||||||
- Add descriptions for methods and parameters in the controller code: <https://github.com/appwrite/appwrite/tree/main/app/controllers/api>
|
- Add descriptions for methods and parameters in the controller code: <https://github.com/appwrite/appwrite/tree/main/app/controllers/api>
|
||||||
- Check new response models have meaningful descriptions
|
- Check new response models have meaningful descriptions
|
||||||
|
|
||||||
### Adding a new quickstart
|
### Adding a new quickstart
|
||||||
|
|
||||||
- Copy a quick start from the [src/routes/docs/quick-starts](src/routes/docs/quick-starts) folder.
|
- Copy a quick start from the [src/routes/docs/quick-starts](src/routes/docs/quick-starts) folder.
|
||||||
- Add a new entry and logo to [src/routes/docs/quick-starts/+page.svelte](src/routes/docs/quick-starts/+page.svelte)
|
- Add a new entry and logo to [src/routes/docs/quick-starts/+page.svelte](src/routes/docs/quick-starts/+page.svelte)
|
||||||
- If you need a new logo, contact the Appwrite team to add one to Pink design.
|
- If you need a new logo, contact the Appwrite team to add one to Pink design.
|
||||||
- Update the content of your tutorial. Remember to update the front matter!
|
- Update the content of your tutorial. Remember to update the front matter!
|
||||||
- Try to be consistent in both the quickstart's content and format when compared to existing quick starts
|
- Try to be consistent in both the quickstart's content and format when compared to existing quick starts
|
||||||
- Add the quick start to the footer and front page of Appwrite
|
- Add the quick start to the footer and front page of Appwrite
|
||||||
- Use sections for steps on your page
|
- Use sections for steps on your page
|
||||||
|
|
||||||
### Adding a new tutorial
|
### Adding a new tutorial
|
||||||
|
|
||||||
- Copy a tutorial from the [src/routes/docs/tutorials](src/routes/docs/tutorials) folder.
|
- Copy a tutorial from the [src/routes/docs/tutorials](src/routes/docs/tutorials) folder.
|
||||||
- Update the `+page.ts`'s redirect, for example, the Android tutorial has this: [src/routes/docs/tutorials/android/+page.ts](src/routes/docs/tutorials/android/+page.ts)
|
- Update the `+page.ts`'s redirect, for example, the Android tutorial has this: [src/routes/docs/tutorials/android/+page.ts](src/routes/docs/tutorials/android/+page.ts)
|
||||||
- Update [src/routes/docs/tutorials/+page.svelte](src/routes/docs/tutorials/+page.svelte) and add your new tutorial
|
- Update [src/routes/docs/tutorials/+page.svelte](src/routes/docs/tutorials/+page.svelte) and add your new tutorial
|
||||||
- Update [src/routes/docs/tutorials/android/+layout.ts](src/routes/docs/tutorials/android/+layout.ts) and add your new tutorial
|
- Update [src/routes/docs/tutorials/android/+layout.ts](src/routes/docs/tutorials/android/+layout.ts) and add your new tutorial
|
||||||
- Add the content of your tutorial. Keep pages short, separated by a different distinct feature for each step.
|
- Add the content of your tutorial. Keep pages short, separated by a different distinct feature for each step.
|
||||||
- If you need a new logo, contact the Appwrite team to add one to Pink design.
|
- If you need a new logo, contact the Appwrite team to add one to Pink design.
|
||||||
- Add the tutorial to the footer and front page of Appwrite
|
- Add the tutorial to the footer and front page of Appwrite
|
||||||
|
|
||||||
## Language and diction
|
## Language and diction
|
||||||
|
|
||||||
@@ -283,9 +289,11 @@ Like sentences, important information always comes first.
|
|||||||
This makes it easier to scan through the page.
|
This makes it easier to scan through the page.
|
||||||
|
|
||||||
✅ Clear, important information such as actions come first
|
✅ Clear, important information such as actions come first
|
||||||
|
|
||||||
> Store secrets as environment variables in vaults by navigating to **settings** > **security** > **vault**. Your secrets should never be shared. You must ensure data privacy, sharing secrets can compromise security during development.
|
> Store secrets as environment variables in vaults by navigating to **settings** > **security** > **vault**. Your secrets should never be shared. You must ensure data privacy, sharing secrets can compromise security during development.
|
||||||
|
|
||||||
❌ Unclear, important information is in the middle of the paragraph
|
❌ Unclear, important information is in the middle of the paragraph
|
||||||
|
|
||||||
> Security is important in development. That's why you should take care to protect secrets. Secrets should be safely stored as a environment variable in a vault. You can find vaults under **settings** > **security** > **vault**. Don't share this with anyone!
|
> Security is important in development. That's why you should take care to protect secrets. Secrets should be safely stored as a environment variable in a vault. You can find vaults under **settings** > **security** > **vault**. Don't share this with anyone!
|
||||||
|
|
||||||
If there are multiple important actions or pieces of information, **break up the paragraph**.
|
If there are multiple important actions or pieces of information, **break up the paragraph**.
|
||||||
|
|||||||
@@ -1,58 +1,58 @@
|
|||||||
services:
|
services:
|
||||||
traefik:
|
traefik:
|
||||||
image: traefik:2.9
|
image: traefik:2.9
|
||||||
command:
|
command:
|
||||||
- --log.level=DEBUG
|
- --log.level=DEBUG
|
||||||
- --api.insecure=true
|
- --api.insecure=true
|
||||||
- --providers.docker=true
|
- --providers.docker=true
|
||||||
- --providers.docker.exposedByDefault=false
|
- --providers.docker.exposedByDefault=false
|
||||||
- --entrypoints.web.address=:80
|
- --entrypoints.web.address=:80
|
||||||
- --entrypoints.websecure.address=:443
|
- --entrypoints.websecure.address=:443
|
||||||
- --providers.docker.constraints=Label(`traefik.constraint-label-stack`,`homepage`)
|
- --providers.docker.constraints=Label(`traefik.constraint-label-stack`,`homepage`)
|
||||||
- --accesslog=true
|
- --accesslog=true
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.traefik.middlewares=traefik-compress
|
- traefik.http.routers.traefik.middlewares=traefik-compress
|
||||||
- traefik.http.middlewares.traefik-compress.compress=true
|
- traefik.http.middlewares.traefik-compress.compress=true
|
||||||
ports:
|
ports:
|
||||||
- 80:80
|
- 80:80
|
||||||
- 8080:8080
|
- 8080:8080
|
||||||
volumes:
|
volumes:
|
||||||
# - /letsencrypt:/letsencrypt
|
# - /letsencrypt:/letsencrypt
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
networks:
|
networks:
|
||||||
- homepage
|
- homepage
|
||||||
|
|
||||||
homepage:
|
homepage:
|
||||||
image: homepage-dev
|
image: homepage-dev
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
args:
|
args:
|
||||||
- PUBLIC_APPWRITE_PROJECT_INIT_ID=$PUBLIC_APPWRITE_PROJECT_INIT_ID
|
- PUBLIC_APPWRITE_PROJECT_INIT_ID=$PUBLIC_APPWRITE_PROJECT_INIT_ID
|
||||||
- PUBLIC_APPWRITE_PROJECT_ID=$PUBLIC_APPWRITE_PROJECT_ID
|
- PUBLIC_APPWRITE_PROJECT_ID=$PUBLIC_APPWRITE_PROJECT_ID
|
||||||
- PUBLIC_APPWRITE_DB_MAIN_ID=$PUBLIC_APPWRITE_DB_MAIN_ID
|
- PUBLIC_APPWRITE_DB_MAIN_ID=$PUBLIC_APPWRITE_DB_MAIN_ID
|
||||||
- PUBLIC_APPWRITE_COL_THREADS_ID=$PUBLIC_APPWRITE_COL_THREADS_ID
|
- PUBLIC_APPWRITE_COL_THREADS_ID=$PUBLIC_APPWRITE_COL_THREADS_ID
|
||||||
- PUBLIC_APPWRITE_COL_MESSAGES_ID=$PUBLIC_APPWRITE_COL_MESSAGES_ID
|
- PUBLIC_APPWRITE_COL_MESSAGES_ID=$PUBLIC_APPWRITE_COL_MESSAGES_ID
|
||||||
- PUBLIC_APPWRITE_FN_TLDR_ID=$PUBLIC_APPWRITE_FN_TLDR_ID
|
- PUBLIC_APPWRITE_FN_TLDR_ID=$PUBLIC_APPWRITE_FN_TLDR_ID
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- homepage
|
- homepage
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.constraint-label-stack=homepage
|
- traefik.constraint-label-stack=homepage
|
||||||
- traefik.docker.network=appwrite
|
- traefik.docker.network=appwrite
|
||||||
- traefik.http.middlewares.appwrite_middlewares.compress=true
|
- traefik.http.middlewares.appwrite_middlewares.compress=true
|
||||||
- traefik.http.services.appwrite_service.loadbalancer.server.port=3000
|
- traefik.http.services.appwrite_service.loadbalancer.server.port=3000
|
||||||
#http
|
#http
|
||||||
- traefik.http.routers.appwrite.entrypoints=web
|
- traefik.http.routers.appwrite.entrypoints=web
|
||||||
- traefik.http.routers.appwrite.rule=PathPrefix(`/`)
|
- traefik.http.routers.appwrite.rule=PathPrefix(`/`)
|
||||||
- traefik.http.routers.appwrite.service=appwrite_service
|
- traefik.http.routers.appwrite.service=appwrite_service
|
||||||
- traefik.http.routers.appwrite.middlewares=appwrite_middlewares
|
- traefik.http.routers.appwrite.middlewares=appwrite_middlewares
|
||||||
# https
|
# https
|
||||||
- traefik.http.routers.appwrite_secure.entrypoints=websecure
|
- traefik.http.routers.appwrite_secure.entrypoints=websecure
|
||||||
- traefik.http.routers.appwrite_secure.rule=PathPrefix(`/`)
|
- traefik.http.routers.appwrite_secure.rule=PathPrefix(`/`)
|
||||||
- traefik.http.routers.appwrite_secure.service=appwrite_service
|
- traefik.http.routers.appwrite_secure.service=appwrite_service
|
||||||
- traefik.http.routers.appwrite_secure.tls=true
|
- traefik.http.routers.appwrite_secure.tls=true
|
||||||
- traefik.http.routers.appwrite_secure.middlewares=appwrite_middlewares
|
- traefik.http.routers.appwrite_secure.middlewares=appwrite_middlewares
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
homepage:
|
homepage:
|
||||||
|
|||||||
@@ -1,135 +1,135 @@
|
|||||||
x-logging: &x-logging
|
x-logging: &x-logging
|
||||||
logging:
|
logging:
|
||||||
driver: 'json-file'
|
driver: 'json-file'
|
||||||
options:
|
options:
|
||||||
max-file: '5'
|
max-file: '5'
|
||||||
max-size: '20m'
|
max-size: '20m'
|
||||||
|
|
||||||
x-update-config: &x-update-config
|
x-update-config: &x-update-config
|
||||||
update_config:
|
update_config:
|
||||||
order: stop-first
|
order: stop-first
|
||||||
failure_action: rollback
|
failure_action: rollback
|
||||||
parallelism: 1
|
parallelism: 1
|
||||||
delay: 10s
|
delay: 10s
|
||||||
rollback_config:
|
rollback_config:
|
||||||
failure_action: pause
|
failure_action: pause
|
||||||
monitor: 5s
|
monitor: 5s
|
||||||
parallelism: 2
|
parallelism: 2
|
||||||
order: stop-first
|
order: stop-first
|
||||||
|
|
||||||
version: '3.8'
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
traefik:
|
traefik:
|
||||||
image: traefik:2.9
|
image: traefik:2.9
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
command:
|
command:
|
||||||
- --log.level=DEBUG
|
- --log.level=DEBUG
|
||||||
- --api.insecure=false
|
- --api.insecure=false
|
||||||
- --providers.docker=true
|
- --providers.docker=true
|
||||||
- --providers.docker.watch=true
|
- --providers.docker.watch=true
|
||||||
- --providers.docker.swarmMode=true
|
- --providers.docker.swarmMode=true
|
||||||
- --providers.docker.exposedByDefault=false
|
- --providers.docker.exposedByDefault=false
|
||||||
- --entrypoints.web.address=:80
|
- --entrypoints.web.address=:80
|
||||||
- --entrypoints.websecure.address=:443
|
- --entrypoints.websecure.address=:443
|
||||||
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
||||||
- --entrypoints.web.http.redirections.entrypoint.scheme=https
|
- --entrypoints.web.http.redirections.entrypoint.scheme=https
|
||||||
- --providers.docker.constraints=Label(`traefik.constraint-label-stack`,`appwrite`)
|
- --providers.docker.constraints=Label(`traefik.constraint-label-stack`,`appwrite`)
|
||||||
- --certificatesresolvers.myresolver.acme.httpchallenge=true
|
- --certificatesresolvers.myresolver.acme.httpchallenge=true
|
||||||
- --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
|
- --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
|
||||||
- --certificatesresolvers.myresolver.acme.email=$_APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
- --certificatesresolvers.myresolver.acme.email=$_APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||||
- --certificatesresolvers.myresolver.acme.storage=/letsencrypt/${_APP_DOMAIN}.json
|
- --certificatesresolvers.myresolver.acme.storage=/letsencrypt/${_APP_DOMAIN}.json
|
||||||
- --accesslog=true
|
- --accesslog=true
|
||||||
ports:
|
ports:
|
||||||
- 80:80
|
- 80:80
|
||||||
- 443:443
|
- 443:443
|
||||||
volumes:
|
volumes:
|
||||||
- /letsencrypt:/letsencrypt
|
- /letsencrypt:/letsencrypt
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
networks:
|
networks:
|
||||||
- cloud
|
- cloud
|
||||||
deploy:
|
deploy:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
<<: *x-update-config
|
<<: *x-update-config
|
||||||
placement:
|
placement:
|
||||||
max_replicas_per_node: 1
|
max_replicas_per_node: 1
|
||||||
constraints:
|
constraints:
|
||||||
- node.role == manager
|
- node.role == manager
|
||||||
preferences:
|
preferences:
|
||||||
- spread: node.role == worker
|
- spread: node.role == worker
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.traefik.middlewares=traefik-compress
|
- traefik.http.routers.traefik.middlewares=traefik-compress
|
||||||
- traefik.http.middlewares.traefik-compress.compress=true
|
- traefik.http.middlewares.traefik-compress.compress=true
|
||||||
|
|
||||||
server:
|
server:
|
||||||
image: ghcr.io/appwrite/website:$_APP_VERSION
|
image: ghcr.io/appwrite/website:$_APP_VERSION
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
networks:
|
networks:
|
||||||
- cloud
|
- cloud
|
||||||
environment:
|
environment:
|
||||||
- PUBLIC_APPWRITE_PROJECT_INIT_ID
|
- PUBLIC_APPWRITE_PROJECT_INIT_ID
|
||||||
- PUBLIC_APPWRITE_PROJECT_ID
|
- PUBLIC_APPWRITE_PROJECT_ID
|
||||||
- PUBLIC_APPWRITE_DB_MAIN_ID
|
- PUBLIC_APPWRITE_DB_MAIN_ID
|
||||||
- PUBLIC_APPWRITE_COL_THREADS_ID
|
- PUBLIC_APPWRITE_COL_THREADS_ID
|
||||||
- PUBLIC_APPWRITE_COL_MESSAGES_ID
|
- PUBLIC_APPWRITE_COL_MESSAGES_ID
|
||||||
- PUBLIC_APPWRITE_FN_TLDR_ID
|
- PUBLIC_APPWRITE_FN_TLDR_ID
|
||||||
deploy:
|
deploy:
|
||||||
<<: *x-update-config
|
<<: *x-update-config
|
||||||
mode: replicated
|
mode: replicated
|
||||||
replicas: 8
|
replicas: 8
|
||||||
placement:
|
placement:
|
||||||
max_replicas_per_node: 2
|
max_replicas_per_node: 2
|
||||||
constraints:
|
constraints:
|
||||||
- node.role == worker
|
- node.role == worker
|
||||||
preferences:
|
preferences:
|
||||||
- spread: node.role == worker
|
- spread: node.role == worker
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.docker.lbswarm=true
|
- traefik.docker.lbswarm=true
|
||||||
- traefik.constraint-label-stack=appwrite
|
- traefik.constraint-label-stack=appwrite
|
||||||
- traefik.http.services.appwrite_service.loadbalancer.server.port=3000
|
- traefik.http.services.appwrite_service.loadbalancer.server.port=3000
|
||||||
- traefik.http.middlewares.appwrite_middlewares.compress=true
|
- traefik.http.middlewares.appwrite_middlewares.compress=true
|
||||||
#http
|
#http
|
||||||
- traefik.http.routers.appwrite.entrypoints=web
|
- traefik.http.routers.appwrite.entrypoints=web
|
||||||
- traefik.http.routers.appwrite.rule=Host(`$_APP_DOMAIN`) || Host(`www.$_APP_DOMAIN`)
|
- traefik.http.routers.appwrite.rule=Host(`$_APP_DOMAIN`) || Host(`www.$_APP_DOMAIN`)
|
||||||
- traefik.http.routers.appwrite.service=appwrite_service
|
- traefik.http.routers.appwrite.service=appwrite_service
|
||||||
- traefik.http.routers.appwrite.middlewares=appwrite_middlewares
|
- traefik.http.routers.appwrite.middlewares=appwrite_middlewares
|
||||||
# https
|
# https
|
||||||
- traefik.http.routers.appwrite_secure.entrypoints=websecure
|
- traefik.http.routers.appwrite_secure.entrypoints=websecure
|
||||||
- traefik.http.routers.appwrite_secure.rule=Host(`$_APP_DOMAIN`) || Host(`www.$_APP_DOMAIN`)
|
- traefik.http.routers.appwrite_secure.rule=Host(`$_APP_DOMAIN`) || Host(`www.$_APP_DOMAIN`)
|
||||||
- traefik.http.routers.appwrite_secure.service=appwrite_service
|
- traefik.http.routers.appwrite_secure.service=appwrite_service
|
||||||
- traefik.http.routers.appwrite_secure.tls=true
|
- traefik.http.routers.appwrite_secure.tls=true
|
||||||
- traefik.http.routers.appwrite_secure.tls.certresolver=myresolver
|
- traefik.http.routers.appwrite_secure.tls.certresolver=myresolver
|
||||||
- traefik.http.routers.appwrite_secure.middlewares=appwrite_middlewares
|
- traefik.http.routers.appwrite_secure.middlewares=appwrite_middlewares
|
||||||
|
|
||||||
janitor:
|
janitor:
|
||||||
image: appwrite/docker-janitor
|
image: appwrite/docker-janitor
|
||||||
deploy:
|
deploy:
|
||||||
mode: global
|
mode: global
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
environment:
|
environment:
|
||||||
- TIME_BETWEEN_RUNS=3600
|
- TIME_BETWEEN_RUNS=3600
|
||||||
- UNUSED_TIME=6h
|
- UNUSED_TIME=6h
|
||||||
|
|
||||||
sematext-agent:
|
sematext-agent:
|
||||||
image: sematext/agent:latest
|
image: sematext/agent:latest
|
||||||
environment:
|
environment:
|
||||||
REGION: EU
|
REGION: EU
|
||||||
INFRA_TOKEN: $SEMATEXT_TOKEN
|
INFRA_TOKEN: $SEMATEXT_TOKEN
|
||||||
deploy:
|
deploy:
|
||||||
mode: global
|
mode: global
|
||||||
restart_policy:
|
restart_policy:
|
||||||
condition: any
|
condition: any
|
||||||
volumes:
|
volumes:
|
||||||
- /:/hostfs:ro
|
- /:/hostfs:ro
|
||||||
- /etc/passwd:/etc/passwd:ro
|
- /etc/passwd:/etc/passwd:ro
|
||||||
- /etc/group:/etc/group:ro
|
- /etc/group:/etc/group:ro
|
||||||
- /sys:/host/sys:ro
|
- /sys:/host/sys:ro
|
||||||
- /dev:/hostfs/dev:ro
|
- /dev:/hostfs/dev:ro
|
||||||
- /var/run:/var/run
|
- /var/run:/var/run
|
||||||
- /sys/kernel/debug:/sys/kernel/debug
|
- /sys/kernel/debug:/sys/kernel/debug
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
cloud:
|
cloud:
|
||||||
driver: overlay
|
driver: overlay
|
||||||
|
|||||||
250
docker/stage.yml
250
docker/stage.yml
@@ -1,137 +1,137 @@
|
|||||||
x-logging: &x-logging
|
x-logging: &x-logging
|
||||||
logging:
|
logging:
|
||||||
driver: 'json-file'
|
driver: 'json-file'
|
||||||
options:
|
options:
|
||||||
max-file: '5'
|
max-file: '5'
|
||||||
max-size: '20m'
|
max-size: '20m'
|
||||||
|
|
||||||
x-update-config: &x-update-config
|
x-update-config: &x-update-config
|
||||||
update_config:
|
update_config:
|
||||||
order: stop-first
|
order: stop-first
|
||||||
failure_action: rollback
|
failure_action: rollback
|
||||||
parallelism: 1
|
parallelism: 1
|
||||||
delay: 10s
|
delay: 10s
|
||||||
rollback_config:
|
rollback_config:
|
||||||
failure_action: pause
|
failure_action: pause
|
||||||
monitor: 5s
|
monitor: 5s
|
||||||
parallelism: 2
|
parallelism: 2
|
||||||
order: stop-first
|
order: stop-first
|
||||||
|
|
||||||
version: '3.8'
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
traefik:
|
traefik:
|
||||||
image: traefik:2.9
|
image: traefik:2.9
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
command:
|
command:
|
||||||
- --log.level=DEBUG
|
- --log.level=DEBUG
|
||||||
- --api.insecure=true
|
- --api.insecure=true
|
||||||
- --providers.docker=true
|
- --providers.docker=true
|
||||||
- --providers.docker.watch=true
|
- --providers.docker.watch=true
|
||||||
- --providers.docker.swarmMode=true
|
- --providers.docker.swarmMode=true
|
||||||
- --providers.docker.exposedByDefault=false
|
- --providers.docker.exposedByDefault=false
|
||||||
- --entrypoints.web.address=:80
|
- --entrypoints.web.address=:80
|
||||||
- --entrypoints.websecure.address=:443
|
- --entrypoints.websecure.address=:443
|
||||||
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
||||||
- --entrypoints.web.http.redirections.entrypoint.scheme=https
|
- --entrypoints.web.http.redirections.entrypoint.scheme=https
|
||||||
- --providers.docker.constraints=Label(`traefik.constraint-label-stack`,`appwrite`)
|
- --providers.docker.constraints=Label(`traefik.constraint-label-stack`,`appwrite`)
|
||||||
- --certificatesresolvers.myresolver.acme.httpchallenge=true
|
- --certificatesresolvers.myresolver.acme.httpchallenge=true
|
||||||
- --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
|
- --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
|
||||||
- --certificatesresolvers.myresolver.acme.email=$_APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
- --certificatesresolvers.myresolver.acme.email=$_APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||||
- --certificatesresolvers.myresolver.acme.storage=/letsencrypt/${_APP_DOMAIN}.json
|
- --certificatesresolvers.myresolver.acme.storage=/letsencrypt/${_APP_DOMAIN}.json
|
||||||
- --accesslog=true
|
- --accesslog=true
|
||||||
ports:
|
ports:
|
||||||
- 80:80
|
- 80:80
|
||||||
- 443:443
|
- 443:443
|
||||||
- 8080:8080
|
- 8080:8080
|
||||||
volumes:
|
volumes:
|
||||||
- /letsencrypt:/letsencrypt
|
- /letsencrypt:/letsencrypt
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
networks:
|
networks:
|
||||||
- cloud
|
- cloud
|
||||||
deploy:
|
deploy:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
<<: *x-update-config
|
<<: *x-update-config
|
||||||
placement:
|
placement:
|
||||||
max_replicas_per_node: 1
|
max_replicas_per_node: 1
|
||||||
constraints:
|
constraints:
|
||||||
- node.role == manager
|
- node.role == manager
|
||||||
preferences:
|
preferences:
|
||||||
- spread: node.role == worker
|
- spread: node.role == worker
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.traefik.middlewares=traefik-compress
|
- traefik.http.routers.traefik.middlewares=traefik-compress
|
||||||
- traefik.http.middlewares.traefik-compress.compress=true
|
- traefik.http.middlewares.traefik-compress.compress=true
|
||||||
|
|
||||||
server:
|
server:
|
||||||
image: ghcr.io/appwrite/website:$_APP_VERSION
|
image: ghcr.io/appwrite/website:$_APP_VERSION
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
networks:
|
networks:
|
||||||
- cloud
|
- cloud
|
||||||
environment:
|
environment:
|
||||||
- PUBLIC_APPWRITE_PROJECT_INIT_ID
|
- PUBLIC_APPWRITE_PROJECT_INIT_ID
|
||||||
- PUBLIC_APPWRITE_PROJECT_ID
|
- PUBLIC_APPWRITE_PROJECT_ID
|
||||||
- PUBLIC_APPWRITE_DB_MAIN_ID
|
- PUBLIC_APPWRITE_DB_MAIN_ID
|
||||||
- PUBLIC_APPWRITE_COL_THREADS_ID
|
- PUBLIC_APPWRITE_COL_THREADS_ID
|
||||||
- PUBLIC_APPWRITE_COL_MESSAGES_ID
|
- PUBLIC_APPWRITE_COL_MESSAGES_ID
|
||||||
- PUBLIC_APPWRITE_FN_TLDR_ID
|
- PUBLIC_APPWRITE_FN_TLDR_ID
|
||||||
deploy:
|
deploy:
|
||||||
<<: *x-update-config
|
<<: *x-update-config
|
||||||
mode: replicated
|
mode: replicated
|
||||||
replicas: 8
|
replicas: 8
|
||||||
placement:
|
placement:
|
||||||
max_replicas_per_node: 2
|
max_replicas_per_node: 2
|
||||||
constraints:
|
constraints:
|
||||||
- node.role == worker
|
- node.role == worker
|
||||||
preferences:
|
preferences:
|
||||||
- spread: node.role == worker
|
- spread: node.role == worker
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.docker.lbswarm=true
|
- traefik.docker.lbswarm=true
|
||||||
- traefik.constraint-label-stack=appwrite
|
- traefik.constraint-label-stack=appwrite
|
||||||
- traefik.http.services.appwrite_service.loadbalancer.server.port=3000
|
- traefik.http.services.appwrite_service.loadbalancer.server.port=3000
|
||||||
- traefik.http.middlewares.appwrite_middlewares.compress=true
|
- traefik.http.middlewares.appwrite_middlewares.compress=true
|
||||||
#http
|
#http
|
||||||
- traefik.http.routers.appwrite.entrypoints=web
|
- traefik.http.routers.appwrite.entrypoints=web
|
||||||
- traefik.http.routers.appwrite.rule=Host(`$_APP_DOMAIN`) || Host(`www.$_APP_DOMAIN`)
|
- traefik.http.routers.appwrite.rule=Host(`$_APP_DOMAIN`) || Host(`www.$_APP_DOMAIN`)
|
||||||
- traefik.http.routers.appwrite.service=appwrite_service
|
- traefik.http.routers.appwrite.service=appwrite_service
|
||||||
- traefik.http.routers.appwrite.middlewares=appwrite_middlewares
|
- traefik.http.routers.appwrite.middlewares=appwrite_middlewares
|
||||||
# https
|
# https
|
||||||
- traefik.http.routers.appwrite_secure.entrypoints=websecure
|
- traefik.http.routers.appwrite_secure.entrypoints=websecure
|
||||||
- traefik.http.routers.appwrite_secure.rule=Host(`$_APP_DOMAIN`) || Host(`www.$_APP_DOMAIN`)
|
- traefik.http.routers.appwrite_secure.rule=Host(`$_APP_DOMAIN`) || Host(`www.$_APP_DOMAIN`)
|
||||||
- traefik.http.routers.appwrite_secure.service=appwrite_service
|
- traefik.http.routers.appwrite_secure.service=appwrite_service
|
||||||
- traefik.http.routers.appwrite_secure.tls=true
|
- traefik.http.routers.appwrite_secure.tls=true
|
||||||
- traefik.http.routers.appwrite_secure.tls.certresolver=myresolver
|
- traefik.http.routers.appwrite_secure.tls.certresolver=myresolver
|
||||||
- traefik.http.routers.appwrite_secure.middlewares=appwrite_middlewares
|
- traefik.http.routers.appwrite_secure.middlewares=appwrite_middlewares
|
||||||
|
|
||||||
janitor:
|
janitor:
|
||||||
image: appwrite/docker-janitor
|
image: appwrite/docker-janitor
|
||||||
deploy:
|
deploy:
|
||||||
mode: global
|
mode: global
|
||||||
environment:
|
environment:
|
||||||
- TIME_BETWEEN_RUNS=600
|
- TIME_BETWEEN_RUNS=600
|
||||||
- UNUSED_TIME=10m
|
- UNUSED_TIME=10m
|
||||||
- RUN_ON_STARTUP=true
|
- RUN_ON_STARTUP=true
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
|
||||||
sematext-agent:
|
sematext-agent:
|
||||||
image: sematext/agent:latest
|
image: sematext/agent:latest
|
||||||
environment:
|
environment:
|
||||||
REGION: EU
|
REGION: EU
|
||||||
INFRA_TOKEN: $SEMATEXT_TOKEN
|
INFRA_TOKEN: $SEMATEXT_TOKEN
|
||||||
deploy:
|
deploy:
|
||||||
mode: global
|
mode: global
|
||||||
restart_policy:
|
restart_policy:
|
||||||
condition: any
|
condition: any
|
||||||
volumes:
|
volumes:
|
||||||
- /:/hostfs:ro
|
- /:/hostfs:ro
|
||||||
- /etc/passwd:/etc/passwd:ro
|
- /etc/passwd:/etc/passwd:ro
|
||||||
- /etc/group:/etc/group:ro
|
- /etc/group:/etc/group:ro
|
||||||
- /sys:/host/sys:ro
|
- /sys:/host/sys:ro
|
||||||
- /dev:/hostfs/dev:ro
|
- /dev:/hostfs/dev:ro
|
||||||
- /var/run:/var/run
|
- /var/run:/var/run
|
||||||
- /sys/kernel/debug:/sys/kernel/debug
|
- /sys/kernel/debug:/sys/kernel/debug
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
cloud:
|
cloud:
|
||||||
driver: overlay
|
driver: overlay
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
"openapi-types": "^12.1.3",
|
"openapi-types": "^12.1.3",
|
||||||
"oslllo-svg-fixer": "^3.0.0",
|
"oslllo-svg-fixer": "^3.0.0",
|
||||||
"postcss": "^8.4.39",
|
"postcss": "^8.4.39",
|
||||||
"prettier": "^3.3.2",
|
"prettier": "^3.3.3",
|
||||||
"prettier-plugin-svelte": "^3.2.5",
|
"prettier-plugin-svelte": "^3.2.5",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||||
"sass": "^1.77.6",
|
"sass": "^1.77.6",
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
import type { PlaywrightTestConfig } from '@playwright/test';
|
||||||
|
|
||||||
const config: PlaywrightTestConfig = {
|
const config: PlaywrightTestConfig = {
|
||||||
webServer: {
|
webServer: {
|
||||||
command: 'npm run build && npm run preview',
|
command: 'npm run build && npm run preview',
|
||||||
port: 4173
|
port: 4173
|
||||||
},
|
},
|
||||||
testDir: 'tests',
|
testDir: 'tests',
|
||||||
testMatch: /(.+\.)?(test|spec)\.[jt]s/
|
testMatch: /(.+\.)?(test|spec)\.[jt]s/
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|||||||
24
pnpm-lock.yaml
generated
24
pnpm-lock.yaml
generated
@@ -109,14 +109,14 @@ importers:
|
|||||||
specifier: ^8.4.39
|
specifier: ^8.4.39
|
||||||
version: 8.4.39
|
version: 8.4.39
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.3.2
|
specifier: ^3.3.3
|
||||||
version: 3.3.2
|
version: 3.3.3
|
||||||
prettier-plugin-svelte:
|
prettier-plugin-svelte:
|
||||||
specifier: ^3.2.5
|
specifier: ^3.2.5
|
||||||
version: 3.2.5(prettier@3.3.2)(svelte@4.2.18)
|
version: 3.2.5(prettier@3.3.3)(svelte@4.2.18)
|
||||||
prettier-plugin-tailwindcss:
|
prettier-plugin-tailwindcss:
|
||||||
specifier: ^0.6.5
|
specifier: ^0.6.5
|
||||||
version: 0.6.5(prettier-plugin-svelte@3.2.5(prettier@3.3.2)(svelte@4.2.18))(prettier@3.3.2)
|
version: 0.6.5(prettier-plugin-svelte@3.2.5(prettier@3.3.3)(svelte@4.2.18))(prettier@3.3.3)
|
||||||
sass:
|
sass:
|
||||||
specifier: ^1.77.6
|
specifier: ^1.77.6
|
||||||
version: 1.77.6
|
version: 1.77.6
|
||||||
@@ -3388,8 +3388,8 @@ packages:
|
|||||||
prettier-plugin-svelte:
|
prettier-plugin-svelte:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
prettier@3.3.2:
|
prettier@3.3.3:
|
||||||
resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==}
|
resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@@ -7552,18 +7552,18 @@ snapshots:
|
|||||||
|
|
||||||
prelude-ls@1.2.1: {}
|
prelude-ls@1.2.1: {}
|
||||||
|
|
||||||
prettier-plugin-svelte@3.2.5(prettier@3.3.2)(svelte@4.2.18):
|
prettier-plugin-svelte@3.2.5(prettier@3.3.3)(svelte@4.2.18):
|
||||||
dependencies:
|
dependencies:
|
||||||
prettier: 3.3.2
|
prettier: 3.3.3
|
||||||
svelte: 4.2.18
|
svelte: 4.2.18
|
||||||
|
|
||||||
prettier-plugin-tailwindcss@0.6.5(prettier-plugin-svelte@3.2.5(prettier@3.3.2)(svelte@4.2.18))(prettier@3.3.2):
|
prettier-plugin-tailwindcss@0.6.5(prettier-plugin-svelte@3.2.5(prettier@3.3.3)(svelte@4.2.18))(prettier@3.3.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
prettier: 3.3.2
|
prettier: 3.3.3
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
prettier-plugin-svelte: 3.2.5(prettier@3.3.2)(svelte@4.2.18)
|
prettier-plugin-svelte: 3.2.5(prettier@3.3.3)(svelte@4.2.18)
|
||||||
|
|
||||||
prettier@3.3.2: {}
|
prettier@3.3.3: {}
|
||||||
|
|
||||||
pretty-format@29.7.0:
|
pretty-format@29.7.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ const perPage = 100;
|
|||||||
|
|
||||||
const outputFile = `./src/lib/contributors.ts`;
|
const outputFile = `./src/lib/contributors.ts`;
|
||||||
|
|
||||||
const headers = process.env.GITHUB_TOKEN ? {
|
const headers = process.env.GITHUB_TOKEN
|
||||||
Authorization: `token ${process.env.GITHUB_TOKEN}`
|
? {
|
||||||
} : {}
|
Authorization: `token ${process.env.GITHUB_TOKEN}`
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
|
||||||
console.log(`using github token: ${!!process.env.GITHUB_TOKEN}`)
|
console.log(`using github token: ${!!process.env.GITHUB_TOKEN}`);
|
||||||
|
|
||||||
async function fetchRepositories() {
|
async function fetchRepositories() {
|
||||||
let page = 1;
|
let page = 1;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
if (isDocs) {
|
if (isDocs) {
|
||||||
const theme = localStorage.getItem('theme');
|
const theme = localStorage.getItem('theme');
|
||||||
if (theme) {
|
if (theme) {
|
||||||
document.body.classList.remove('theme-dark', 'theme-light');
|
document.body.classList.remove('theme-dark', 'light');
|
||||||
if (theme === 'system') {
|
if (theme === 'system') {
|
||||||
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)')
|
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)')
|
||||||
.matches
|
.matches
|
||||||
|
|||||||
@@ -18,11 +18,13 @@ Sentry.init({
|
|||||||
replaysOnErrorSampleRate: 1.0,
|
replaysOnErrorSampleRate: 1.0,
|
||||||
|
|
||||||
// If you don't want to use Session Replay, just remove the line below:
|
// If you don't want to use Session Replay, just remove the line below:
|
||||||
integrations: [replayIntegration({
|
integrations: [
|
||||||
maskAllInputs: true,
|
replayIntegration({
|
||||||
maskAllText: false,
|
maskAllInputs: true,
|
||||||
blockAllMedia: false,
|
maskAllText: false,
|
||||||
})]
|
blockAllMedia: false
|
||||||
|
})
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
// If you have a custom error handler, pass it to `handleErrorWithSentry`
|
// If you have a custom error handler, pass it to `handleErrorWithSentry`
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Sentry.init({
|
|||||||
dsn: SENTRY_DSN,
|
dsn: SENTRY_DSN,
|
||||||
tracesSampleRate: 1,
|
tracesSampleRate: 1,
|
||||||
allowUrls: [/appwrite\.io/]
|
allowUrls: [/appwrite\.io/]
|
||||||
})
|
});
|
||||||
|
|
||||||
const redirectMap = new Map(redirects.map(({ link, redirect }) => [link, redirect]));
|
const redirectMap = new Map(redirects.map(({ link, redirect }) => [link, redirect]));
|
||||||
|
|
||||||
@@ -36,4 +36,4 @@ const bannerRewriter: Handle = async ({ event, resolve }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const handle = sequence(Sentry.sentryHandle(), redirecter, bannerRewriter);
|
export const handle = sequence(Sentry.sentryHandle(), redirecter, bannerRewriter);
|
||||||
export const handleError = Sentry.handleErrorWithSentry();
|
export const handleError = Sentry.handleErrorWithSentry();
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { generateIcons } from "./scripts.js";
|
import { generateIcons } from './scripts.js';
|
||||||
|
|
||||||
generateIcons();
|
generateIcons();
|
||||||
|
|||||||
@@ -1,302 +1,302 @@
|
|||||||
{
|
{
|
||||||
"apple": {
|
"apple": {
|
||||||
"encodedCode": "\\ea01",
|
"encodedCode": "\\ea01",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-apple",
|
"className": "web-icon-apple",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"appwrite": {
|
"appwrite": {
|
||||||
"encodedCode": "\\ea02",
|
"encodedCode": "\\ea02",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-appwrite",
|
"className": "web-icon-appwrite",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"arrow-down": {
|
"arrow-down": {
|
||||||
"encodedCode": "\\ea03",
|
"encodedCode": "\\ea03",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-arrow-down",
|
"className": "web-icon-arrow-down",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"arrow-ext-link": {
|
"arrow-ext-link": {
|
||||||
"encodedCode": "\\ea04",
|
"encodedCode": "\\ea04",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-arrow-ext-link",
|
"className": "web-icon-arrow-ext-link",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"arrow-left": {
|
"arrow-left": {
|
||||||
"encodedCode": "\\ea05",
|
"encodedCode": "\\ea05",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-arrow-left",
|
"className": "web-icon-arrow-left",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"arrow-right": {
|
"arrow-right": {
|
||||||
"encodedCode": "\\ea06",
|
"encodedCode": "\\ea06",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-arrow-right",
|
"className": "web-icon-arrow-right",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"arrow-up": {
|
"arrow-up": {
|
||||||
"encodedCode": "\\ea07",
|
"encodedCode": "\\ea07",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-arrow-up",
|
"className": "web-icon-arrow-up",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"encodedCode": "\\ea08",
|
"encodedCode": "\\ea08",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-calendar",
|
"className": "web-icon-calendar",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"encodedCode": "\\ea09",
|
"encodedCode": "\\ea09",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-check",
|
"className": "web-icon-check",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"chevron-down": {
|
"chevron-down": {
|
||||||
"encodedCode": "\\ea0a",
|
"encodedCode": "\\ea0a",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-chevron-down",
|
"className": "web-icon-chevron-down",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"chevron-left": {
|
"chevron-left": {
|
||||||
"encodedCode": "\\ea0b",
|
"encodedCode": "\\ea0b",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-chevron-left",
|
"className": "web-icon-chevron-left",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"chevron-right": {
|
"chevron-right": {
|
||||||
"encodedCode": "\\ea0c",
|
"encodedCode": "\\ea0c",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-chevron-right",
|
"className": "web-icon-chevron-right",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"chevron-up": {
|
"chevron-up": {
|
||||||
"encodedCode": "\\ea0d",
|
"encodedCode": "\\ea0d",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-chevron-up",
|
"className": "web-icon-chevron-up",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"close": {
|
"close": {
|
||||||
"encodedCode": "\\ea0e",
|
"encodedCode": "\\ea0e",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-close",
|
"className": "web-icon-close",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"command": {
|
"command": {
|
||||||
"encodedCode": "\\ea0f",
|
"encodedCode": "\\ea0f",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-command",
|
"className": "web-icon-command",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"copy": {
|
"copy": {
|
||||||
"encodedCode": "\\ea10",
|
"encodedCode": "\\ea10",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-copy",
|
"className": "web-icon-copy",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"dark": {
|
"dark": {
|
||||||
"encodedCode": "\\ea11",
|
"encodedCode": "\\ea11",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-dark",
|
"className": "web-icon-dark",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"discord": {
|
"discord": {
|
||||||
"encodedCode": "\\ea12",
|
"encodedCode": "\\ea12",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-discord",
|
"className": "web-icon-discord",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"divider-vertical": {
|
"divider-vertical": {
|
||||||
"encodedCode": "\\ea13",
|
"encodedCode": "\\ea13",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-divider-vertical",
|
"className": "web-icon-divider-vertical",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"encodedCode": "\\ea14",
|
"encodedCode": "\\ea14",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-download",
|
"className": "web-icon-download",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"ext-link": {
|
"ext-link": {
|
||||||
"encodedCode": "\\ea15",
|
"encodedCode": "\\ea15",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-ext-link",
|
"className": "web-icon-ext-link",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"firebase": {
|
"firebase": {
|
||||||
"encodedCode": "\\ea16",
|
"encodedCode": "\\ea16",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-firebase",
|
"className": "web-icon-firebase",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"github": {
|
"github": {
|
||||||
"encodedCode": "\\ea17",
|
"encodedCode": "\\ea17",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-github",
|
"className": "web-icon-github",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"google": {
|
"google": {
|
||||||
"encodedCode": "\\ea18",
|
"encodedCode": "\\ea18",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-google",
|
"className": "web-icon-google",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"hamburger-menu": {
|
"hamburger-menu": {
|
||||||
"encodedCode": "\\ea19",
|
"encodedCode": "\\ea19",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-hamburger-menu",
|
"className": "web-icon-hamburger-menu",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"light": {
|
"light": {
|
||||||
"encodedCode": "\\ea1a",
|
"encodedCode": "\\ea1a",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-light",
|
"className": "web-icon-light",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"linkedin": {
|
"linkedin": {
|
||||||
"encodedCode": "\\ea1b",
|
"encodedCode": "\\ea1b",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-linkedin",
|
"className": "web-icon-linkedin",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"location": {
|
"location": {
|
||||||
"encodedCode": "\\ea1c",
|
"encodedCode": "\\ea1c",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-location",
|
"className": "web-icon-location",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"logout-left": {
|
"logout-left": {
|
||||||
"encodedCode": "\\ea1d",
|
"encodedCode": "\\ea1d",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-logout-left",
|
"className": "web-icon-logout-left",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"logout-right": {
|
"logout-right": {
|
||||||
"encodedCode": "\\ea1e",
|
"encodedCode": "\\ea1e",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-logout-right",
|
"className": "web-icon-logout-right",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"mailgun": {
|
"mailgun": {
|
||||||
"encodedCode": "\\ea1f",
|
"encodedCode": "\\ea1f",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-mailgun",
|
"className": "web-icon-mailgun",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"message": {
|
"message": {
|
||||||
"encodedCode": "\\ea20",
|
"encodedCode": "\\ea20",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-message",
|
"className": "web-icon-message",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"microsoft": {
|
"microsoft": {
|
||||||
"encodedCode": "\\ea21",
|
"encodedCode": "\\ea21",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-microsoft",
|
"className": "web-icon-microsoft",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"minus": {
|
"minus": {
|
||||||
"encodedCode": "\\ea22",
|
"encodedCode": "\\ea22",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-minus",
|
"className": "web-icon-minus",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"nuxt": {
|
"nuxt": {
|
||||||
"encodedCode": "\\ea23",
|
"encodedCode": "\\ea23",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-nuxt",
|
"className": "web-icon-nuxt",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"platform": {
|
"platform": {
|
||||||
"encodedCode": "\\ea24",
|
"encodedCode": "\\ea24",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-platform",
|
"className": "web-icon-platform",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"play": {
|
"play": {
|
||||||
"encodedCode": "\\ea25",
|
"encodedCode": "\\ea25",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-play",
|
"className": "web-icon-play",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"plus": {
|
"plus": {
|
||||||
"encodedCode": "\\ea26",
|
"encodedCode": "\\ea26",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-plus",
|
"className": "web-icon-plus",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"product-hunt": {
|
"product-hunt": {
|
||||||
"encodedCode": "\\ea27",
|
"encodedCode": "\\ea27",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-product-hunt",
|
"className": "web-icon-product-hunt",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"refine": {
|
"refine": {
|
||||||
"encodedCode": "\\ea28",
|
"encodedCode": "\\ea28",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-refine",
|
"className": "web-icon-refine",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"rest": {
|
"rest": {
|
||||||
"encodedCode": "\\ea29",
|
"encodedCode": "\\ea29",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-rest",
|
"className": "web-icon-rest",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"encodedCode": "\\ea2a",
|
"encodedCode": "\\ea2a",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-search",
|
"className": "web-icon-search",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"sendgrid": {
|
"sendgrid": {
|
||||||
"encodedCode": "\\ea2b",
|
"encodedCode": "\\ea2b",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-sendgrid",
|
"className": "web-icon-sendgrid",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"star": {
|
"star": {
|
||||||
"encodedCode": "\\ea2c",
|
"encodedCode": "\\ea2c",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-star",
|
"className": "web-icon-star",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"encodedCode": "\\ea2d",
|
"encodedCode": "\\ea2d",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-system",
|
"className": "web-icon-system",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"textmagic": {
|
"textmagic": {
|
||||||
"encodedCode": "\\ea2e",
|
"encodedCode": "\\ea2e",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-textmagic",
|
"className": "web-icon-textmagic",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"twitter": {
|
"twitter": {
|
||||||
"encodedCode": "\\ea2f",
|
"encodedCode": "\\ea2f",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-twitter",
|
"className": "web-icon-twitter",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"vue": {
|
"vue": {
|
||||||
"encodedCode": "\\ea30",
|
"encodedCode": "\\ea30",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-vue",
|
"className": "web-icon-vue",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"x": {
|
"x": {
|
||||||
"encodedCode": "\\ea31",
|
"encodedCode": "\\ea31",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-x",
|
"className": "web-icon-x",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
},
|
},
|
||||||
"youtube": {
|
"youtube": {
|
||||||
"encodedCode": "\\ea32",
|
"encodedCode": "\\ea32",
|
||||||
"prefix": "web-icon",
|
"prefix": "web-icon",
|
||||||
"className": "web-icon-youtube",
|
"className": "web-icon-youtube",
|
||||||
"unicode": ""
|
"unicode": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "web-icon";
|
font-family: 'web-icon';
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url('web-icon.eot'); /* IE9*/
|
src: url('web-icon.eot'); /* IE9*/
|
||||||
src: url('web-icon.eot#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
src:
|
||||||
url("web-icon.woff2") format("woff2"),
|
url('web-icon.eot#iefix') format('embedded-opentype'),
|
||||||
url("web-icon.woff") format("woff"),
|
/* IE6-IE8 */ url('web-icon.woff2') format('woff2'),
|
||||||
url('web-icon.ttf') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
|
url('web-icon.woff') format('woff'),
|
||||||
url('web-icon.svg#web-icon') format('svg'); /* iOS 4.1- */
|
url('web-icon.ttf') format('truetype'),
|
||||||
|
/* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ url('web-icon.svg#web-icon')
|
||||||
|
format('svg'); /* iOS 4.1- */
|
||||||
}
|
}
|
||||||
|
|
||||||
[class^="web-icon-"], [class*=" web-icon-"] {
|
[class^='web-icon-'],
|
||||||
|
[class*=' web-icon-'] {
|
||||||
font-family: 'web-icon' !important;
|
font-family: 'web-icon' !important;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -17,53 +20,153 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
.web-icon-apple:before { content: "\ea01"; }
|
.web-icon-apple:before {
|
||||||
.web-icon-appwrite:before { content: "\ea02"; }
|
content: '\ea01';
|
||||||
.web-icon-arrow-down:before { content: "\ea03"; }
|
}
|
||||||
.web-icon-arrow-ext-link:before { content: "\ea04"; }
|
.web-icon-appwrite:before {
|
||||||
.web-icon-arrow-left:before { content: "\ea05"; }
|
content: '\ea02';
|
||||||
.web-icon-arrow-right:before { content: "\ea06"; }
|
}
|
||||||
.web-icon-arrow-up:before { content: "\ea07"; }
|
.web-icon-arrow-down:before {
|
||||||
.web-icon-calendar:before { content: "\ea08"; }
|
content: '\ea03';
|
||||||
.web-icon-check:before { content: "\ea09"; }
|
}
|
||||||
.web-icon-chevron-down:before { content: "\ea0a"; }
|
.web-icon-arrow-ext-link:before {
|
||||||
.web-icon-chevron-left:before { content: "\ea0b"; }
|
content: '\ea04';
|
||||||
.web-icon-chevron-right:before { content: "\ea0c"; }
|
}
|
||||||
.web-icon-chevron-up:before { content: "\ea0d"; }
|
.web-icon-arrow-left:before {
|
||||||
.web-icon-close:before { content: "\ea0e"; }
|
content: '\ea05';
|
||||||
.web-icon-command:before { content: "\ea0f"; }
|
}
|
||||||
.web-icon-copy:before { content: "\ea10"; }
|
.web-icon-arrow-right:before {
|
||||||
.web-icon-dark:before { content: "\ea11"; }
|
content: '\ea06';
|
||||||
.web-icon-discord:before { content: "\ea12"; }
|
}
|
||||||
.web-icon-divider-vertical:before { content: "\ea13"; }
|
.web-icon-arrow-up:before {
|
||||||
.web-icon-download:before { content: "\ea14"; }
|
content: '\ea07';
|
||||||
.web-icon-ext-link:before { content: "\ea15"; }
|
}
|
||||||
.web-icon-firebase:before { content: "\ea16"; }
|
.web-icon-calendar:before {
|
||||||
.web-icon-github:before { content: "\ea17"; }
|
content: '\ea08';
|
||||||
.web-icon-google:before { content: "\ea18"; }
|
}
|
||||||
.web-icon-hamburger-menu:before { content: "\ea19"; }
|
.web-icon-check:before {
|
||||||
.web-icon-light:before { content: "\ea1a"; }
|
content: '\ea09';
|
||||||
.web-icon-linkedin:before { content: "\ea1b"; }
|
}
|
||||||
.web-icon-location:before { content: "\ea1c"; }
|
.web-icon-chevron-down:before {
|
||||||
.web-icon-logout-left:before { content: "\ea1d"; }
|
content: '\ea0a';
|
||||||
.web-icon-logout-right:before { content: "\ea1e"; }
|
}
|
||||||
.web-icon-mailgun:before { content: "\ea1f"; }
|
.web-icon-chevron-left:before {
|
||||||
.web-icon-message:before { content: "\ea20"; }
|
content: '\ea0b';
|
||||||
.web-icon-microsoft:before { content: "\ea21"; }
|
}
|
||||||
.web-icon-minus:before { content: "\ea22"; }
|
.web-icon-chevron-right:before {
|
||||||
.web-icon-nuxt:before { content: "\ea23"; }
|
content: '\ea0c';
|
||||||
.web-icon-platform:before { content: "\ea24"; }
|
}
|
||||||
.web-icon-play:before { content: "\ea25"; }
|
.web-icon-chevron-up:before {
|
||||||
.web-icon-plus:before { content: "\ea26"; }
|
content: '\ea0d';
|
||||||
.web-icon-product-hunt:before { content: "\ea27"; }
|
}
|
||||||
.web-icon-refine:before { content: "\ea28"; }
|
.web-icon-close:before {
|
||||||
.web-icon-rest:before { content: "\ea29"; }
|
content: '\ea0e';
|
||||||
.web-icon-search:before { content: "\ea2a"; }
|
}
|
||||||
.web-icon-sendgrid:before { content: "\ea2b"; }
|
.web-icon-command:before {
|
||||||
.web-icon-star:before { content: "\ea2c"; }
|
content: '\ea0f';
|
||||||
.web-icon-system:before { content: "\ea2d"; }
|
}
|
||||||
.web-icon-textmagic:before { content: "\ea2e"; }
|
.web-icon-copy:before {
|
||||||
.web-icon-twitter:before { content: "\ea2f"; }
|
content: '\ea10';
|
||||||
.web-icon-vue:before { content: "\ea30"; }
|
}
|
||||||
.web-icon-x:before { content: "\ea31"; }
|
.web-icon-dark:before {
|
||||||
.web-icon-youtube:before { content: "\ea32"; }
|
content: '\ea11';
|
||||||
|
}
|
||||||
|
.web-icon-discord:before {
|
||||||
|
content: '\ea12';
|
||||||
|
}
|
||||||
|
.web-icon-divider-vertical:before {
|
||||||
|
content: '\ea13';
|
||||||
|
}
|
||||||
|
.web-icon-download:before {
|
||||||
|
content: '\ea14';
|
||||||
|
}
|
||||||
|
.web-icon-ext-link:before {
|
||||||
|
content: '\ea15';
|
||||||
|
}
|
||||||
|
.web-icon-firebase:before {
|
||||||
|
content: '\ea16';
|
||||||
|
}
|
||||||
|
.web-icon-github:before {
|
||||||
|
content: '\ea17';
|
||||||
|
}
|
||||||
|
.web-icon-google:before {
|
||||||
|
content: '\ea18';
|
||||||
|
}
|
||||||
|
.web-icon-hamburger-menu:before {
|
||||||
|
content: '\ea19';
|
||||||
|
}
|
||||||
|
.web-icon-light:before {
|
||||||
|
content: '\ea1a';
|
||||||
|
}
|
||||||
|
.web-icon-linkedin:before {
|
||||||
|
content: '\ea1b';
|
||||||
|
}
|
||||||
|
.web-icon-location:before {
|
||||||
|
content: '\ea1c';
|
||||||
|
}
|
||||||
|
.web-icon-logout-left:before {
|
||||||
|
content: '\ea1d';
|
||||||
|
}
|
||||||
|
.web-icon-logout-right:before {
|
||||||
|
content: '\ea1e';
|
||||||
|
}
|
||||||
|
.web-icon-mailgun:before {
|
||||||
|
content: '\ea1f';
|
||||||
|
}
|
||||||
|
.web-icon-message:before {
|
||||||
|
content: '\ea20';
|
||||||
|
}
|
||||||
|
.web-icon-microsoft:before {
|
||||||
|
content: '\ea21';
|
||||||
|
}
|
||||||
|
.web-icon-minus:before {
|
||||||
|
content: '\ea22';
|
||||||
|
}
|
||||||
|
.web-icon-nuxt:before {
|
||||||
|
content: '\ea23';
|
||||||
|
}
|
||||||
|
.web-icon-platform:before {
|
||||||
|
content: '\ea24';
|
||||||
|
}
|
||||||
|
.web-icon-play:before {
|
||||||
|
content: '\ea25';
|
||||||
|
}
|
||||||
|
.web-icon-plus:before {
|
||||||
|
content: '\ea26';
|
||||||
|
}
|
||||||
|
.web-icon-product-hunt:before {
|
||||||
|
content: '\ea27';
|
||||||
|
}
|
||||||
|
.web-icon-refine:before {
|
||||||
|
content: '\ea28';
|
||||||
|
}
|
||||||
|
.web-icon-rest:before {
|
||||||
|
content: '\ea29';
|
||||||
|
}
|
||||||
|
.web-icon-search:before {
|
||||||
|
content: '\ea2a';
|
||||||
|
}
|
||||||
|
.web-icon-sendgrid:before {
|
||||||
|
content: '\ea2b';
|
||||||
|
}
|
||||||
|
.web-icon-star:before {
|
||||||
|
content: '\ea2c';
|
||||||
|
}
|
||||||
|
.web-icon-system:before {
|
||||||
|
content: '\ea2d';
|
||||||
|
}
|
||||||
|
.web-icon-textmagic:before {
|
||||||
|
content: '\ea2e';
|
||||||
|
}
|
||||||
|
.web-icon-twitter:before {
|
||||||
|
content: '\ea2f';
|
||||||
|
}
|
||||||
|
.web-icon-vue:before {
|
||||||
|
content: '\ea30';
|
||||||
|
}
|
||||||
|
.web-icon-x:before {
|
||||||
|
content: '\ea31';
|
||||||
|
}
|
||||||
|
.web-icon-youtube:before {
|
||||||
|
content: '\ea32';
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { melt } from '@melt-ui/svelte';
|
import { melt } from '@melt-ui/svelte';
|
||||||
import { getTabsContext } from './index.svelte';
|
import { getTabsContext } from './index.svelte';
|
||||||
|
|
||||||
export let tab: string;
|
export let tab: string;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
elements: { content }
|
elements: { content }
|
||||||
} = getTabsContext();
|
} = getTabsContext();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div use:melt={$content(tab)}>
|
<div use:melt={$content(tab)}>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,45 +1,45 @@
|
|||||||
<script lang="ts" context="module">
|
<script lang="ts" context="module">
|
||||||
const CTX_KEY = 'tabs';
|
const CTX_KEY = 'tabs';
|
||||||
|
|
||||||
type Context = Tabs & {
|
type Context = Tabs & {
|
||||||
tabs: readonly string[];
|
tabs: readonly string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const setTabsContext = (ctx: Context) => {
|
const setTabsContext = (ctx: Context) => {
|
||||||
setContext(CTX_KEY, ctx);
|
setContext(CTX_KEY, ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTabsContext = () => {
|
export const getTabsContext = () => {
|
||||||
return getContext<Context>(CTX_KEY);
|
return getContext<Context>(CTX_KEY);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createTabs, melt, type Tabs } from '@melt-ui/svelte';
|
import { createTabs, melt, type Tabs } from '@melt-ui/svelte';
|
||||||
import { getContext, setContext } from 'svelte';
|
import { getContext, setContext } from 'svelte';
|
||||||
import List from './List.svelte';
|
import List from './List.svelte';
|
||||||
import Content from './Content.svelte';
|
import Content from './Content.svelte';
|
||||||
|
|
||||||
export let tabs: Context['tabs'];
|
export let tabs: Context['tabs'];
|
||||||
export let tab = tabs[0];
|
export let tab = tabs[0];
|
||||||
|
|
||||||
const ctx = createTabs({
|
const ctx = createTabs({
|
||||||
defaultValue: tab,
|
defaultValue: tab,
|
||||||
onValueChange({ next }) {
|
onValueChange({ next }) {
|
||||||
tab = next;
|
tab = next;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$: value.set(tab);
|
$: value.set(tab);
|
||||||
|
|
||||||
setTabsContext({ ...ctx, tabs });
|
setTabsContext({ ...ctx, tabs });
|
||||||
|
|
||||||
const {
|
const {
|
||||||
elements: { root },
|
elements: { root },
|
||||||
states: { value }
|
states: { value }
|
||||||
} = ctx;
|
} = ctx;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div use:melt={$root}>
|
<div use:melt={$root}>
|
||||||
<slot TabsList={List} TabContent={Content} />
|
<slot TabsList={List} TabContent={Content} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,54 +2,54 @@ import { tick } from 'svelte';
|
|||||||
import type { Action } from 'svelte/action';
|
import type { Action } from 'svelte/action';
|
||||||
|
|
||||||
export type PortalConfig =
|
export type PortalConfig =
|
||||||
| { target?: string | HTMLElement | undefined; prepend?: boolean }
|
| { target?: string | HTMLElement | undefined; prepend?: boolean }
|
||||||
| undefined;
|
| undefined;
|
||||||
|
|
||||||
const defaults: PortalConfig = {
|
const defaults: PortalConfig = {
|
||||||
target: 'body',
|
target: 'body',
|
||||||
prepend: false
|
prepend: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export const portal: Action<HTMLElement, PortalConfig> = (el, config?: PortalConfig) => {
|
export const portal: Action<HTMLElement, PortalConfig> = (el, config?: PortalConfig) => {
|
||||||
let targetEl;
|
let targetEl;
|
||||||
|
|
||||||
async function update(newConfig: PortalConfig) {
|
async function update(newConfig: PortalConfig) {
|
||||||
const { target, prepend } = { ...defaults, ...newConfig };
|
const { target, prepend } = { ...defaults, ...newConfig };
|
||||||
|
|
||||||
if (typeof target === 'string') {
|
if (typeof target === 'string') {
|
||||||
targetEl = document.querySelector(target);
|
targetEl = document.querySelector(target);
|
||||||
if (targetEl === null) {
|
if (targetEl === null) {
|
||||||
await tick();
|
await tick();
|
||||||
targetEl = document.querySelector(target);
|
targetEl = document.querySelector(target);
|
||||||
}
|
}
|
||||||
if (targetEl === null) {
|
if (targetEl === null) {
|
||||||
throw new Error(`No element found matching css selector: "${target}"`);
|
throw new Error(`No element found matching css selector: "${target}"`);
|
||||||
}
|
}
|
||||||
} else if (target instanceof HTMLElement) {
|
} else if (target instanceof HTMLElement) {
|
||||||
targetEl = target;
|
targetEl = target;
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError(
|
throw new TypeError(
|
||||||
`Unknown portal target type: ${
|
`Unknown portal target type: ${
|
||||||
target === null ? 'null' : typeof target
|
target === null ? 'null' : typeof target
|
||||||
}. Allowed types: string (CSS selector) or HTMLElement.`
|
}. Allowed types: string (CSS selector) or HTMLElement.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
el.dataset.portal = '';
|
el.dataset.portal = '';
|
||||||
if (prepend) {
|
if (prepend) {
|
||||||
targetEl.prepend(el);
|
targetEl.prepend(el);
|
||||||
} else {
|
} else {
|
||||||
targetEl.appendChild(el);
|
targetEl.appendChild(el);
|
||||||
}
|
}
|
||||||
el.hidden = false;
|
el.hidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function destroy() {
|
function destroy() {
|
||||||
el.remove();
|
el.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
update(config ?? {});
|
update(config ?? {});
|
||||||
return {
|
return {
|
||||||
update,
|
update,
|
||||||
destroy
|
destroy
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,25 +4,25 @@ import type { Writable } from 'svelte/store';
|
|||||||
type Args = Writable<DOMRect | null>;
|
type Args = Writable<DOMRect | null>;
|
||||||
|
|
||||||
export const rect: Action<HTMLElement, Args> = (node, store) => {
|
export const rect: Action<HTMLElement, Args> = (node, store) => {
|
||||||
let observer: ResizeObserver | null = null;
|
let observer: ResizeObserver | null = null;
|
||||||
const update = (store: Args) => {
|
const update = (store: Args) => {
|
||||||
observer?.disconnect();
|
observer?.disconnect();
|
||||||
|
|
||||||
store.set(node.getBoundingClientRect());
|
store.set(node.getBoundingClientRect());
|
||||||
|
|
||||||
// Observe resize
|
// Observe resize
|
||||||
observer = new ResizeObserver(() => {
|
observer = new ResizeObserver(() => {
|
||||||
store.set(node.getBoundingClientRect());
|
store.set(node.getBoundingClientRect());
|
||||||
});
|
});
|
||||||
observer.observe(node);
|
observer.observe(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
update(store);
|
update(store);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
update,
|
update,
|
||||||
destroy() {
|
destroy() {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { rect } from '$lib/actions';
|
import { rect } from '$lib/actions';
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
const bodyRect = writable<DOMRect | null>(null);
|
const bodyRect = writable<DOMRect | null>(null);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div
|
<div
|
||||||
class="true-body"
|
class="true-body"
|
||||||
style:width={`${$bodyRect?.width ?? 0}px`}
|
style:width={`${$bodyRect?.width ?? 0}px`}
|
||||||
style:height={`${$bodyRect?.height ?? 0}px`}
|
style:height={`${$bodyRect?.height ?? 0}px`}
|
||||||
/>
|
/>
|
||||||
<div class="body" use:rect={bodyRect}>
|
<div class="body" use:rect={bodyRect}>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.relative {
|
.relative {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.true-body {
|
.true-body {
|
||||||
transition: 0.2s ease;
|
transition: 0.2s ease;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import '$scss/hljs.css';
|
import '$scss/hljs.css';
|
||||||
|
|
||||||
import { getCodeHtml } from '$lib/utils/code';
|
import { getCodeHtml } from '$lib/utils/code';
|
||||||
|
|
||||||
export let content: string;
|
export let content: string;
|
||||||
$: codeHtml = getCodeHtml({ content, language: 'js' });
|
$: codeHtml = getCodeHtml({ content, language: 'js' });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||||
|
|||||||
@@ -1,96 +1,96 @@
|
|||||||
<script>
|
<script>
|
||||||
import AutoBox from '../AutoBox.svelte';
|
import AutoBox from '../AutoBox.svelte';
|
||||||
import Code from './Code.svelte';
|
import Code from './Code.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="code-console">
|
<div class="code-console">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="ellipse" />
|
<div class="ellipse" />
|
||||||
<div class="ellipse-2" />
|
<div class="ellipse-2" />
|
||||||
<div class="ellipse-3" />
|
<div class="ellipse-3" />
|
||||||
</div>
|
</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<AutoBox>
|
<AutoBox>
|
||||||
<slot {Code} />
|
<slot {Code} />
|
||||||
</AutoBox>
|
</AutoBox>
|
||||||
</div>
|
</div>
|
||||||
<div id="code-bottom" />
|
<div id="code-bottom" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@use '$scss/abstract/mixins/border-gradient' as gradients;
|
@use '$scss/abstract/mixins/border-gradient' as gradients;
|
||||||
|
|
||||||
.code-console {
|
.code-console {
|
||||||
@include gradients.border-gradient;
|
@include gradients.border-gradient;
|
||||||
--p-radius: 16px;
|
--p-radius: 16px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
background-color: hsl(var(--web-color-card));
|
background-color: hsl(var(--web-color-card));
|
||||||
border-radius: var(--p-radius);
|
border-radius: var(--p-radius);
|
||||||
--m-border-radius: var(--p-radius);
|
--m-border-radius: var(--p-radius);
|
||||||
--m-border-gradient-before: linear-gradient(
|
--m-border-gradient-before: linear-gradient(
|
||||||
180deg,
|
180deg,
|
||||||
rgba(255, 255, 255, 0.12) 0%,
|
rgba(255, 255, 255, 0.12) 0%,
|
||||||
rgba(255, 255, 255, 0) 125.11%
|
rgba(255, 255, 255, 0) 125.11%
|
||||||
);
|
);
|
||||||
backdrop-filter: blur(8px);
|
backdrop-filter: blur(8px);
|
||||||
|
|
||||||
min-width: 330px;
|
min-width: 330px;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
padding: 0 0.25rem 0.25rem;
|
padding: 0 0.25rem 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background: linear-gradient(129deg, rgba(0, 0, 0, 0.48) 22.38%, rgba(0, 0, 0, 0) 136.5%);
|
background: linear-gradient(129deg, rgba(0, 0, 0, 0.48) 22.38%, rgba(0, 0, 0, 0) 136.5%);
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.375rem;
|
gap: 0.375rem;
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
|
|
||||||
.ellipse {
|
.ellipse {
|
||||||
background-color: #ec6a5e;
|
background-color: #ec6a5e;
|
||||||
|
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
top: 12px;
|
top: 12px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ellipse-2 {
|
.ellipse-2 {
|
||||||
background-color: #f5bf4f;
|
background-color: #f5bf4f;
|
||||||
|
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
top: 12px;
|
top: 12px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ellipse-3 {
|
.ellipse-3 {
|
||||||
background-color: #61c554;
|
background-color: #61c554;
|
||||||
|
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
top: 12px;
|
top: 12px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-console :global(code) {
|
.code-console :global(code) {
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
tab-size: 4;
|
tab-size: 4;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -182,7 +182,7 @@
|
|||||||
class="web-card is-white web-u-min-block-size-320 u-flex-vertical oss-card"
|
class="web-card is-white web-u-min-block-size-320 u-flex-vertical oss-card"
|
||||||
id="oss-discord"
|
id="oss-discord"
|
||||||
>
|
>
|
||||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
<div class="u-flex-vertical u-main-space-between gap-8">
|
||||||
<span
|
<span
|
||||||
class="web-icon-discord web-u-font-size-40"
|
class="web-icon-discord web-u-font-size-40"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -197,7 +197,7 @@
|
|||||||
id="oss-github"
|
id="oss-github"
|
||||||
href="https://github.com/appwrite/appwrite"
|
href="https://github.com/appwrite/appwrite"
|
||||||
>
|
>
|
||||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
<div class="u-flex-vertical u-main-space-between gap-8">
|
||||||
<span
|
<span
|
||||||
class="web-icon-github web-u-font-size-40"
|
class="web-icon-github web-u-font-size-40"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -212,7 +212,7 @@
|
|||||||
class="web-card is-white web-u-min-block-size-320 u-flex-vertical oss-card"
|
class="web-card is-white web-u-min-block-size-320 u-flex-vertical oss-card"
|
||||||
id="oss-twitter"
|
id="oss-twitter"
|
||||||
>
|
>
|
||||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
<div class="u-flex-vertical u-main-space-between gap-8">
|
||||||
<span
|
<span
|
||||||
class="web-icon-x web-u-font-size-40"
|
class="web-icon-x web-u-font-size-40"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
class="web-card is-white web-u-min-block-size-320 u-flex-vertical oss-card"
|
class="web-card is-white web-u-min-block-size-320 u-flex-vertical oss-card"
|
||||||
id="oss-youtube"
|
id="oss-youtube"
|
||||||
>
|
>
|
||||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
<div class="u-flex-vertical u-main-space-between gap-8">
|
||||||
<span
|
<span
|
||||||
class="web-icon-youtube web-u-font-size-40"
|
class="web-icon-youtube web-u-font-size-40"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -242,7 +242,7 @@
|
|||||||
id="oss-commits"
|
id="oss-commits"
|
||||||
href="https://github.com/appwrite/appwrite"
|
href="https://github.com/appwrite/appwrite"
|
||||||
>
|
>
|
||||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
<div class="u-flex-vertical u-main-space-between gap-8">
|
||||||
<span
|
<span
|
||||||
class="web-icon-github web-u-font-size-40"
|
class="web-icon-github web-u-font-size-40"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let id: string | undefined = undefined;
|
export let id: string | undefined = undefined;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="phone" {id}>
|
<div class="phone" {id}>
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,55 +1,55 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import AutoHeight from '../AutoBox.svelte';
|
import AutoHeight from '../AutoBox.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="anim-box">
|
<div class="anim-box">
|
||||||
<div class="top"><slot name="top" /></div>
|
<div class="top"><slot name="top" /></div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<AutoHeight>
|
<AutoHeight>
|
||||||
<slot />
|
<slot />
|
||||||
</AutoHeight>
|
</AutoHeight>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@use '$scss/abstract/mixins/border-gradient' as gradients;
|
@use '$scss/abstract/mixins/border-gradient' as gradients;
|
||||||
|
|
||||||
.anim-box {
|
.anim-box {
|
||||||
@include gradients.border-gradient;
|
@include gradients.border-gradient;
|
||||||
--m-border-radius: 1rem;
|
--m-border-radius: 1rem;
|
||||||
--m-border-gradient-before: linear-gradient(
|
--m-border-gradient-before: linear-gradient(
|
||||||
180deg,
|
180deg,
|
||||||
rgba(255, 255, 255, 0.12) 0%,
|
rgba(255, 255, 255, 0.12) 0%,
|
||||||
rgba(255, 255, 255, 0) 125.11%
|
rgba(255, 255, 255, 0) 125.11%
|
||||||
);
|
);
|
||||||
border-radius: var(--m-border-radius);
|
border-radius: var(--m-border-radius);
|
||||||
background: hsl(var(--web-color-card));
|
background: hsl(var(--web-color-card));
|
||||||
backdrop-filter: blur(8px);
|
backdrop-filter: blur(8px);
|
||||||
|
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
padding-block-start: 0;
|
padding-block-start: 0;
|
||||||
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
.top {
|
.top {
|
||||||
color: var(--greyscale-50, #ededf0);
|
color: var(--greyscale-50, #ededf0);
|
||||||
font-family: Aeonik Pro;
|
font-family: Aeonik Pro;
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 2rem; /* 160% */
|
line-height: 2rem; /* 160% */
|
||||||
letter-spacing: -0.0125rem;
|
letter-spacing: -0.0125rem;
|
||||||
|
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
background: rgba(255, 255, 255, 0.04);
|
background: rgba(255, 255, 255, 0.04);
|
||||||
backdrop-filter: blur(30px);
|
backdrop-filter: blur(30px);
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -247,7 +247,7 @@
|
|||||||
Your backend, minus the hassle
|
Your backend, minus the hassle
|
||||||
</h2>
|
</h2>
|
||||||
<p
|
<p
|
||||||
class="web-description web-u-max-width-700 u-margin-inline-auto"
|
class="web-description web-u-max-width-700 mx-auto"
|
||||||
transition:fly={{
|
transition:fly={{
|
||||||
y: 16,
|
y: 16,
|
||||||
delay: 400
|
delay: 400
|
||||||
|
|||||||
@@ -1,61 +1,61 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createCheckbox, melt } from '@melt-ui/svelte';
|
import { createCheckbox, melt } from '@melt-ui/svelte';
|
||||||
|
|
||||||
export let checked = false;
|
export let checked = false;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
elements: { root },
|
elements: { root },
|
||||||
states: { checked: localChecked },
|
states: { checked: localChecked },
|
||||||
helpers: { isChecked }
|
helpers: { isChecked }
|
||||||
} = createCheckbox({
|
} = createCheckbox({
|
||||||
onCheckedChange({ next }) {
|
onCheckedChange({ next }) {
|
||||||
if (typeof next === 'boolean') {
|
if (typeof next === 'boolean') {
|
||||||
checked = next;
|
checked = next;
|
||||||
}
|
}
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$: localChecked.set(checked);
|
$: localChecked.set(checked);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<button use:melt={$root} class="anim-checkbox">
|
<button use:melt={$root} class="anim-checkbox">
|
||||||
{#if $isChecked}
|
{#if $isChecked}
|
||||||
<span class="web-icon-check" />
|
<span class="web-icon-check" />
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.wrapper {
|
.wrapper {
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.anim-checkbox {
|
.anim-checkbox {
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
border-radius: 0.125rem;
|
border-radius: 0.125rem;
|
||||||
border: 1.5px solid var(--greyscale-500, #818186);
|
border: 1.5px solid var(--greyscale-500, #818186);
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&:global(.anim-checkbox[data-state='checked']) {
|
&:global(.anim-checkbox[data-state='checked']) {
|
||||||
background-color: #7c67fe;
|
background-color: #7c67fe;
|
||||||
border-color: #7c67fe;
|
border-color: #7c67fe;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[class*='icon-'] {
|
[class*='icon-'] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,64 +1,64 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getInitials } from '$lib/animations';
|
import { getInitials } from '$lib/animations';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
import { authController } from '.';
|
import { authController } from '.';
|
||||||
import { flip } from '$lib/utils/flip';
|
import { flip } from '$lib/utils/flip';
|
||||||
|
|
||||||
const { state } = authController;
|
const { state } = authController;
|
||||||
|
|
||||||
type AuthEntry = {
|
type AuthEntry = {
|
||||||
avatar: string;
|
avatar: string;
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
id: number;
|
id: number;
|
||||||
};
|
};
|
||||||
$: authData = [
|
$: authData = [
|
||||||
$state.submitted
|
$state.submitted
|
||||||
? {
|
? {
|
||||||
avatar: getInitials($state.name),
|
avatar: getInitials($state.name),
|
||||||
name: $state.name,
|
name: $state.name,
|
||||||
email: $state.email,
|
email: $state.email,
|
||||||
id: 0
|
id: 0
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
{
|
{
|
||||||
avatar: 'BD',
|
avatar: 'BD',
|
||||||
name: 'Benjamin Davis',
|
name: 'Benjamin Davis',
|
||||||
email: 'benjamin.davis@example.com',
|
email: 'benjamin.davis@example.com',
|
||||||
id: 1
|
id: 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
avatar: 'OS',
|
avatar: 'OS',
|
||||||
name: 'Olivia Smith',
|
name: 'Olivia Smith',
|
||||||
email: 'olivia.smith@example.com',
|
email: 'olivia.smith@example.com',
|
||||||
id: 2
|
id: 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
avatar: 'EW',
|
avatar: 'EW',
|
||||||
name: 'Ethan Wilson',
|
name: 'Ethan Wilson',
|
||||||
email: 'ethan.wilson@example.com',
|
email: 'ethan.wilson@example.com',
|
||||||
id: 3
|
id: 3
|
||||||
}
|
}
|
||||||
].filter(Boolean) as AuthEntry[];
|
].filter(Boolean) as AuthEntry[];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="pseudo-table">
|
<div class="pseudo-table">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<span class="web-eyebrow">Name</span>
|
<span class="web-eyebrow">Name</span>
|
||||||
<span class="web-eyebrow">Identifier</span>
|
<span class="web-eyebrow">Identifier</span>
|
||||||
</div>
|
</div>
|
||||||
{#each authData as user (user.id)}
|
{#each authData as user (user.id)}
|
||||||
<div
|
<div
|
||||||
class="row"
|
class="row"
|
||||||
in:fly={{ duration: 100, x: -16, delay: 100 }}
|
in:fly={{ duration: 100, x: -16, delay: 100 }}
|
||||||
out:fly={{ duration: 100, x: -16 }}
|
out:fly={{ duration: 100, x: -16 }}
|
||||||
animate:flip={{ duration: 150 }}
|
animate:flip={{ duration: 150 }}
|
||||||
>
|
>
|
||||||
<div class="u-flex u-cross-center u-gap-12">
|
<div class="flex u-cross-center gap-3">
|
||||||
<div class="avatar is-size-small">{user.avatar}</div>
|
<div class="avatar is-size-small">{user.avatar}</div>
|
||||||
<span class="truncated">{user.name}</span>
|
<span class="truncated">{user.name}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="truncated">{user.email}</span>
|
<span class="truncated">{user.email}</span>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,211 +1,220 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { authController } from '.';
|
import { authController } from '.';
|
||||||
import { objectKeys } from '$lib/utils/object';
|
import { objectKeys } from '$lib/utils/object';
|
||||||
import { flip } from '$lib/utils/flip';
|
import { flip } from '$lib/utils/flip';
|
||||||
|
|
||||||
const { state } = authController;
|
const { state } = authController;
|
||||||
|
|
||||||
$: controlsEnabled = $state.showControls && Object.values($state.controls).some(Boolean);
|
$: controlsEnabled = $state.showControls && Object.values($state.controls).some(Boolean);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div data-theme-ignore class="inner-phone theme-light">
|
<div data-theme-ignore class="inner-phone light">
|
||||||
<p class="title">Create an Account</p>
|
<p class="title">Create an Account</p>
|
||||||
<p class="subtitle">Please enter your details</p>
|
<p class="subtitle">Please enter your details</p>
|
||||||
<div class="inputs">
|
<div class="inputs">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="name">Your Name</label>
|
<label for="name">Your Name</label>
|
||||||
<input type="name" id="name" placeholder="Enter your name" bind:value={$state.name} />
|
<input type="name" id="name" placeholder="Enter your name" bind:value={$state.name} />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="email">Your Email</label>
|
<label for="email">Your Email</label>
|
||||||
<input type="email" id="email" placeholder="Enter your email" bind:value={$state.email} />
|
<input
|
||||||
</fieldset>
|
type="email"
|
||||||
<fieldset>
|
id="email"
|
||||||
<label for="password">Create Password</label>
|
placeholder="Enter your email"
|
||||||
<input
|
bind:value={$state.email}
|
||||||
type="password"
|
/>
|
||||||
id="password"
|
</fieldset>
|
||||||
placeholder="Enter Password"
|
<fieldset>
|
||||||
bind:value={$state.password}
|
<label for="password">Create Password</label>
|
||||||
/>
|
<input
|
||||||
</fieldset>
|
type="password"
|
||||||
</div>
|
id="password"
|
||||||
<button class="sign-up">Sign Up</button>
|
placeholder="Enter Password"
|
||||||
{#if controlsEnabled}
|
bind:value={$state.password}
|
||||||
<span class="with-sep" transition:fade={{ duration: 100 }}>or sign up with</span>
|
/>
|
||||||
<div class="oauth-btns" transition:fade={{ duration: 100 }}>
|
</fieldset>
|
||||||
{#each objectKeys($state.controls).filter((p) => $state.controls[p]) as provider (provider)}
|
</div>
|
||||||
<button class="oauth" transition:fade={{ duration: 100 }} animate:flip={{ duration: 250 }}>
|
<button class="sign-up">Sign Up</button>
|
||||||
<div class="inner">
|
{#if controlsEnabled}
|
||||||
<span class="web-icon-{provider.toLowerCase()}" />
|
<span class="with-sep" transition:fade={{ duration: 100 }}>or sign up with</span>
|
||||||
<span>{provider}</span>
|
<div class="oauth-btns" transition:fade={{ duration: 100 }}>
|
||||||
</div>
|
{#each objectKeys($state.controls).filter((p) => $state.controls[p]) as provider (provider)}
|
||||||
</button>
|
<button
|
||||||
{/each}
|
class="oauth"
|
||||||
</div>
|
transition:fade={{ duration: 100 }}
|
||||||
{/if}
|
animate:flip={{ duration: 250 }}
|
||||||
|
>
|
||||||
|
<div class="inner">
|
||||||
|
<span class="web-icon-{provider.toLowerCase()}" />
|
||||||
|
<span>{provider}</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.inner-phone {
|
.inner-phone {
|
||||||
padding-block: 3rem;
|
padding-block: 3rem;
|
||||||
padding-inline: 1rem;
|
padding-inline: 1rem;
|
||||||
|
|
||||||
color: rgba(67, 67, 71, 1);
|
color: rgba(67, 67, 71, 1);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: #434347;
|
color: #434347;
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 22px; /* 137.5% */
|
line-height: 22px; /* 137.5% */
|
||||||
letter-spacing: -0.224px;
|
letter-spacing: -0.224px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 20px; /* 142.857% */
|
line-height: 20px; /* 142.857% */
|
||||||
letter-spacing: -0.196px;
|
letter-spacing: -0.196px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputs {
|
.inputs {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
margin-block-start: 1.5rem;
|
margin-block-start: 1.5rem;
|
||||||
|
|
||||||
fieldset {
|
fieldset {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.3125rem;
|
gap: 0.3125rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
color: var(--color-greyscale-700, #56565c);
|
color: var(--color-greyscale-700, #56565c);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 16px; /* 133.333% */
|
line-height: 16px; /* 133.333% */
|
||||||
letter-spacing: -0.168px;
|
letter-spacing: -0.168px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
all: unset;
|
all: unset;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid #d8d8db;
|
border: 1px solid #d8d8db;
|
||||||
|
|
||||||
color: #434347;
|
color: #434347;
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 16px; /* 133.333% */
|
line-height: 16px; /* 133.333% */
|
||||||
letter-spacing: -0.168px;
|
letter-spacing: -0.168px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sign-up {
|
.sign-up {
|
||||||
padding: 0.375rem 0.75rem;
|
padding: 0.375rem 0.75rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-block-start: 1.25rem;
|
margin-block-start: 1.25rem;
|
||||||
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
background: var(--appwrite-purple, #7c67fe);
|
background: var(--appwrite-purple, #7c67fe);
|
||||||
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.06);
|
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
color: var(--color-bw-white, #fff);
|
color: var(--color-bw-white, #fff);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
/* Responsive/SubBody-500 */
|
/* Responsive/SubBody-500 */
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 22px; /* 157.143% */
|
line-height: 22px; /* 157.143% */
|
||||||
letter-spacing: -0.07px;
|
letter-spacing: -0.07px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.with-sep {
|
.with-sep {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.25rem; /* 166.667% */
|
line-height: 1.25rem; /* 166.667% */
|
||||||
letter-spacing: -0.0105rem;
|
letter-spacing: -0.0105rem;
|
||||||
color: hsl(var(--web-color-greyscale-500));
|
color: hsl(var(--web-color-greyscale-500));
|
||||||
|
|
||||||
margin-block-start: 0.75rem;
|
margin-block-start: 0.75rem;
|
||||||
|
|
||||||
&::before,
|
&::before,
|
||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: '';
|
||||||
height: 1px;
|
height: 1px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
background-color: hsl(var(--web-color-greyscale-200));
|
background-color: hsl(var(--web-color-greyscale-200));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.oauth-btns {
|
.oauth-btns {
|
||||||
--gap: 0.5rem;
|
--gap: 0.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: var(--gap);
|
gap: var(--gap);
|
||||||
margin-block-start: 0.75rem;
|
margin-block-start: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.oauth {
|
.oauth {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
border: 1px solid #d9d9d9;
|
border: 1px solid #d9d9d9;
|
||||||
color: hsl(var(--web-color-greyscale-750));
|
color: hsl(var(--web-color-greyscale-750));
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
/* Responsive/Caption-500 */
|
/* Responsive/Caption-500 */
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 1.375rem; /* 157.143% */
|
line-height: 1.375rem; /* 157.143% */
|
||||||
letter-spacing: -0.01575rem;
|
letter-spacing: -0.01575rem;
|
||||||
|
|
||||||
flex: 1 1 calc(50% - var(--gap));
|
flex: 1 1 calc(50% - var(--gap));
|
||||||
padding-block: 0.375rem;
|
padding-block: 0.375rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 2.125rem;
|
height: 2.125rem;
|
||||||
|
|
||||||
.inner {
|
.inner {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
transform: translate(-50%, -50%) scale(var(--inverse-sx, 1), var(--inverse-sy, 1));
|
transform: translate(-50%, -50%) scale(var(--inverse-sx, 1), var(--inverse-sy, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,54 +1,54 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { slide } from 'svelte/transition';
|
import { slide } from 'svelte/transition';
|
||||||
import { databasesController } from '.';
|
import { databasesController } from '.';
|
||||||
import { flip } from '$lib/utils/flip';
|
import { flip } from '$lib/utils/flip';
|
||||||
|
|
||||||
const { state } = databasesController;
|
const { state } = databasesController;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="pseudo-table">
|
<div class="pseudo-table">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<span class="web-eyebrow">Document ID</span>
|
<span class="web-eyebrow">Document ID</span>
|
||||||
<span class="web-eyebrow">Task</span>
|
<span class="web-eyebrow">Task</span>
|
||||||
</div>
|
</div>
|
||||||
{#each $state.tasks.slice(0, $state.tableSlice) as task (task.id)}
|
{#each $state.tasks.slice(0, $state.tableSlice) as task (task.id)}
|
||||||
<div class="row" transition:slide={{ duration: 150 }} animate:flip={{ duration: 150 }}>
|
<div class="row" transition:slide={{ duration: 150 }} animate:flip={{ duration: 150 }}>
|
||||||
<div class="copy-button">
|
<div class="copy-button">
|
||||||
<span class="web-icon-copy" />
|
<span class="web-icon-copy" />
|
||||||
<span>{task.id}</span>
|
<span>{task.id}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="truncated">{task.title}</span>
|
<span class="truncated">{task.title}</span>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.copy-button {
|
.copy-button {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0.25rem 0.5rem;
|
padding: 0.25rem 0.5rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.375rem;
|
gap: 0.375rem;
|
||||||
|
|
||||||
border-radius: 62.4375rem;
|
border-radius: 62.4375rem;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
background: rgba(255, 255, 255, 0.04);
|
background: rgba(255, 255, 255, 0.04);
|
||||||
backdrop-filter: blur(2.6666667461395264px);
|
backdrop-filter: blur(2.6666667461395264px);
|
||||||
|
|
||||||
[class*='icon-'] {
|
[class*='icon-'] {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
color: hsl(var(--web-color-greyscale-600));
|
color: hsl(var(--web-color-greyscale-600));
|
||||||
}
|
}
|
||||||
|
|
||||||
span:not([class*='icon-']) {
|
span:not([class*='icon-']) {
|
||||||
color: var(--greyscale-400, #adadb1);
|
color: var(--greyscale-400, #adadb1);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.25rem; /* 142.857% */
|
line-height: 1.25rem; /* 142.857% */
|
||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
||||||
|
|
||||||
let content = `
|
let content = `
|
||||||
const result = databases.createDocument(
|
const result = databases.createDocument(
|
||||||
'Your-tasks',
|
'Your-tasks',
|
||||||
tasks,
|
tasks,
|
||||||
|
|||||||
@@ -7,88 +7,88 @@ import { createResettable } from '$lib/utils/resettable';
|
|||||||
import { getElSelector } from '../Products.svelte';
|
import { getElSelector } from '../Products.svelte';
|
||||||
|
|
||||||
type Task = {
|
type Task = {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
tasks: Task[];
|
tasks: Task[];
|
||||||
tableSlice: number;
|
tableSlice: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const state = createResettable<State>({
|
const state = createResettable<State>({
|
||||||
tasks: [
|
tasks: [
|
||||||
{
|
{
|
||||||
id: '3397fecdedb13397fecdedb1',
|
id: '3397fecdedb13397fecdedb1',
|
||||||
title: 'Research user needs',
|
title: 'Research user needs',
|
||||||
checked: true
|
checked: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
tableSlice: 1
|
tableSlice: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
const execute = async () => {
|
const execute = async () => {
|
||||||
const phone = getElSelector('phone');
|
const phone = getElSelector('phone');
|
||||||
const box = getElSelector('box');
|
const box = getElSelector('box');
|
||||||
const code = getElSelector('code');
|
const code = getElSelector('code');
|
||||||
const { update } = state.reset();
|
const { update } = state.reset();
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
safeAnimate(phone, { x: 390, y: 0 }, { duration: 0.5 })?.finished,
|
safeAnimate(phone, { x: 390, y: 0 }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(box, { x: 0, y: 32, opacity: 1 }, { duration: 0.5 })?.finished,
|
safeAnimate(box, { x: 0, y: 32, opacity: 1 }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(code, { x: 80, y: 320, opacity: 1 }, { duration: 0.5 })?.finished
|
safeAnimate(code, { x: 80, y: 320, opacity: 1 }, { duration: 0.5 })?.finished
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
update((p) => ({
|
update((p) => ({
|
||||||
...p,
|
...p,
|
||||||
tasks: [
|
tasks: [
|
||||||
...p.tasks,
|
...p.tasks,
|
||||||
{
|
{
|
||||||
id: '3397fecdedb13397fecdedb2',
|
id: '3397fecdedb13397fecdedb2',
|
||||||
title: 'Create wireframes',
|
title: 'Create wireframes',
|
||||||
checked: false
|
checked: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}));
|
}));
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
update((p) => ({
|
update((p) => ({
|
||||||
...p,
|
...p,
|
||||||
tableSlice: p.tableSlice + 1
|
tableSlice: p.tableSlice + 1
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
update((p) => ({
|
update((p) => ({
|
||||||
...p,
|
...p,
|
||||||
tasks: [
|
tasks: [
|
||||||
...p.tasks,
|
...p.tasks,
|
||||||
{
|
{
|
||||||
id: '3397fecdedb13397fecdedb3',
|
id: '3397fecdedb13397fecdedb3',
|
||||||
title: 'Create visual design',
|
title: 'Create visual design',
|
||||||
checked: false
|
checked: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
update((p) => ({
|
update((p) => ({
|
||||||
...p,
|
...p,
|
||||||
tableSlice: p.tableSlice + 1
|
tableSlice: p.tableSlice + 1
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const databasesController = {
|
export const databasesController = {
|
||||||
execute,
|
execute,
|
||||||
state
|
state
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Databases = {
|
export const Databases = {
|
||||||
Phone,
|
Phone,
|
||||||
Box,
|
Box,
|
||||||
Code
|
Code
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,127 +1,127 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
import { databasesController } from '.';
|
import { databasesController } from '.';
|
||||||
import TaskCheckbox from '../TaskCheckbox.svelte';
|
import TaskCheckbox from '../TaskCheckbox.svelte';
|
||||||
|
|
||||||
const { state } = databasesController;
|
const { state } = databasesController;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div data-theme-ignore class="inner-phone theme-light">
|
<div data-theme-ignore class="inner-phone light">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<p class="title">Your tasks</p>
|
<p class="title">Your tasks</p>
|
||||||
<span class="icon-menu" aria-label="menu" />
|
<span class="icon-menu" aria-label="menu" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="date">Today</div>
|
<div class="date">Today</div>
|
||||||
<div class="tasks">
|
<div class="tasks">
|
||||||
{#each $state.tasks as task (task.id)}
|
{#each $state.tasks as task (task.id)}
|
||||||
<div class="task" data-checked={task.checked ? '' : undefined} in:fly={{ x: -16 }}>
|
<div class="task" data-checked={task.checked ? '' : undefined} in:fly={{ x: -16 }}>
|
||||||
<TaskCheckbox bind:checked={task.checked} />
|
<TaskCheckbox bind:checked={task.checked} />
|
||||||
<span class="title">{task.title}</span>
|
<span class="title">{task.title}</span>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="add-btn">
|
<button class="add-btn">
|
||||||
<span class="web-icon-plus" />
|
<span class="web-icon-plus" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.inner-phone {
|
.inner-phone {
|
||||||
padding-block: 3rem;
|
padding-block: 3rem;
|
||||||
padding-inline: 1rem;
|
padding-inline: 1rem;
|
||||||
|
|
||||||
color: rgba(67, 67, 71, 1);
|
color: rgba(67, 67, 71, 1);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: var(--color-greyscale-800, #2d2d31);
|
color: var(--color-greyscale-800, #2d2d31);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 1.375rem; /* 137.5% */
|
line-height: 1.375rem; /* 137.5% */
|
||||||
letter-spacing: -0.014rem;
|
letter-spacing: -0.014rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
[class*='icon-'] {
|
[class*='icon-'] {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
color: hsl(var(--web-color-greyscale-500));
|
color: hsl(var(--web-color-greyscale-500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
margin-block-start: 3rem;
|
margin-block-start: 3rem;
|
||||||
|
|
||||||
color: hsl(var(--web-color-greyscale-600));
|
color: hsl(var(--web-color-greyscale-600));
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 1.25rem; /* 166.667% */
|
line-height: 1.25rem; /* 166.667% */
|
||||||
}
|
}
|
||||||
|
|
||||||
.tasks {
|
.tasks {
|
||||||
margin-block-start: 0.5rem;
|
margin-block-start: 0.5rem;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|
||||||
.task {
|
.task {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
border: 1px solid hsl(var(--web-color-greyscale-50));
|
border: 1px solid hsl(var(--web-color-greyscale-50));
|
||||||
background: hsl(var(--web-color-white));
|
background: hsl(var(--web-color-white));
|
||||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||||
|
|
||||||
padding-block: 0.55rem;
|
padding-block: 0.55rem;
|
||||||
padding-inline: 0.88rem;
|
padding-inline: 0.88rem;
|
||||||
|
|
||||||
/* Responsive/SubBody-400 */
|
/* Responsive/SubBody-400 */
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.375rem; /* 157.143% */
|
line-height: 1.375rem; /* 157.143% */
|
||||||
letter-spacing: -0.00394rem;
|
letter-spacing: -0.00394rem;
|
||||||
|
|
||||||
transition: opacity 200ms ease;
|
transition: opacity 200ms ease;
|
||||||
|
|
||||||
&[data-checked] {
|
&[data-checked] {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-btn {
|
.add-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 1rem;
|
right: 1rem;
|
||||||
bottom: 2.5rem;
|
bottom: 2.5rem;
|
||||||
|
|
||||||
width: 2.5rem;
|
width: 2.5rem;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.12);
|
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.12);
|
||||||
background-color: rgba(124, 103, 254, 1);
|
background-color: rgba(124, 103, 254, 1);
|
||||||
color: rgba(237, 237, 240, 1);
|
color: rgba(237, 237, 240, 1);
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { portal } from '$lib/actions';
|
import { portal } from '$lib/actions';
|
||||||
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { functionsController } from '.';
|
import { functionsController } from '.';
|
||||||
|
|
||||||
let content = `
|
let content = `
|
||||||
const userId = req.headers['user-id'];
|
const userId = req.headers['user-id'];
|
||||||
|
|
||||||
if (req.path === '/subscribe') {
|
if (req.path === '/subscribe') {
|
||||||
@@ -18,39 +18,39 @@ if (req.path === '/webhook') {
|
|||||||
|
|
||||||
return res.json({ success: true });`.trim();
|
return res.json({ success: true });`.trim();
|
||||||
|
|
||||||
const { state } = functionsController;
|
const { state } = functionsController;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Code {content} />
|
<Code {content} />
|
||||||
|
|
||||||
<div use:portal={{ target: '#code-bottom' }} class="bottom">
|
<div use:portal={{ target: '#code-bottom' }} class="bottom">
|
||||||
{#if $state.submit !== 'idle'}
|
{#if $state.submit !== 'idle'}
|
||||||
<span class="web-icon-github" in:fade />
|
<span class="web-icon-github" in:fade />
|
||||||
{/if}
|
{/if}
|
||||||
{#if $state.submit === 'loading'}
|
{#if $state.submit === 'loading'}
|
||||||
<span in:fade>Pushing to GitHub...</span>
|
<span in:fade>Pushing to GitHub...</span>
|
||||||
<div class="loader is-small" in:fade />
|
<div class="loader is-small" in:fade />
|
||||||
{:else if $state.submit === 'success'}
|
{:else if $state.submit === 'success'}
|
||||||
<span>Deployed to Appwrite Cloud</span>
|
<span>Deployed to Appwrite Cloud</span>
|
||||||
<span class="web-icon-check" />
|
<span class="web-icon-check" />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.bottom {
|
.bottom {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
padding-inline: 1rem;
|
padding-inline: 1rem;
|
||||||
|
|
||||||
color: var(--color-bw-white, #fff);
|
color: var(--color-bw-white, #fff);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 150%; /* 1.3125rem */
|
line-height: 150%; /* 1.3125rem */
|
||||||
letter-spacing: -0.00875rem;
|
letter-spacing: -0.00875rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -6,53 +6,53 @@ import { createResettable } from '$lib/utils/resettable';
|
|||||||
import { getElSelector } from '../Products.svelte';
|
import { getElSelector } from '../Products.svelte';
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
submit: 'idle' | 'loading' | 'success';
|
submit: 'idle' | 'loading' | 'success';
|
||||||
};
|
};
|
||||||
|
|
||||||
const state = createResettable<State>({
|
const state = createResettable<State>({
|
||||||
submit: 'idle'
|
submit: 'idle'
|
||||||
});
|
});
|
||||||
|
|
||||||
const execute = async () => {
|
const execute = async () => {
|
||||||
const phone = getElSelector('phone');
|
const phone = getElSelector('phone');
|
||||||
const box = getElSelector('box');
|
const box = getElSelector('box');
|
||||||
const code = getElSelector('code');
|
const code = getElSelector('code');
|
||||||
|
|
||||||
const { update } = state.reset();
|
const { update } = state.reset();
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
safeAnimate(phone, { x: 430, y: 0, width: '275px' }, { duration: 0.5 })?.finished,
|
safeAnimate(phone, { x: 430, y: 0, width: '275px' }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(code, { x: 0, y: 200, opacity: 0 }, { duration: 0.5 })?.finished,
|
safeAnimate(code, { x: 0, y: 200, opacity: 0 }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(box, { opacity: 0 }, { duration: 0.5 })?.finished
|
safeAnimate(box, { opacity: 0 }, { duration: 0.5 })?.finished
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
await safeAnimate(code, { zIndex: 0 }, { duration: 0 })?.finished;
|
await safeAnimate(code, { zIndex: 0 }, { duration: 0 })?.finished;
|
||||||
await safeAnimate(code, { y: [200 - 16, 200], opacity: 1 }, { duration: 0.5 })?.finished;
|
await safeAnimate(code, { y: [200 - 16, 200], opacity: 1 }, { duration: 0.5 })?.finished;
|
||||||
|
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
update((p) => ({
|
update((p) => ({
|
||||||
...p,
|
...p,
|
||||||
submit: 'loading'
|
submit: 'loading'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await sleep(1500);
|
await sleep(1500);
|
||||||
|
|
||||||
update((p) => ({
|
update((p) => ({
|
||||||
...p,
|
...p,
|
||||||
submit: 'success'
|
submit: 'success'
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const functionsController = {
|
export const functionsController = {
|
||||||
execute,
|
execute,
|
||||||
state
|
state
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Functions = {
|
export const Functions = {
|
||||||
Phone,
|
Phone,
|
||||||
|
|
||||||
Code
|
Code
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,325 +1,325 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { flip } from '$lib/utils/flip';
|
import { flip } from '$lib/utils/flip';
|
||||||
import { crossfade, scale, slide } from 'svelte/transition';
|
import { crossfade, scale, slide } from 'svelte/transition';
|
||||||
import { functionsController } from '.';
|
import { functionsController } from '.';
|
||||||
|
|
||||||
const { state } = functionsController;
|
const { state } = functionsController;
|
||||||
|
|
||||||
type Method = {
|
type Method = {
|
||||||
icon: string;
|
icon: string;
|
||||||
label: string;
|
label: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
$: methods = [
|
$: methods = [
|
||||||
$state.submit === 'success' && {
|
$state.submit === 'success' && {
|
||||||
icon: '/images/animations/stripe.png',
|
icon: '/images/animations/stripe.png',
|
||||||
label: 'Stripe'
|
label: 'Stripe'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: '/images/animations/credit-card.svg',
|
icon: '/images/animations/credit-card.svg',
|
||||||
label: 'Card'
|
label: 'Card'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: '/images/animations/paypal.svg',
|
icon: '/images/animations/paypal.svg',
|
||||||
label: 'PayPal'
|
label: 'PayPal'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: '/images/animations/apple.svg',
|
icon: '/images/animations/apple.svg',
|
||||||
label: 'Apple'
|
label: 'Apple'
|
||||||
}
|
}
|
||||||
].filter(Boolean) as Method[];
|
].filter(Boolean) as Method[];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div data-theme-ignore class="inner-phone theme-light">
|
<div data-theme-ignore class="inner-phone light">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<p class="title">Upgrade plan</p>
|
<p class="title">Upgrade plan</p>
|
||||||
<span class="icon-menu" aria-label="menu" />
|
<span class="icon-menu" aria-label="menu" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="plan">
|
<div class="plan">
|
||||||
<p class="title">Premium plan</p>
|
<p class="title">Premium plan</p>
|
||||||
<div class="subscription">
|
<div class="subscription">
|
||||||
<p class="price">$20</p>
|
<p class="price">$20</p>
|
||||||
<p class="period">/month</p>
|
<p class="period">/month</p>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Premium plan</li>
|
<li>Premium plan</li>
|
||||||
<li>Premium plan</li>
|
<li>Premium plan</li>
|
||||||
<li>Premium plan</li>
|
<li>Premium plan</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="methods">
|
<ul class="methods">
|
||||||
{#each methods as method, i (method.label)}
|
{#each methods as method, i (method.label)}
|
||||||
<li
|
<li
|
||||||
in:scale={{ delay: 150 }}
|
in:scale={{ delay: 150 }}
|
||||||
animate:flip={{ duration: 500 }}
|
animate:flip={{ duration: 500 }}
|
||||||
data-active={i == 0 ? '' : undefined}
|
data-active={i == 0 ? '' : undefined}
|
||||||
>
|
>
|
||||||
<img src={method.icon} alt="" />
|
<img src={method.icon} alt="" />
|
||||||
<p>{method.label}</p>
|
<p>{method.label}</p>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{#if $state.submit !== 'success'}
|
{#if $state.submit !== 'success'}
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<p>Card information</p>
|
<p>Card information</p>
|
||||||
<div class="bordered">
|
<div class="bordered">
|
||||||
<div>
|
<div>
|
||||||
<p>placeholder</p>
|
<p>placeholder</p>
|
||||||
<img src="/images/animations/visa.png" alt="" />
|
<img src="/images/animations/visa.png" alt="" />
|
||||||
<img src="/images/animations/mastercard.png" alt="" />
|
<img src="/images/animations/mastercard.png" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>MM/YY</p>
|
<p>MM/YY</p>
|
||||||
<p>CVV</p>
|
<p>CVV</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button>
|
<button>
|
||||||
Pay $20.00
|
Pay $20.00
|
||||||
{#if $state.submit === 'success'}
|
{#if $state.submit === 'success'}
|
||||||
<span in:slide={{ axis: 'x' }}>on Stripe</span>
|
<span in:slide={{ axis: 'x' }}>on Stripe</span>
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.inner-phone {
|
.inner-phone {
|
||||||
padding-block: 3rem 1.5rem;
|
padding-block: 3rem 1.5rem;
|
||||||
padding-inline: 1rem;
|
padding-inline: 1rem;
|
||||||
|
|
||||||
color: rgba(67, 67, 71, 1);
|
color: rgba(67, 67, 71, 1);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: #434347;
|
color: #434347;
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 1.375rem; /* 137.5% */
|
line-height: 1.375rem; /* 137.5% */
|
||||||
letter-spacing: -0.014rem;
|
letter-spacing: -0.014rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
[class*='icon-'] {
|
[class*='icon-'] {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
color: hsl(var(--web-color-greyscale-500));
|
color: hsl(var(--web-color-greyscale-500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.plan {
|
.plan {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0.75rem 1rem;
|
padding: 0.75rem 1rem;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
background: rgba(237, 237, 240, 0.5);
|
background: rgba(237, 237, 240, 0.5);
|
||||||
|
|
||||||
margin-block-start: 1rem;
|
margin-block-start: 1rem;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: var(--color-greyscale-700, #56565c);
|
color: var(--color-greyscale-700, #56565c);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
line-height: 1.25rem; /* 166.667% */
|
line-height: 1.25rem; /* 166.667% */
|
||||||
}
|
}
|
||||||
|
|
||||||
.subscription {
|
.subscription {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
margin-block-start: 0.15rem;
|
margin-block-start: 0.15rem;
|
||||||
|
|
||||||
.price {
|
.price {
|
||||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 1.125rem;
|
font-size: 1.125rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
line-height: 1.25rem; /* 111.111% */
|
line-height: 1.25rem; /* 111.111% */
|
||||||
}
|
}
|
||||||
|
|
||||||
.period {
|
.period {
|
||||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.25rem;
|
line-height: 1.25rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.125rem;
|
gap: 0.125rem;
|
||||||
margin-block-start: 0.75rem;
|
margin-block-start: 0.75rem;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
color: var(--color-greyscale-500, #818186);
|
color: var(--color-greyscale-500, #818186);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.25rem; /* 166.667% */
|
line-height: 1.25rem; /* 166.667% */
|
||||||
|
|
||||||
padding-inline-start: 1.5rem;
|
padding-inline-start: 1.5rem;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
|
|
||||||
background-image: url('/images/animations/check-circle.svg');
|
background-image: url('/images/animations/check-circle.svg');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.methods {
|
.methods {
|
||||||
margin-block-start: 1.25rem;
|
margin-block-start: 1.25rem;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-inline: -1rem;
|
margin-inline: -1rem;
|
||||||
padding-inline: 1rem;
|
padding-inline: 1rem;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 5.5rem;
|
width: 5.5rem;
|
||||||
padding: 0.75rem 0.75rem 0.625rem 0.75rem;
|
padding: 0.75rem 0.75rem 0.625rem 0.75rem;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 0.125rem;
|
gap: 0.125rem;
|
||||||
|
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
border: 1px solid var(--greyscale-50, #ededf0);
|
border: 1px solid var(--greyscale-50, #ededf0);
|
||||||
|
|
||||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.25rem; /* 166.667% */
|
line-height: 1.25rem; /* 166.667% */
|
||||||
|
|
||||||
&[data-active] {
|
&[data-active] {
|
||||||
border-color: var(--appwrite-purple, #7c67fe);
|
border-color: var(--appwrite-purple, #7c67fe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.form {
|
.form {
|
||||||
margin-block-start: 1.25rem;
|
margin-block-start: 1.25rem;
|
||||||
|
|
||||||
> p {
|
> p {
|
||||||
color: var(--dark-neutrals-150, #373b4d);
|
color: var(--dark-neutrals-150, #373b4d);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 150%; /* 1.125rem */
|
line-height: 150%; /* 1.125rem */
|
||||||
}
|
}
|
||||||
|
|
||||||
.bordered {
|
.bordered {
|
||||||
margin-block-start: 0.25rem;
|
margin-block-start: 0.25rem;
|
||||||
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
border: 1px solid #ededf0;
|
border: 1px solid #ededf0;
|
||||||
background: var(--color-bw-white, #fff);
|
background: var(--color-bw-white, #fff);
|
||||||
|
|
||||||
> div:first-child {
|
> div:first-child {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
padding: 0.65rem 0.75rem;
|
padding: 0.65rem 0.75rem;
|
||||||
border-bottom: 1px solid #ededf0;
|
border-bottom: 1px solid #ededf0;
|
||||||
|
|
||||||
> :nth-child(2) {
|
> :nth-child(2) {
|
||||||
margin-inline-start: auto;
|
margin-inline-start: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> div:nth-child(2) {
|
> div:nth-child(2) {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
> p {
|
> p {
|
||||||
padding: 0.65rem 0.75rem;
|
padding: 0.65rem 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
> p:first-child {
|
> p:first-child {
|
||||||
flex-grow: 3;
|
flex-grow: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
> p:last-child {
|
> p:last-child {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
border-inline-start: 1px solid #ededf0;
|
border-inline-start: 1px solid #ededf0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
color: var(--light-neutrals-50, #c4c6d7);
|
color: var(--light-neutrals-50, #c4c6d7);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 150%; /* 1.125rem */
|
line-height: 150%; /* 1.125rem */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> button {
|
> button {
|
||||||
display: flex;
|
display: flex;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
background: var(--appwrite-purple, #7c67fe);
|
background: var(--appwrite-purple, #7c67fe);
|
||||||
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.06);
|
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
color: var(--color-bw-white, #fff);
|
color: var(--color-bw-white, #fff);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 1.375rem; /* 157.143% */
|
line-height: 1.375rem; /* 157.143% */
|
||||||
letter-spacing: -0.01225rem;
|
letter-spacing: -0.01225rem;
|
||||||
|
|
||||||
margin-block-start: auto;
|
margin-block-start: auto;
|
||||||
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div data-theme-ignore class="inner-phone theme-light">
|
<div data-theme-ignore class="inner-phone light">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<p class="title">Your tasks</p>
|
<p class="title">Your tasks</p>
|
||||||
<span class="icon-menu" aria-label="menu" />
|
<span class="icon-menu" aria-label="menu" />
|
||||||
|
|||||||
@@ -12,42 +12,42 @@ const executions = createResettable(0);
|
|||||||
const realtime = createResettable(0);
|
const realtime = createResettable(0);
|
||||||
|
|
||||||
const execute = async () => {
|
const execute = async () => {
|
||||||
const phone = getElSelector('phone');
|
const phone = getElSelector('phone');
|
||||||
const pd = getElSelector('pd');
|
const pd = getElSelector('pd');
|
||||||
|
|
||||||
const graphBox = getElSelector('graph-box');
|
const graphBox = getElSelector('graph-box');
|
||||||
|
|
||||||
const boxesAndStates = [
|
const boxesAndStates = [
|
||||||
{ box: getElSelector('post-auth'), state: authentication.reset() },
|
{ box: getElSelector('post-auth'), state: authentication.reset() },
|
||||||
{ box: getElSelector('post-storage'), state: storage.reset() },
|
{ box: getElSelector('post-storage'), state: storage.reset() },
|
||||||
{ box: getElSelector('post-bandwidth'), state: bandwidth.reset() },
|
{ box: getElSelector('post-bandwidth'), state: bandwidth.reset() },
|
||||||
{ box: getElSelector('post-functions'), state: executions.reset() },
|
{ box: getElSelector('post-functions'), state: executions.reset() },
|
||||||
{ box: getElSelector('post-databases'), state: databases.reset() },
|
{ box: getElSelector('post-databases'), state: databases.reset() },
|
||||||
{ box: getElSelector('post-realtime'), state: realtime.reset() },
|
{ box: getElSelector('post-realtime'), state: realtime.reset() },
|
||||||
{ box: getElSelector('post-requests'), state: requests.reset() }
|
{ box: getElSelector('post-requests'), state: requests.reset() }
|
||||||
];
|
];
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
safeAnimate(pd, { opacity: 0, y: -16 }, { duration: 0.5 })?.finished,
|
safeAnimate(pd, { opacity: 0, y: -16 }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(graphBox, { opacity: 0, visibility: 'hidden' }, { duration: 0.5 })?.finished,
|
safeAnimate(graphBox, { opacity: 0, visibility: 'hidden' }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(phone, { x: '-50%', width: '660px' }, { duration: 1, delay: 0.5 })?.finished
|
safeAnimate(phone, { x: '-50%', width: '660px' }, { duration: 1, delay: 0.5 })?.finished
|
||||||
]);
|
]);
|
||||||
|
|
||||||
boxesAndStates.forEach(({ box, state }, i) => {
|
boxesAndStates.forEach(({ box, state }, i) => {
|
||||||
safeAnimate(box, { opacity: 1, y: [1200, 0] }, { duration: 0.5, delay: i * 0.1 })?.finished;
|
safeAnimate(box, { opacity: 1, y: [1200, 0] }, { duration: 0.5, delay: i * 0.1 })?.finished;
|
||||||
animate(state.set, { duration: 2, delay: (i + 1) * 0.25 });
|
animate(state.set, { duration: 2, delay: (i + 1) * 0.25 });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const postController = {
|
export const postController = {
|
||||||
execute,
|
execute,
|
||||||
state: {
|
state: {
|
||||||
requests,
|
requests,
|
||||||
databases,
|
databases,
|
||||||
authentication,
|
authentication,
|
||||||
storage,
|
storage,
|
||||||
bandwidth,
|
bandwidth,
|
||||||
executions,
|
executions,
|
||||||
realtime
|
realtime
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,297 +1,300 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { toScale } from '$lib/utils/toScale';
|
import { toScale } from '$lib/utils/toScale';
|
||||||
import { postController } from '.';
|
import { postController } from '.';
|
||||||
import { elId } from '../Products.svelte';
|
import { elId } from '../Products.svelte';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
state: { authentication, bandwidth, databases, executions, requests, storage, realtime }
|
state: { authentication, bandwidth, databases, executions, requests, storage, realtime }
|
||||||
} = postController;
|
} = postController;
|
||||||
|
|
||||||
const formatK = (num: number) => {
|
const formatK = (num: number) => {
|
||||||
if (num > 999) {
|
if (num > 999) {
|
||||||
return `${(num / 1000).toFixed(1)}K`;
|
return `${(num / 1000).toFixed(1)}K`;
|
||||||
}
|
}
|
||||||
return Math.floor(num);
|
return Math.floor(num);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="gradient-box auth" id="post-auth-{$elId}">
|
<div class="gradient-box auth" id="post-auth-{$elId}">
|
||||||
<div class="u-flex u-cross-center u-gap-8">
|
<div class="flex u-cross-center gap-2">
|
||||||
<p class="icon-user-group" />
|
<p class="icon-user-group" />
|
||||||
<p class="f-eyebrow">Authentication</p>
|
<p class="f-eyebrow">Authentication</p>
|
||||||
</div>
|
</div>
|
||||||
<p class="f-display mbs-16">{formatK(toScale($authentication, [0, 1], [0, 4000]))}</p>
|
<p class="f-display mbs-16">{formatK(toScale($authentication, [0, 1], [0, 4000]))}</p>
|
||||||
<div class="u-flex u-cross-center justify-between mbs-4">
|
<div class="flex u-cross-center justify-between mbs-4">
|
||||||
<p class="f-sub">Users</p>
|
<p class="f-sub">Users</p>
|
||||||
<p class="f-idk">Sessions: 20K</p>
|
<p class="f-idk">Sessions: 20K</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gradient-box storage" id="post-storage-{$elId}">
|
<div class="gradient-box storage" id="post-storage-{$elId}">
|
||||||
<div class="u-flex u-cross-center u-gap-8">
|
<div class="flex u-cross-center gap-2">
|
||||||
<p class="icon-folder" />
|
<p class="icon-folder" />
|
||||||
<p class="f-eyebrow">Storage</p>
|
<p class="f-eyebrow">Storage</p>
|
||||||
</div>
|
</div>
|
||||||
<p class="f-display mbs-16">
|
<p class="f-display mbs-16">
|
||||||
{toScale($storage, [0, 1], [0, 8]).toFixed(1)} <span class="f-tiny-display">GB</span>
|
{toScale($storage, [0, 1], [0, 8]).toFixed(1)} <span class="f-tiny-display">GB</span>
|
||||||
</p>
|
</p>
|
||||||
<div class="u-flex u-cross-center justify-between mbs-4">
|
<div class="flex u-cross-center justify-between mbs-4">
|
||||||
<p class="f-sub">Storage</p>
|
<p class="f-sub">Storage</p>
|
||||||
<p class="f-idk">Buckets: 44</p>
|
<p class="f-idk">Buckets: 44</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gradient-box bandwidth" id="post-bandwidth-{$elId}">
|
<div class="gradient-box bandwidth" id="post-bandwidth-{$elId}">
|
||||||
<p class="f-display">
|
<p class="f-display">
|
||||||
{toScale($bandwidth, [0, 1], [0, 1.2]).toFixed(2)} <span class="f-tiny-display">GB</span>
|
{toScale($bandwidth, [0, 1], [0, 1.2]).toFixed(2)} <span class="f-tiny-display">GB</span>
|
||||||
</p>
|
</p>
|
||||||
<p class="f-sub">Bandwidth</p>
|
<p class="f-sub">Bandwidth</p>
|
||||||
<img class="mbs-16" src="./images/animations/bandwidth-graph.svg" alt="" />
|
<img class="mbs-16" src="./images/animations/bandwidth-graph.svg" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gradient-box functions" id="post-functions-{$elId}">
|
<div class="gradient-box functions" id="post-functions-{$elId}">
|
||||||
<div class="u-flex u-cross-center u-gap-8">
|
<div class="flex u-cross-center gap-2">
|
||||||
<p class="icon-lightning-bolt" />
|
<p class="icon-lightning-bolt" />
|
||||||
<p class="f-eyebrow">Functions</p>
|
<p class="f-eyebrow">Functions</p>
|
||||||
</div>
|
</div>
|
||||||
<p class="f-display mbs-16">{toScale($executions, [0, 1], [0, 846]).toFixed(0)}</p>
|
<p class="f-display mbs-16">{toScale($executions, [0, 1], [0, 846]).toFixed(0)}</p>
|
||||||
<div class="u-flex u-cross-center justify-between mbs-4">
|
<div class="flex u-cross-center justify-between mbs-4">
|
||||||
<p class="f-sub">Executions</p>
|
<p class="f-sub">Executions</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gradient-box databases" id="post-databases-{$elId}">
|
<div class="gradient-box databases" id="post-databases-{$elId}">
|
||||||
<div class="u-flex u-cross-center u-gap-8">
|
<div class="flex u-cross-center gap-2">
|
||||||
<p class="icon-database" />
|
<p class="icon-database" />
|
||||||
<p class="f-eyebrow">Databases</p>
|
<p class="f-eyebrow">Databases</p>
|
||||||
</div>
|
</div>
|
||||||
<p class="f-display mbs-16">{toScale($databases, [0, 1], [0, 8]).toFixed(0)}</p>
|
<p class="f-display mbs-16">{toScale($databases, [0, 1], [0, 8]).toFixed(0)}</p>
|
||||||
<div class="u-flex u-cross-center justify-between mbs-4">
|
<div class="flex u-cross-center justify-between mbs-4">
|
||||||
<p class="f-sub">Databases</p>
|
<p class="f-sub">Databases</p>
|
||||||
<p class="f-idk">Documents: 20</p>
|
<p class="f-idk">Documents: 20</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gradient-box requests" id="post-requests-{$elId}">
|
<div class="gradient-box requests" id="post-requests-{$elId}">
|
||||||
<p class="f-display">{formatK(toScale($requests, [0, 1], [0, 6849]))}</p>
|
<p class="f-display">{formatK(toScale($requests, [0, 1], [0, 6849]))}</p>
|
||||||
<p class="f-sub">Requests</p>
|
<p class="f-sub">Requests</p>
|
||||||
<img class="mbs-16" src="./images/animations/requests-graph.svg" alt="" />
|
<img class="mbs-16" src="./images/animations/requests-graph.svg" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gradient-box realtime" id="post-realtime-{$elId}">
|
<div class="gradient-box realtime" id="post-realtime-{$elId}">
|
||||||
<p class="f-display">{formatK(toScale($realtime, [0, 1], [0, 100000]))}</p>
|
<p class="f-display">{formatK(toScale($realtime, [0, 1], [0, 100000]))}</p>
|
||||||
<p class="f-sub">Realtime connections</p>
|
<p class="f-sub">Realtime connections</p>
|
||||||
<img class="mbs-16" src="./images/animations/realtime-graph.svg" alt="" />
|
<img class="mbs-16" src="./images/animations/realtime-graph.svg" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gradient-overlay u-flex u-flex-vertical">
|
<div class="gradient-overlay flex u-flex-vertical">
|
||||||
<h3>See your products grow</h3>
|
<h3>See your products grow</h3>
|
||||||
<p>
|
<p>
|
||||||
Keep track of your projects progress on the Appwrite Console and see them grow into products
|
Keep track of your projects progress on the Appwrite Console and see them grow into products
|
||||||
users love and use every day.
|
users love and use every day.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@use '$scss/abstract/mixins/border-gradient' as gradients;
|
@use '$scss/abstract/mixins/border-gradient' as gradients;
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
.f-eyebrow {
|
.f-eyebrow {
|
||||||
color: #adadb0;
|
color: #adadb0;
|
||||||
/* Eyebrow headings/level 3 */
|
/* Eyebrow headings/level 3 */
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 150%; /* 1.125rem */
|
line-height: 150%; /* 1.125rem */
|
||||||
letter-spacing: 0.09rem;
|
letter-spacing: 0.09rem;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.f-display {
|
.f-display {
|
||||||
color: #ededf0;
|
color: #ededf0;
|
||||||
font-family: Aeonik Pro;
|
font-family: Aeonik Pro;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 2.25rem; /* 112.5% */
|
line-height: 2.25rem; /* 112.5% */
|
||||||
}
|
}
|
||||||
|
|
||||||
.f-tiny-display {
|
.f-tiny-display {
|
||||||
color: var(--greyscale-50, #ededf0);
|
color: var(--greyscale-50, #ededf0);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 1rem; /* 114.286% */
|
line-height: 1rem; /* 114.286% */
|
||||||
}
|
}
|
||||||
|
|
||||||
.f-sub {
|
.f-sub {
|
||||||
color: #97979b;
|
color: #97979b;
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.125rem; /* 128.571% */
|
line-height: 1.125rem; /* 128.571% */
|
||||||
}
|
}
|
||||||
|
|
||||||
.f-idk {
|
.f-idk {
|
||||||
color: var(--primary, #e4e4e7);
|
color: var(--primary, #e4e4e7);
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 150%; /* 1.3125rem */
|
line-height: 150%; /* 1.3125rem */
|
||||||
opacity: 40%;
|
opacity: 40%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mbs-16 {
|
.mbs-16 {
|
||||||
margin-block-start: 1rem;
|
margin-block-start: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mbs-4 {
|
.mbs-4 {
|
||||||
margin-block-start: 0.25rem;
|
margin-block-start: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.justify-between {
|
.justify-between {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
.gradient-box {
|
.gradient-box {
|
||||||
@include gradients.border-gradient;
|
@include gradients.border-gradient;
|
||||||
--m-border-gradient-before: linear-gradient(
|
--m-border-gradient-before: linear-gradient(
|
||||||
180deg,
|
180deg,
|
||||||
rgba(255, 255, 255, 0.12) 0%,
|
rgba(255, 255, 255, 0.12) 0%,
|
||||||
rgba(255, 255, 255, 0) 125.11%
|
rgba(255, 255, 255, 0) 125.11%
|
||||||
);
|
);
|
||||||
--m-border-radius: 1rem;
|
--m-border-radius: 1rem;
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: var(--card, rgba(35, 35, 37, 0.9));
|
background: var(--card, rgba(35, 35, 37, 0.9));
|
||||||
box-shadow: 0px 0px 0px 0px rgba(0, 0, 0, 0.06), -2px 4px 9px 0px rgba(0, 0, 0, 0.06),
|
box-shadow:
|
||||||
-8px 15px 17px 0px rgba(0, 0, 0, 0.05), -19px 34px 23px 0px rgba(0, 0, 0, 0.03),
|
0px 0px 0px 0px rgba(0, 0, 0, 0.06),
|
||||||
-33px 60px 27px 0px rgba(0, 0, 0, 0.01), -52px 94px 30px 0px rgba(0, 0, 0, 0);
|
-2px 4px 9px 0px rgba(0, 0, 0, 0.06),
|
||||||
backdrop-filter: blur(8px);
|
-8px 15px 17px 0px rgba(0, 0, 0, 0.05),
|
||||||
|
-19px 34px 23px 0px rgba(0, 0, 0, 0.03),
|
||||||
|
-33px 60px 27px 0px rgba(0, 0, 0, 0.01),
|
||||||
|
-52px 94px 30px 0px rgba(0, 0, 0, 0);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
|
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
|
|
||||||
min-width: 20rem;
|
min-width: 20rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.gradient-overlay {
|
.gradient-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
bottom: -7.5rem;
|
bottom: -7.5rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 30rem;
|
height: 30rem;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
|
|
||||||
padding-block-start: 15rem;
|
padding-block-start: 15rem;
|
||||||
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
animation: fadeIn 0.75s ease-in-out 1.5s forwards;
|
animation: fadeIn 0.75s ease-in-out 1.5s forwards;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
inset: 0;
|
inset: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
//background: #19191d; // old bg
|
//background: #19191d; // old bg
|
||||||
//filter: blur(125px); // break Safari
|
//filter: blur(125px); // break Safari
|
||||||
background: #19191dcc;
|
background: #19191dcc;
|
||||||
filter: blur(67px);
|
filter: blur(67px);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
h3 {
|
||||||
|
position: relative;
|
||||||
|
color: var(--primary, #e4e4e7);
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
h3 {
|
/* Desktop/Display */
|
||||||
position: relative;
|
font-family: Aeonik Pro;
|
||||||
color: var(--primary, #e4e4e7);
|
font-size: 4rem;
|
||||||
text-align: center;
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 4.25rem; /* 106.25% */
|
||||||
|
letter-spacing: -0.04rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* Desktop/Display */
|
p {
|
||||||
font-family: Aeonik Pro;
|
position: relative;
|
||||||
font-size: 4rem;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 4.25rem; /* 106.25% */
|
|
||||||
letter-spacing: -0.04rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
color: var(--secondary, #adadb0);
|
||||||
position: relative;
|
text-align: center;
|
||||||
|
|
||||||
color: var(--secondary, #adadb0);
|
/* Desktop/Description */
|
||||||
text-align: center;
|
font-family: Inter;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.75rem; /* 140% */
|
||||||
|
letter-spacing: -0.0175rem;
|
||||||
|
max-width: 40rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Desktop/Description */
|
// Specifics
|
||||||
font-family: Inter;
|
.auth {
|
||||||
font-size: 1.25rem;
|
opacity: 0;
|
||||||
font-style: normal;
|
left: 4rem;
|
||||||
font-weight: 500;
|
top: -11rem;
|
||||||
line-height: 1.75rem; /* 140% */
|
}
|
||||||
letter-spacing: -0.0175rem;
|
|
||||||
max-width: 40rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specifics
|
.storage {
|
||||||
.auth {
|
opacity: 0;
|
||||||
opacity: 0;
|
left: -10rem;
|
||||||
left: 4rem;
|
top: -2rem;
|
||||||
top: -11rem;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.storage {
|
.bandwidth {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
left: -10rem;
|
left: -4rem;
|
||||||
top: -2rem;
|
top: 11rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bandwidth {
|
.functions {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
left: -4rem;
|
left: -6rem;
|
||||||
top: 11rem;
|
top: 35rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.functions {
|
.databases {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
left: -6rem;
|
top: -13rem;
|
||||||
top: 35rem;
|
right: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.databases {
|
.requests {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
top: -13rem;
|
top: 17rem;
|
||||||
right: 10rem;
|
right: -18rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.requests {
|
.realtime {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
top: 17rem;
|
top: -1rem;
|
||||||
right: -18rem;
|
right: -7rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.realtime {
|
|
||||||
opacity: 0;
|
|
||||||
top: -1rem;
|
|
||||||
right: -7rem;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,39 +1,39 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { slide } from 'svelte/transition';
|
import { slide } from 'svelte/transition';
|
||||||
import { storageController } from '.';
|
import { storageController } from '.';
|
||||||
import { flip } from '$lib/utils/flip';
|
import { flip } from '$lib/utils/flip';
|
||||||
|
|
||||||
const { state } = storageController;
|
const { state } = storageController;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="pseudo-table">
|
<div class="pseudo-table">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<span class="web-eyebrow">Filename</span>
|
<span class="web-eyebrow">Filename</span>
|
||||||
<span class="web-eyebrow">Type</span>
|
<span class="web-eyebrow">Type</span>
|
||||||
<span class="web-eyebrow">Size</span>
|
<span class="web-eyebrow">Size</span>
|
||||||
</div>
|
</div>
|
||||||
{#each $state.files as file (file.src)}
|
{#each $state.files as file (file.src)}
|
||||||
<div class="row" in:slide={{ duration: 150 }} animate:flip={{ duration: 150 }}>
|
<div class="row" in:slide={{ duration: 150 }} animate:flip={{ duration: 150 }}>
|
||||||
<div class="img-wrapper">
|
<div class="img-wrapper">
|
||||||
<img src={file.src} alt="" />
|
<img src={file.src} alt="" />
|
||||||
<span>{file.filename}</span>
|
<span>{file.filename}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="truncated">{file.type}</span>
|
<span class="truncated">{file.type}</span>
|
||||||
<span class="truncated">{file.size}</span>
|
<span class="truncated">{file.size}</span>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.header,
|
.header,
|
||||||
.row {
|
.row {
|
||||||
grid-template-columns: 7rem 1fr 1fr !important;
|
grid-template-columns: 7rem 1fr 1fr !important;
|
||||||
gap: 1.5rem 3rem;
|
gap: 1.5rem 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-wrapper {
|
.img-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
||||||
|
|
||||||
let content = `
|
let content = `
|
||||||
const result = storage.createFile(
|
const result = storage.createFile(
|
||||||
'my-bucket',
|
'my-bucket',
|
||||||
ID.unique(),
|
ID.unique(),
|
||||||
|
|||||||
@@ -7,130 +7,131 @@ import { createResettable } from '$lib/utils/resettable';
|
|||||||
import { getElSelector } from '../Products.svelte';
|
import { getElSelector } from '../Products.svelte';
|
||||||
|
|
||||||
type File = {
|
type File = {
|
||||||
src: string;
|
src: string;
|
||||||
filename: string;
|
filename: string;
|
||||||
type: string;
|
type: string;
|
||||||
size: string;
|
size: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
files: File[];
|
files: File[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const state = createResettable<State>({
|
const state = createResettable<State>({
|
||||||
files: []
|
files: []
|
||||||
});
|
});
|
||||||
|
|
||||||
const execute = async () => {
|
const execute = async () => {
|
||||||
const phone = getElSelector('phone');
|
const phone = getElSelector('phone');
|
||||||
const box = getElSelector('box');
|
const box = getElSelector('box');
|
||||||
const code = getElSelector('code');
|
const code = getElSelector('code');
|
||||||
const overlay = getElSelector('overlay');
|
const overlay = getElSelector('overlay');
|
||||||
const drawer = getElSelector('drawer');
|
const drawer = getElSelector('drawer');
|
||||||
const upload = getElSelector('upload');
|
const upload = getElSelector('upload');
|
||||||
const uploadBtn = getElSelector('upload-btn');
|
const uploadBtn = getElSelector('upload-btn');
|
||||||
const uploadImg = getElSelector('upload-img');
|
const uploadImg = getElSelector('upload-img');
|
||||||
const uploadLoading = getElSelector('upload-loading');
|
const uploadLoading = getElSelector('upload-loading');
|
||||||
const uploadText = getElSelector('upload-text');
|
const uploadText = getElSelector('upload-text');
|
||||||
|
|
||||||
const { update } = state.reset();
|
const { update } = state.reset();
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
safeAnimate(phone, { x: 0, y: 0 }, { duration: 0.5 })?.finished,
|
safeAnimate(phone, { x: 0, y: 0 }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(box, { opacity: 0 }, { duration: 0.5 })?.finished,
|
safeAnimate(box, { opacity: 0 }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(code, { opacity: 0 }, { duration: 0.5 })?.finished,
|
safeAnimate(code, { opacity: 0 }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(uploadLoading, { opacity: 0 }, { duration: 0 })?.finished
|
safeAnimate(uploadLoading, { opacity: 0 }, { duration: 0 })?.finished
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await safeAnimate(code, { zIndex: 20 }, { duration: 0 })?.finished;
|
await safeAnimate(code, { zIndex: 20 }, { duration: 0 })?.finished;
|
||||||
|
|
||||||
update((p) => ({
|
update((p) => ({
|
||||||
...p,
|
...p,
|
||||||
files: [
|
files: [
|
||||||
...p.files,
|
...p.files,
|
||||||
{
|
{
|
||||||
src: '/images/animations/storage-1.png',
|
src: '/images/animations/storage-1.png',
|
||||||
filename: 'Profile.png',
|
filename: 'Profile.png',
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
size: '362.6 KB'
|
size: '362.6 KB'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
safeAnimate(overlay, { opacity: 1 }, { duration: 0.25 })?.finished,
|
safeAnimate(overlay, { opacity: 1 }, { duration: 0.25 })?.finished,
|
||||||
safeAnimate(drawer, { y: [128, 0], opacity: 1 }, { duration: 0.5 })?.finished
|
safeAnimate(drawer, { y: [128, 0], opacity: 1 }, { duration: 0.5 })?.finished
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
await safeAnimate(uploadBtn, { scale: [1, 0.9, 1] }, { duration: 0.25 })?.finished;
|
await safeAnimate(uploadBtn, { scale: [1, 0.9, 1] }, { duration: 0.25 })?.finished;
|
||||||
|
|
||||||
await safeAnimate(code, { x: 300, y: 32 }, { duration: 0 })?.finished;
|
await safeAnimate(code, { x: 300, y: 32 }, { duration: 0 })?.finished;
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
safeAnimate(code, { y: [32 - 16, 32], opacity: 1 }, { duration: 0.5 })?.finished,
|
safeAnimate(code, { y: [32 - 16, 32], opacity: 1 }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(upload, { y: [-16, 0], opacity: 1 }, { duration: 0.5 })?.finished
|
safeAnimate(upload, { y: [-16, 0], opacity: 1 }, { duration: 0.5 })?.finished
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
await safeAnimate(box, { x: 300, y: 300 }, { duration: 0 })?.finished;
|
await safeAnimate(box, { x: 300, y: 300 }, { duration: 0 })?.finished;
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
safeAnimate(uploadImg, { x: [64, 48], y: [80, 64], opacity: 1 }, { duration: 0.5 })?.finished,
|
safeAnimate(uploadImg, { x: [64, 48], y: [80, 64], opacity: 1 }, { duration: 0.5 })
|
||||||
safeAnimate(box, { y: [300 - 16, 300], opacity: 1 }, { duration: 1 })?.finished
|
?.finished,
|
||||||
]);
|
safeAnimate(box, { y: [300 - 16, 300], opacity: 1 }, { duration: 1 })?.finished
|
||||||
|
]);
|
||||||
|
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
safeAnimate(uploadText, { opacity: 0 }, { duration: 0.5 })?.finished,
|
safeAnimate(uploadText, { opacity: 0 }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(uploadLoading, { opacity: 1 }, { duration: 0.5 })?.finished,
|
safeAnimate(uploadLoading, { opacity: 1 }, { duration: 0.5 })?.finished,
|
||||||
safeAnimate(uploadImg, { opacity: 0, y: 64 + 8 }, { duration: 0.5 })?.finished
|
safeAnimate(uploadImg, { opacity: 0, y: 64 + 8 }, { duration: 0.5 })?.finished
|
||||||
]);
|
]);
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
await safeAnimate(upload, { opacity: 0, y: 48 }, { duration: 0.5 })?.finished;
|
await safeAnimate(upload, { opacity: 0, y: 48 }, { duration: 0.5 })?.finished;
|
||||||
|
|
||||||
update((p) => ({
|
update((p) => ({
|
||||||
...p,
|
...p,
|
||||||
files: [
|
files: [
|
||||||
...p.files,
|
...p.files,
|
||||||
{
|
{
|
||||||
src: '/images/animations/storage-2.png',
|
src: '/images/animations/storage-2.png',
|
||||||
filename: 'Vector.svg',
|
filename: 'Vector.svg',
|
||||||
type: 'vector/svg',
|
type: 'vector/svg',
|
||||||
size: '1.5 KB'
|
size: '1.5 KB'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await sleep(250);
|
await sleep(250);
|
||||||
|
|
||||||
update((p) => ({
|
update((p) => ({
|
||||||
...p,
|
...p,
|
||||||
files: [
|
files: [
|
||||||
...p.files,
|
...p.files,
|
||||||
{
|
{
|
||||||
src: '/images/animations/storage-3.png',
|
src: '/images/animations/storage-3.png',
|
||||||
filename: 'img2.webp',
|
filename: 'img2.webp',
|
||||||
type: 'image/webp',
|
type: 'image/webp',
|
||||||
size: '3.2 MB'
|
size: '3.2 MB'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const storageController = {
|
export const storageController = {
|
||||||
execute,
|
execute,
|
||||||
state
|
state
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Storage = {
|
export const Storage = {
|
||||||
Phone,
|
Phone,
|
||||||
Box,
|
Box,
|
||||||
Code
|
Code
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,284 +1,284 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
import { storageController } from '.';
|
import { storageController } from '.';
|
||||||
import { elId } from '../Products.svelte';
|
import { elId } from '../Products.svelte';
|
||||||
import TaskCheckbox from '../TaskCheckbox.svelte';
|
import TaskCheckbox from '../TaskCheckbox.svelte';
|
||||||
import { databasesController } from '../databases';
|
import { databasesController } from '../databases';
|
||||||
|
|
||||||
const { state: dbState } = databasesController;
|
const { state: dbState } = databasesController;
|
||||||
const fixedTasks = $dbState.tasks;
|
const fixedTasks = $dbState.tasks;
|
||||||
|
|
||||||
const { state } = storageController;
|
const { state } = storageController;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div data-theme-ignore class="inner-phone theme-light">
|
<div data-theme-ignore class="inner-phone light">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<p class="title">Your tasks</p>
|
<p class="title">Your tasks</p>
|
||||||
<span class="icon-menu" aria-label="menu" />
|
<span class="icon-menu" aria-label="menu" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="date">Today</div>
|
<div class="date">Today</div>
|
||||||
<div class="tasks">
|
<div class="tasks">
|
||||||
{#each fixedTasks as task (task.id)}
|
{#each fixedTasks as task (task.id)}
|
||||||
<div class="task" data-checked={task.checked ? '' : undefined} in:fly={{ x: -16 }}>
|
<div class="task" data-checked={task.checked ? '' : undefined} in:fly={{ x: -16 }}>
|
||||||
<TaskCheckbox bind:checked={task.checked} />
|
<TaskCheckbox bind:checked={task.checked} />
|
||||||
<span class="title">{task.title}</span>
|
<span class="title">{task.title}</span>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="add-btn">
|
<button class="add-btn">
|
||||||
<span class="web-icon-plus" />
|
<span class="web-icon-plus" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="overlay" id="overlay-{$elId}">
|
<div class="overlay" id="overlay-{$elId}">
|
||||||
<div class="drawer" id="drawer-{$elId}">
|
<div class="drawer" id="drawer-{$elId}">
|
||||||
<p class="title">Edit images for website</p>
|
<p class="title">Edit images for website</p>
|
||||||
<p class="subtitle">Edit the attached images to use in the website</p>
|
<p class="subtitle">Edit the attached images to use in the website</p>
|
||||||
|
|
||||||
<div class="upload" id="upload-btn-{$elId}">Upload media...</div>
|
<div class="upload" id="upload-btn-{$elId}">Upload media...</div>
|
||||||
<div class="images">
|
<div class="images">
|
||||||
{#each $state.files.slice(1) as file}
|
{#each $state.files.slice(1) as file}
|
||||||
<img src={file.src} alt="" transition:fly={{ x: 16 }} />
|
<img src={file.src} alt="" transition:fly={{ x: 16 }} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="upload-media" id="upload-{$elId}">
|
<div class="upload-media" id="upload-{$elId}">
|
||||||
<p class="title">Upload media</p>
|
<p class="title">Upload media</p>
|
||||||
<div class="drop-zone">
|
<div class="drop-zone">
|
||||||
<span id="upload-text-{$elId}"> Drop media here </span>
|
<span id="upload-text-{$elId}"> Drop media here </span>
|
||||||
<div class="loading-overlay" id="upload-loading-{$elId}">
|
<div class="loading-overlay" id="upload-loading-{$elId}">
|
||||||
<div class="loader" />
|
<div class="loader" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<img id="upload-img-{$elId}" src="/images/animations/storage-2.png" alt="" />
|
<img id="upload-img-{$elId}" src="/images/animations/storage-2.png" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.inner-phone {
|
.inner-phone {
|
||||||
padding-block: 3rem;
|
padding-block: 3rem;
|
||||||
padding-inline: 1rem;
|
padding-inline: 1rem;
|
||||||
|
|
||||||
color: rgba(67, 67, 71, 1);
|
color: rgba(67, 67, 71, 1);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: var(--color-greyscale-800, #2d2d31);
|
color: var(--color-greyscale-800, #2d2d31);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 1.375rem; /* 137.5% */
|
line-height: 1.375rem; /* 137.5% */
|
||||||
letter-spacing: -0.014rem;
|
letter-spacing: -0.014rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
[class*='icon-'] {
|
[class*='icon-'] {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
color: hsl(var(--web-color-greyscale-500));
|
color: hsl(var(--web-color-greyscale-500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
margin-block-start: 3rem;
|
margin-block-start: 3rem;
|
||||||
|
|
||||||
color: hsl(var(--web-color-greyscale-600));
|
color: hsl(var(--web-color-greyscale-600));
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 1.25rem; /* 166.667% */
|
line-height: 1.25rem; /* 166.667% */
|
||||||
}
|
}
|
||||||
|
|
||||||
.tasks {
|
.tasks {
|
||||||
margin-block-start: 0.5rem;
|
margin-block-start: 0.5rem;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|
||||||
.task {
|
.task {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
border: 1px solid hsl(var(--web-color-greyscale-50));
|
border: 1px solid hsl(var(--web-color-greyscale-50));
|
||||||
background: hsl(var(--web-color-white));
|
background: hsl(var(--web-color-white));
|
||||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||||
|
|
||||||
padding-block: 0.55rem;
|
padding-block: 0.55rem;
|
||||||
padding-inline: 0.88rem;
|
padding-inline: 0.88rem;
|
||||||
|
|
||||||
/* Responsive/SubBody-400 */
|
/* Responsive/SubBody-400 */
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.375rem; /* 157.143% */
|
line-height: 1.375rem; /* 157.143% */
|
||||||
letter-spacing: -0.00394rem;
|
letter-spacing: -0.00394rem;
|
||||||
|
|
||||||
transition: opacity 200ms ease;
|
transition: opacity 200ms ease;
|
||||||
|
|
||||||
&[data-checked] {
|
&[data-checked] {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-btn {
|
.add-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 1rem;
|
right: 1rem;
|
||||||
bottom: 2.5rem;
|
bottom: 2.5rem;
|
||||||
|
|
||||||
width: 2.5rem;
|
width: 2.5rem;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.12);
|
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.12);
|
||||||
background-color: rgba(124, 103, 254, 1);
|
background-color: rgba(124, 103, 254, 1);
|
||||||
color: rgba(237, 237, 240, 1);
|
color: rgba(237, 237, 240, 1);
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay {
|
.overlay {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
background: rgba(0, 0, 0, 0.32);
|
background: rgba(0, 0, 0, 0.32);
|
||||||
border-radius: 2rem;
|
border-radius: 2rem;
|
||||||
|
|
||||||
.drawer {
|
.drawer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: 60%;
|
height: 60%;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border-radius: 0.88463rem 0.88463rem 2rem 2rem;
|
border-radius: 0.88463rem 0.88463rem 2rem 2rem;
|
||||||
|
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: #434347;
|
color: #434347;
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.88463rem;
|
font-size: 0.88463rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 1.21638rem; /* 137.5% */
|
line-height: 1.21638rem; /* 137.5% */
|
||||||
letter-spacing: -0.01238rem;
|
letter-spacing: -0.01238rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.77406rem;
|
font-size: 0.77406rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.10575rem; /* 142.857% */
|
line-height: 1.10575rem; /* 142.857% */
|
||||||
letter-spacing: -0.01081rem;
|
letter-spacing: -0.01081rem;
|
||||||
|
|
||||||
margin-block-start: 0.2rem;
|
margin-block-start: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload {
|
.upload {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0.44231rem 0.66344rem;
|
padding: 0.44231rem 0.66344rem;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
|
|
||||||
border-radius: 0.66344rem;
|
border-radius: 0.66344rem;
|
||||||
border: 1px dashed #d9d9d9;
|
border: 1px dashed #d9d9d9;
|
||||||
|
|
||||||
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.77406rem;
|
font-size: 0.77406rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.10575rem; /* 142.857% */
|
line-height: 1.10575rem; /* 142.857% */
|
||||||
letter-spacing: -0.01081rem;
|
letter-spacing: -0.01081rem;
|
||||||
|
|
||||||
margin-block-start: 2rem;
|
margin-block-start: 2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-media {
|
.upload-media {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: calc(0% - 24px);
|
right: calc(0% - 24px);
|
||||||
bottom: 8rem;
|
bottom: 8rem;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
box-shadow: 0px 4px 24px 0px rgba(0, 0, 0, 0.05);
|
box-shadow: 0px 4px 24px 0px rgba(0, 0, 0, 0.05);
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: var(--color-greyscale-800, #2d2d31);
|
color: var(--color-greyscale-800, #2d2d31);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 1.375rem; /* 137.5% */
|
line-height: 1.375rem; /* 137.5% */
|
||||||
letter-spacing: -0.014rem;
|
letter-spacing: -0.014rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drop-zone {
|
.drop-zone {
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border: 0.885px dashed #d9d9d9;
|
border: 0.885px dashed #d9d9d9;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
|
||||||
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
||||||
padding: 2rem 1.25rem;
|
padding: 2rem 1.25rem;
|
||||||
margin-block-start: 0.5rem;
|
margin-block-start: 0.5rem;
|
||||||
font-size: 0.65rem;
|
font-size: 0.65rem;
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.loading-overlay {
|
.loading-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.images {
|
.images {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-block-start: 0.5rem;
|
margin-block-start: 0.5rem;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -25,34 +25,21 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="scroll-indicator"
|
class="scroll-indicator relative h-full w-px shrink-0 rounded-full"
|
||||||
use:rect={elRect}
|
use:rect={elRect}
|
||||||
style:--y={`${y}px`}
|
style:--y={`${y}px`}
|
||||||
style:--percentage={`${easedPercentage * 100}%`}
|
style:--percentage={`${easedPercentage * 100}%`}
|
||||||
>
|
>
|
||||||
<div class="web-dot" />
|
<div class="0)] absolute -top-[8px] left-1/2 translate-[-50%_var(--y," />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.scroll-indicator {
|
.scroll-indicator {
|
||||||
position: relative;
|
|
||||||
|
|
||||||
width: 1px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
to bottom,
|
to bottom,
|
||||||
hsl(var(--web-color-accent)) 0%,
|
hsl(var(--web-color-accent)) 0%,
|
||||||
hsl(var(--web-color-greyscale-700)) var(--percentage),
|
hsl(var(--web-color-greyscale-700)) var(--percentage),
|
||||||
hsl(var(--web-color-greyscale-700)) 100%
|
hsl(var(--web-color-greyscale-700)) 100%
|
||||||
);
|
);
|
||||||
border-radius: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.web-dot {
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
translate: -50% var(--y, 0);
|
|
||||||
top: -8px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { PUBLIC_APPWRITE_PROJECT_INIT_ID } from '$env/static/public';
|
|||||||
import { Client, Account } from '@appwrite.io/console';
|
import { Client, Account } from '@appwrite.io/console';
|
||||||
|
|
||||||
const client = new Client();
|
const client = new Client();
|
||||||
client
|
client.setEndpoint('https://cloud.appwrite.io/v1').setProject(PUBLIC_APPWRITE_PROJECT_INIT_ID);
|
||||||
.setEndpoint('https://cloud.appwrite.io/v1')
|
|
||||||
.setProject(PUBLIC_APPWRITE_PROJECT_INIT_ID);
|
|
||||||
|
|
||||||
export const appwriteInit = {
|
export const appwriteInit = {
|
||||||
client,
|
client,
|
||||||
|
|||||||
@@ -7,4 +7,4 @@
|
|||||||
padding-block-start: 0;
|
padding-block-start: 0;
|
||||||
padding-block-end: 2rem;
|
padding-block-end: 2rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import Root from "./Root.svelte";
|
import Root from './Root.svelte';
|
||||||
import Item from "./Item.svelte";
|
import Item from './Item.svelte';
|
||||||
|
|
||||||
export {
|
export { Root as Accordion, Item as AccordionItem };
|
||||||
Root as Accordion,
|
|
||||||
Item as AccordionItem
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -27,8 +27,14 @@
|
|||||||
{title}
|
{title}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="web-author">
|
<div class="web-author">
|
||||||
<div class="u-flex u-cross-center u-gap-8">
|
<div class="flex u-cross-center gap-2">
|
||||||
<img class="web-author-image" src={avatar} width="24" height="24" alt={author} />
|
<img
|
||||||
|
class="web-author-image"
|
||||||
|
src={avatar}
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
alt={author}
|
||||||
|
/>
|
||||||
<div class="web-author-info">
|
<div class="web-author-info">
|
||||||
<h4 class="web-sub-body-400 web-u-color-text-primary">{author}</h4>
|
<h4 class="web-sub-body-400 web-u-color-text-primary">{author}</h4>
|
||||||
<ul class="web-metadata web-caption-400 web-is-not-mobile">
|
<ul class="web-metadata web-caption-400 web-is-not-mobile">
|
||||||
|
|||||||
@@ -42,9 +42,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="u-flex u-flex-wrap u-cross-center u-margin-block-start-8">
|
<div class="flex flex-wrap u-cross-center u-margin-block-start-8">
|
||||||
<slot name="header" />
|
<slot name="header" />
|
||||||
<div class="u-flex u-gap-12 u-cross-end u-margin-inline-start-auto">
|
<div class="flex gap-3 u-cross-end u-margin-inline-start-auto">
|
||||||
<button
|
<button
|
||||||
class="web-icon-button"
|
class="web-icon-button"
|
||||||
aria-label="Move carousel backward"
|
aria-label="Move carousel backward"
|
||||||
@@ -108,7 +108,11 @@
|
|||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
right: 0;
|
right: 0;
|
||||||
background: linear-gradient(to left, hsl(var(--web-color-background-docs)), transparent);
|
background: linear-gradient(
|
||||||
|
to left,
|
||||||
|
hsl(var(--web-color-background-docs)),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-state='end']::after {
|
&[data-state='end']::after {
|
||||||
|
|||||||
@@ -49,12 +49,12 @@
|
|||||||
<section class="web-content-footer">
|
<section class="web-content-footer">
|
||||||
<header class="web-content-footer-header u-width-full-line">
|
<header class="web-content-footer-header u-width-full-line">
|
||||||
<div
|
<div
|
||||||
class="u-flex u-gap-32 u-main-space-between u-cross-center u-width-full-line"
|
class="flex gap-8 u-main-space-between u-cross-center u-width-full-line"
|
||||||
style="flex-wrap: wrap-reverse;"
|
style="flex-wrap: wrap-reverse;"
|
||||||
>
|
>
|
||||||
<div class="u-flex u-gap-16 u-cross-center">
|
<div class="flex gap-4 u-cross-center">
|
||||||
<h5 class="web-main-body-600 web-u-color-text-primary">Was this page helpful?</h5>
|
<h5 class="web-main-body-600 web-u-color-text-primary">Was this page helpful?</h5>
|
||||||
<div class="u-flex u-gap-8">
|
<div class="flex gap-2">
|
||||||
<button
|
<button
|
||||||
class="web-radio-button"
|
class="web-radio-button"
|
||||||
aria-label="helpful"
|
aria-label="helpful"
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
href="https://github.com/appwrite/website"
|
href="https://github.com/appwrite/website"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
class="web-link u-flex u-gap-4 u-cross-baseline"
|
class="web-link flex gap-1 u-cross-baseline"
|
||||||
>
|
>
|
||||||
<span class="icon-pencil-alt u-contents" aria-hidden="true" />
|
<span class="icon-pencil-alt u-contents" aria-hidden="true" />
|
||||||
<span>Update on GitHub</span>
|
<span>Update on GitHub</span>
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
class="web-card is-normal"
|
class="web-card is-normal"
|
||||||
style="--card-padding:1rem"
|
style="--card-padding:1rem"
|
||||||
>
|
>
|
||||||
<div class="u-flex-vertical u-gap-8">
|
<div class="u-flex-vertical gap-2">
|
||||||
<label for="message">
|
<label for="message">
|
||||||
<span class="web-u-color-text-primary">
|
<span class="web-u-color-text-primary">
|
||||||
What did you {feedbackType === 'negative' ? 'dislike' : 'like'}? (optional)
|
What did you {feedbackType === 'negative' ? 'dislike' : 'like'}? (optional)
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="u-flex u-main-end u-margin-block-start-16 u-gap-8">
|
<div class="flex u-main-end u-margin-block-start-16 gap-2">
|
||||||
<button class="web-button is-text" on:click={() => (showFeedback = false)}>
|
<button class="web-button is-text" on:click={() => (showFeedback = false)}>
|
||||||
<span>Cancel</span>
|
<span>Cancel</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
export let images: Array<string>;
|
export let images: Array<string>;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="u-position-absolute web-u-hide-mobile root">
|
<div class="absolute web-u-hide-mobile root">
|
||||||
{#each headPositions as [size, top, left], i}
|
{#each headPositions as [size, top, left], i}
|
||||||
{@const image = clamp(0, images.length - 1, i % images.length)}
|
{@const image = clamp(0, images.length - 1, i % images.length)}
|
||||||
<FloatingHead
|
<FloatingHead
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
{size}
|
{size}
|
||||||
/>
|
/>
|
||||||
<div style:margin-block-end="0" style:padding="10%">
|
<div style:margin-block-end="0" style:padding="10%">
|
||||||
<img style:border-radius="50%" class="u-block" alt="" />
|
<img style:border-radius="50%" class="block" alt="" />
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
{ label: 'Functions', href: '/docs/products/functions' },
|
{ label: 'Functions', href: '/docs/products/functions' },
|
||||||
{ label: 'Messaging', href: '/products/messaging' },
|
{ label: 'Messaging', href: '/products/messaging' },
|
||||||
{ label: 'Storage', href: '/docs/products/storage' },
|
{ label: 'Storage', href: '/docs/products/storage' },
|
||||||
{ label: 'Realtime', href: '/docs/apis/realtime' },
|
{ label: 'Realtime', href: '/docs/apis/realtime' }
|
||||||
],
|
],
|
||||||
Learn: [
|
Learn: [
|
||||||
{ label: 'Docs', href: '/docs' },
|
{ label: 'Docs', href: '/docs' },
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
|
|
||||||
<nav
|
<nav
|
||||||
aria-label="Footer"
|
aria-label="Footer"
|
||||||
class="web-footer-nav u-margin-block-start-100 u-position-relative"
|
class="web-footer-nav u-margin-block-start-100 relative"
|
||||||
class:web-u-sep-block-start={!noBorder}
|
class:web-u-sep-block-start={!noBorder}
|
||||||
>
|
>
|
||||||
<img class="web-logo" src="/images/logos/appwrite.svg" alt="appwrite" height="24" width="130" />
|
<img class="web-logo" src="/images/logos/appwrite.svg" alt="appwrite" height="24" width="130" />
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
export let variant: 'homepage' | 'docs' = 'homepage';
|
export let variant: 'homepage' | 'docs' = 'homepage';
|
||||||
|
|
||||||
const year = new Date().getFullYear()
|
const year = new Date().getFullYear();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if variant === 'homepage'}
|
{#if variant === 'homepage'}
|
||||||
<footer class="web-main-footer u-position-relative u-margin-block-start-48">
|
<footer class="web-main-footer relative u-margin-block-start-48">
|
||||||
<ul class="u-flex u-gap-8">
|
<ul class="flex gap-2">
|
||||||
{#each socials as social}
|
{#each socials as social}
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
<div class="u-flex u-gap-16">
|
<div class="flex gap-4">
|
||||||
<ul class="u-flex u-gap-8">
|
<ul class="flex gap-2">
|
||||||
<li><a class="web-link" href="/terms">Terms</a></li>
|
<li><a class="web-link" href="/terms">Terms</a></li>
|
||||||
<li><a class="web-link" href="/privacy">Privacy</a></li>
|
<li><a class="web-link" href="/privacy">Privacy</a></li>
|
||||||
<li><a class="web-link" href="/cookies">Cookies</a></li>
|
<li><a class="web-link" href="/cookies">Cookies</a></li>
|
||||||
@@ -34,11 +34,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
{:else if variant === 'docs'}
|
{:else if variant === 'docs'}
|
||||||
<footer
|
<footer class="web-main-footer is-with-bg-color u-margin-block-start-32 u-small relative">
|
||||||
class="web-main-footer is-with-bg-color u-margin-block-start-32 u-small u-position-relative"
|
|
||||||
>
|
|
||||||
<div class="web-main-footer-grid-1">
|
<div class="web-main-footer-grid-1">
|
||||||
<ul class="web-main-footer-grid-1-column-1 u-flex u-gap-8">
|
<ul class="web-main-footer-grid-1-column-1 flex gap-2">
|
||||||
{#each socials as social}
|
{#each socials as social}
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
@@ -77,7 +75,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.web-icon-button {
|
.web-icon-button {
|
||||||
display: grid;
|
display: grid;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
<nav class="web-side-nav web-is-not-desktop" class:u-hide={!open}>
|
<nav class="web-side-nav web-is-not-desktop" class:u-hide={!open}>
|
||||||
<div class="web-side-nav-wrapper web-u-padding-inline-16">
|
<div class="web-side-nav-wrapper web-u-padding-inline-16">
|
||||||
<div class="u-flex items-center u-gap-8">
|
<div class="flex items-center gap-2">
|
||||||
<a href="https://cloud.appwrite.io/register" class="web-button is-secondary web-u-flex-1">
|
<a
|
||||||
|
href="https://cloud.appwrite.io/register"
|
||||||
|
class="web-button is-secondary web-u-flex-1"
|
||||||
|
>
|
||||||
Sign up
|
Sign up
|
||||||
</a>
|
</a>
|
||||||
<IsLoggedIn classes="web-u-flex-1" />
|
<IsLoggedIn classes="web-u-flex-1" />
|
||||||
|
|||||||
@@ -1,181 +1,194 @@
|
|||||||
<script context="module" lang="ts">
|
<script context="module" lang="ts">
|
||||||
export async function newsletter(name: string, email: string) {
|
export async function newsletter(name: string, email: string) {
|
||||||
const response = await fetch('https://growth.appwrite.io/v1/newsletter/subscribe', {
|
const response = await fetch('https://growth.appwrite.io/v1/newsletter/subscribe', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
name,
|
name,
|
||||||
email
|
email
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
let email = '';
|
let email = '';
|
||||||
let name = '';
|
let name = '';
|
||||||
let submitted = false;
|
let submitted = false;
|
||||||
let error: string | undefined;
|
let error: string | undefined;
|
||||||
let submitting = false;
|
let submitting = false;
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
submitting = true;
|
submitting = true;
|
||||||
error = undefined;
|
error = undefined;
|
||||||
const response = await newsletter(name, email);
|
const response = await newsletter(name, email);
|
||||||
submitting = false;
|
submitting = false;
|
||||||
if (response.status >= 400) {
|
if (response.status >= 400) {
|
||||||
error = response.status >= 500 ? 'Server Error.' : 'Error submitting form.';
|
error = response.status >= 500 ? 'Server Error.' : 'Error submitting form.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
submitted = true;
|
submitted = true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="pre-footer-bg" style="pointer-events:none;">
|
<div class="pre-footer-bg" style="pointer-events:none;">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="692"
|
width="692"
|
||||||
height="1171"
|
height="1171"
|
||||||
viewBox="0 0 692 1171"
|
viewBox="0 0 692 1171"
|
||||||
fill="none"
|
fill="none"
|
||||||
style="max-inline-size:100%;"
|
style="max-inline-size:100%;"
|
||||||
>
|
>
|
||||||
<g opacity="0.4" filter="url(#filter0_f_1577_37321)">
|
<g opacity="0.4" filter="url(#filter0_f_1577_37321)">
|
||||||
<path
|
<path
|
||||||
d="M-96.9811 29.2126C-329.155 33.7322 -513.706 225.611 -509.186 457.785C-504.667 689.959 -312.788 874.51 -80.6141 869.99C33.1857 867.775 -132.237 523.592 -36.8339 437.579C62.4044 348.109 394.063 627.529 391.759 509.155C387.239 276.98 135.193 24.693 -96.9811 29.2126Z"
|
d="M-96.9811 29.2126C-329.155 33.7322 -513.706 225.611 -509.186 457.785C-504.667 689.959 -312.788 874.51 -80.6141 869.99C33.1857 867.775 -132.237 523.592 -36.8339 437.579C62.4044 348.109 394.063 627.529 391.759 509.155C387.239 276.98 135.193 24.693 -96.9811 29.2126Z"
|
||||||
fill="url(#paint0_radial_1577_37321)"
|
fill="url(#paint0_radial_1577_37321)"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
<defs>
|
<defs>
|
||||||
<filter
|
<filter
|
||||||
id="filter0_f_1577_37321"
|
id="filter0_f_1577_37321"
|
||||||
x="-809.268"
|
x="-809.268"
|
||||||
y="-270.847"
|
y="-270.847"
|
||||||
width="1501.04"
|
width="1501.04"
|
||||||
height="1440.92"
|
height="1440.92"
|
||||||
filterUnits="userSpaceOnUse"
|
filterUnits="userSpaceOnUse"
|
||||||
color-interpolation-filters="sRGB"
|
color-interpolation-filters="sRGB"
|
||||||
>
|
>
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix" />
|
<feFlood flood-opacity="0" result="BackgroundImageFix" />
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
|
||||||
<feGaussianBlur stdDeviation="150" result="effect1_foregroundBlur_1577_37321" />
|
<feGaussianBlur stdDeviation="150" result="effect1_foregroundBlur_1577_37321" />
|
||||||
</filter>
|
</filter>
|
||||||
<radialGradient
|
<radialGradient
|
||||||
id="paint0_radial_1577_37321"
|
id="paint0_radial_1577_37321"
|
||||||
cx="0"
|
cx="0"
|
||||||
cy="0"
|
cy="0"
|
||||||
r="1"
|
r="1"
|
||||||
gradientUnits="userSpaceOnUse"
|
gradientUnits="userSpaceOnUse"
|
||||||
gradientTransform="translate(-88.7975 449.601) rotate(178.885) scale(420.468 420.468)"
|
gradientTransform="translate(-88.7975 449.601) rotate(178.885) scale(420.468 420.468)"
|
||||||
>
|
>
|
||||||
<stop offset="0.281696" stop-color="#FE9567" />
|
<stop offset="0.281696" stop-color="#FE9567" />
|
||||||
<stop offset="0.59375" stop-color="#FD366E" />
|
<stop offset="0.59375" stop-color="#FD366E" />
|
||||||
</radialGradient>
|
</radialGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="web-big-padding-section">
|
<div class="web-big-padding-section">
|
||||||
<div class="web-big-padding-section-level-1">
|
<div class="web-big-padding-section-level-1">
|
||||||
<div class="web-big-padding-section-level-2">
|
<div class="web-big-padding-section-level-2">
|
||||||
<div class="web-container">
|
<div class="web-container">
|
||||||
<div class="web-grid-1-1-opt-2 u-gap-32">
|
<div class="grid grid-cols-2-opt-2 gap-8">
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="web-u-max-inline-size-none-mobile" class:web-u-max-width-380={!submitted}>
|
<div
|
||||||
<section class="u-flex-vertical web-u-gap-20">
|
class="web-u-max-inline-size-none-mobile"
|
||||||
<h1 class="web-title web-u-color-text-primary">Subscribe to our newsletter</h1>
|
class:web-u-max-width-380={!submitted}
|
||||||
<p class="web-description web-u-padding-block-end-40">
|
>
|
||||||
Sign up to our company blog and get the latest insights from Appwrite. Learn more
|
<section class="u-flex-vertical web-gap-5">
|
||||||
about engineering, product design, building community, and tips & tricks for using
|
<h1 class="web-title web-u-color-text-primary">
|
||||||
Appwrite.
|
Subscribe to our newsletter
|
||||||
</p>
|
</h1>
|
||||||
</section>
|
<p class="web-description web-u-padding-block-end-40">
|
||||||
</div>
|
Sign up to our company blog and get the latest insights from
|
||||||
</div>
|
Appwrite. Learn more about engineering, product design, building
|
||||||
{#if submitted}
|
community, and tips & tricks for using Appwrite.
|
||||||
<div class="u-flex u-gap-8 u-cross-center">
|
</p>
|
||||||
<svg
|
</section>
|
||||||
width="18"
|
</div>
|
||||||
height="18"
|
</div>
|
||||||
viewBox="0 0 18 18"
|
{#if submitted}
|
||||||
fill="none"
|
<div class="flex gap-2 u-cross-center">
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<svg
|
||||||
>
|
width="18"
|
||||||
<circle
|
height="18"
|
||||||
cx="9"
|
viewBox="0 0 18 18"
|
||||||
cy="9"
|
fill="none"
|
||||||
r="8"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="#FD366E"
|
>
|
||||||
fill-opacity="0.08"
|
<circle
|
||||||
stroke="#FD366E"
|
cx="9"
|
||||||
stroke-opacity="0.32"
|
cy="9"
|
||||||
stroke-width="1.2"
|
r="8"
|
||||||
stroke-linecap="round"
|
fill="#FD366E"
|
||||||
stroke-linejoin="round"
|
fill-opacity="0.08"
|
||||||
/>
|
stroke="#FD366E"
|
||||||
<path
|
stroke-opacity="0.32"
|
||||||
d="M5.25 10.5L7.75 12.5L12.75 6"
|
stroke-width="1.2"
|
||||||
stroke="#E4E4E7"
|
stroke-linecap="round"
|
||||||
stroke-width="1.2"
|
stroke-linejoin="round"
|
||||||
stroke-linecap="round"
|
/>
|
||||||
stroke-linejoin="round"
|
<path
|
||||||
/>
|
d="M5.25 10.5L7.75 12.5L12.75 6"
|
||||||
</svg>
|
stroke="#E4E4E7"
|
||||||
|
stroke-width="1.2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
<span class="text">
|
<span class="text">
|
||||||
Thank you for subscribing! An email has been sent to your inbox.
|
Thank you for subscribing! An email has been sent to your inbox.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<form method="post" on:submit|preventDefault={submit} class="u-flex-vertical u-gap-16">
|
<form
|
||||||
<div class="u-flex u-flex-vertical u-gap-4">
|
method="post"
|
||||||
<label for="name">Your name</label>
|
on:submit|preventDefault={submit}
|
||||||
<input
|
class="u-flex-vertical gap-4"
|
||||||
class="web-input-text"
|
>
|
||||||
type="text"
|
<div class="flex u-flex-vertical gap-1">
|
||||||
placeholder="Enter your name"
|
<label for="name">Your name</label>
|
||||||
id="name"
|
<input
|
||||||
name="name"
|
class="web-input-text"
|
||||||
required
|
type="text"
|
||||||
bind:value={name}
|
placeholder="Enter your name"
|
||||||
/>
|
id="name"
|
||||||
</div>
|
name="name"
|
||||||
<div class="u-flex u-flex-vertical u-gap-4">
|
required
|
||||||
<label for="email">Your email</label>
|
bind:value={name}
|
||||||
<input
|
/>
|
||||||
class="web-input-text"
|
</div>
|
||||||
type="email"
|
<div class="flex u-flex-vertical gap-1">
|
||||||
placeholder="Enter your email"
|
<label for="email">Your email</label>
|
||||||
required
|
<input
|
||||||
id="email"
|
class="web-input-text"
|
||||||
name="email"
|
type="email"
|
||||||
bind:value={email}
|
placeholder="Enter your email"
|
||||||
/>
|
required
|
||||||
</div>
|
id="email"
|
||||||
<button type="submit" class="web-button" disabled={submitting}>Sign up</button>
|
name="email"
|
||||||
{#if error}
|
bind:value={email}
|
||||||
<span class="text"> Something went wrong. Please try again later. </span>
|
/>
|
||||||
{/if}
|
</div>
|
||||||
</form>
|
<button type="submit" class="web-button" disabled={submitting}
|
||||||
{/if}
|
>Sign up</button
|
||||||
</div>
|
>
|
||||||
</div>
|
{#if error}
|
||||||
</div>
|
<span class="text">
|
||||||
</div>
|
Something went wrong. Please try again later.
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</form>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.pre-footer-bg {
|
.pre-footer-bg {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: clamp(300px, 50vw, 50%);
|
top: clamp(300px, 50vw, 50%);
|
||||||
left: clamp(300px, 50vw, 50%);
|
left: clamp(300px, 50vw, 50%);
|
||||||
transform: translate(-50%, -70%);
|
transform: translate(-50%, -70%);
|
||||||
width: clamp(1200px, 100vw, 3000px);
|
width: clamp(1200px, 100vw, 3000px);
|
||||||
height: auto;
|
height: auto;
|
||||||
max-inline-size: unset;
|
max-inline-size: unset;
|
||||||
max-block-size: unset;
|
max-block-size: unset;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
<img src="/images/bgs/pre-footer.png" alt="" class="web-pre-footer-bg" style="z-index:-1" />
|
<img src="/images/bgs/pre-footer.png" alt="" class="web-pre-footer-bg" style="z-index:-1" />
|
||||||
|
|
||||||
<div class="web-grid-1-1 u-gap-32 web-u-row-gap-80 u-position-relative">
|
<div class="grid grid-cols-2 gap-8 web-u-row-gap-80 relative">
|
||||||
<section class="web-hero u-flex web-u-row-gap-32 u-main-center u-cross-center">
|
<section class="web-hero flex web-u-row-gap-32 u-main-center u-cross-center">
|
||||||
<h2 class="web-display u-max-width-500 web-u-text-align-center web-u-color-text-primary">
|
<h2 class="web-display u-max-width-500 text-center web-u-color-text-primary">
|
||||||
Start building today
|
Start building today
|
||||||
</h2>
|
</h2>
|
||||||
<a
|
<a
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</section>
|
</section>
|
||||||
<section
|
<section
|
||||||
class="web-card is-transparent has-border-gradient web-u-max-inline-width-584-mobile web-u-margin-inline-auto-mobile web-u-inline-width-100-percent-mobile"
|
class="web-card is-transparent has-border-gradient web-u-max-inline-width-584-mobile web-mx-auto-mobile web-u-inline-width-100-percent-mobile"
|
||||||
>
|
>
|
||||||
<header class="web-strip-plans-header">
|
<header class="web-strip-plans-header">
|
||||||
<div class="web-strip-plans-header-wrapper web-u-row-gap-24">
|
<div class="web-strip-plans-header-wrapper web-u-row-gap-24">
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createHref(hit: Hit<Props>): string {
|
function createHref(hit: Hit<Props>): string {
|
||||||
const anchor = hit.anchor === '#' ? '' : hit.anchor ?? '';
|
const anchor = hit.anchor === '#' ? '' : (hit.anchor ?? '');
|
||||||
const target = hit.url + anchor;
|
const target = hit.url + anchor;
|
||||||
|
|
||||||
return target.toString();
|
return target.toString();
|
||||||
@@ -147,7 +147,7 @@
|
|||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<div
|
<div
|
||||||
class="wrapper u-position-fixed u-padding-0 u-inset-0 u-flex u-main-center u-cross-center"
|
class="wrapper u-padding-0 u-inset-0 u-main-center u-cross-center fixed flex"
|
||||||
data-visible={open ? true : undefined}
|
data-visible={open ? true : undefined}
|
||||||
style:z-index="100"
|
style:z-index="100"
|
||||||
style:background="hsl(var(--web-color-black) / 0.3)"
|
style:background="hsl(var(--web-color-black) / 0.3)"
|
||||||
@@ -159,15 +159,11 @@
|
|||||||
<div
|
<div
|
||||||
class="web-input-text-search-wrapper web-u-max-width-680 web-u-margin-inline-20 u-width-full-line"
|
class="web-input-text-search-wrapper web-u-max-width-680 web-u-margin-inline-20 u-width-full-line"
|
||||||
>
|
>
|
||||||
<span
|
<span class="web-icon-search z-[5]" aria-hidden="true" style="inset-block-start:0.9rem" />
|
||||||
class="web-icon-search u-z-index-5"
|
|
||||||
aria-hidden="true"
|
|
||||||
style="inset-block-start:0.9rem"
|
|
||||||
/>
|
|
||||||
<div id="searchbox" />
|
<div id="searchbox" />
|
||||||
|
|
||||||
<input
|
<input
|
||||||
class="web-input-button -u-padding-block-0 u-position-relative u-z-index-1"
|
class="web-input-button -u-padding-block-0 relative z-1"
|
||||||
type="text"
|
type="text"
|
||||||
id="search"
|
id="search"
|
||||||
bind:value
|
bind:value
|
||||||
@@ -184,7 +180,7 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="web-card is-normal u-flex-vertical u-gap-24"
|
class="web-card is-normal u-flex-vertical gap-6"
|
||||||
use:melt={$menu}
|
use:melt={$menu}
|
||||||
style="--card-padding-mobile:1rem; border-radius:0 0 0.5rem 0.5rem;"
|
style="--card-padding-mobile:1rem; border-radius:0 0 0.5rem 0.5rem;"
|
||||||
>
|
>
|
||||||
@@ -192,15 +188,15 @@
|
|||||||
<section>
|
<section>
|
||||||
{#if results.length > 0}
|
{#if results.length > 0}
|
||||||
<h6 class="web-eyebrow">{results.length} results found</h6>
|
<h6 class="web-eyebrow">{results.length} results found</h6>
|
||||||
<ul class="u-flex-vertical u-gap-4 u-margin-block-start-8">
|
<ul class="u-flex-vertical u-margin-block-start-8 gap-1">
|
||||||
{#each results as hit, i (hit.uid)}
|
{#each results as hit, i (hit.uid)}
|
||||||
{@const relevantSubtitle = getRelevantSubtitle(hit)}
|
{@const relevantSubtitle = getRelevantSubtitle(hit)}
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
data-hit={i}
|
data-hit={i}
|
||||||
href={createHref(hit)}
|
href={createHref(hit)}
|
||||||
class="web-button web-caption-400 is-text u-flex-vertical u-gap-8 u-min-width-100-percent
|
class="web-button web-caption-400 is-text u-flex-vertical u-min-width-100-percent web-u-padding-block-8
|
||||||
web-u-padding-block-8 web-padding-inline-12 web-u-cross-start u-max-width-100-percent"
|
web-padding-inline-12 web-u-cross-start u-max-width-100-percent gap-2"
|
||||||
use:melt={$option({
|
use:melt={$option({
|
||||||
value: hit,
|
value: hit,
|
||||||
label: hit.title ?? i.toString()
|
label: hit.title ?? i.toString()
|
||||||
@@ -216,9 +212,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if hit.p}
|
{#if hit.p}
|
||||||
<div
|
<div class="web-u-color-text-secondary web-u-trim-1">
|
||||||
class="web-u-color-text-secondary web-u-trim-1"
|
|
||||||
>
|
|
||||||
{hit.p}
|
{hit.p}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -235,7 +229,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
<section>
|
<section>
|
||||||
<h6 class="web-eyebrow">Recommended</h6>
|
<h6 class="web-eyebrow">Recommended</h6>
|
||||||
<ul class="u-flex-vertical u-gap-4 u-margin-block-start-8">
|
<ul class="u-flex-vertical u-margin-block-start-8 gap-1">
|
||||||
{#each recommended as hit, i (hit.uid)}
|
{#each recommended as hit, i (hit.uid)}
|
||||||
{@const index = i + (results.length ? results.length : 0)}
|
{@const index = i + (results.length ? results.length : 0)}
|
||||||
<li>
|
<li>
|
||||||
@@ -246,7 +240,7 @@
|
|||||||
value: hit,
|
value: hit,
|
||||||
label: hit.title ?? i.toString()
|
label: hit.title ?? i.toString()
|
||||||
})}
|
})}
|
||||||
class="web-button web-caption-400 is-text u-flex-vertical u-gap-8 u-min-width-100-percent web-u-padding-block-4 web-u-cross-start"
|
class="web-button web-caption-400 is-text u-flex-vertical u-min-width-100-percent web-u-padding-block-4 web-u-cross-start gap-2"
|
||||||
>
|
>
|
||||||
<div class="web-u-trim-1">
|
<div class="web-u-trim-1">
|
||||||
<span class="web-u-color-text-secondary">{hit.h1}</span>
|
<span class="web-u-color-text-secondary">{hit.h1}</span>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
{#each groups as group}
|
{#each groups as group}
|
||||||
{@const isDefault = group.label === DEFAULT_GROUP}
|
{@const isDefault = group.label === DEFAULT_GROUP}
|
||||||
{#if isDefault}
|
{#if isDefault}
|
||||||
<div class="u-flex u-flex-vertical u-gap-2">
|
<div class="flex u-flex-vertical gap-0.5">
|
||||||
{#each group.options as option}
|
{#each group.options as option}
|
||||||
<button class="web-select-option" use:melt={$optionEl(option)}>
|
<button class="web-select-option" use:melt={$optionEl(option)}>
|
||||||
{#if option.icon}
|
{#if option.icon}
|
||||||
|
|||||||
@@ -1,68 +1,68 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createSwitch, melt } from '@melt-ui/svelte';
|
import { createSwitch, melt } from '@melt-ui/svelte';
|
||||||
|
|
||||||
export let checked = false;
|
export let checked = false;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
elements: { root },
|
elements: { root },
|
||||||
states: { checked: meltChecked }
|
states: { checked: meltChecked }
|
||||||
} = createSwitch({
|
} = createSwitch({
|
||||||
onCheckedChange({ next }) {
|
onCheckedChange({ next }) {
|
||||||
checked = next;
|
checked = next;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$: meltChecked.set(checked);
|
$: meltChecked.set(checked);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="melt-switch">
|
<div class="melt-switch">
|
||||||
<button use:melt={$root}>
|
<button use:melt={$root}>
|
||||||
<span class="thumb" />
|
<span class="thumb" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.melt-switch {
|
.melt-switch {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
--padding: 0.125rem;
|
--padding: 0.125rem;
|
||||||
--width: 2.25rem;
|
--width: 2.25rem;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
width: var(--width);
|
width: var(--width);
|
||||||
cursor: default;
|
cursor: default;
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
background-color: #19191d;
|
background-color: #19191d;
|
||||||
transition: ease 150ms;
|
transition: ease 150ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.melt-switch :global([data-state='checked']) {
|
.melt-switch :global([data-state='checked']) {
|
||||||
background-color: #fd366e;
|
background-color: #fd366e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumb {
|
.thumb {
|
||||||
--thumb-size: 1.25rem;
|
--thumb-size: 1.25rem;
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
height: var(--thumb-size);
|
height: var(--thumb-size);
|
||||||
width: var(--thumb-size);
|
width: var(--thumb-size);
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
transform: translateX(var(--padding)) translateY(-50%);
|
transform: translateX(var(--padding)) translateY(-50%);
|
||||||
|
|
||||||
transition: ease 150ms;
|
transition: ease 150ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(button[data-state='checked']) .thumb {
|
:global(button[data-state='checked']) .thumb {
|
||||||
--x: calc(var(--width) - var(--thumb-size) - var(--padding));
|
--x: calc(var(--width) - var(--thumb-size) - var(--padding));
|
||||||
transform: translateX(var(--x)) translateY(-50%);
|
transform: translateX(var(--x)) translateY(-50%);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
href: '/docs/quick-starts/angular',
|
href: '/docs/quick-starts/angular',
|
||||||
image: `/images/platforms/${$themeInUse}/angular.svg`
|
image: `/images/platforms/${$themeInUse}/angular.svg`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Refine',
|
name: 'Refine',
|
||||||
href: '/docs/quick-starts/refine',
|
href: '/docs/quick-starts/refine',
|
||||||
image: `/images/platforms/${$themeInUse}/refine.svg`
|
image: `/images/platforms/${$themeInUse}/refine.svg`
|
||||||
@@ -57,8 +57,7 @@
|
|||||||
name: 'React Native',
|
name: 'React Native',
|
||||||
href: '/docs/quick-starts/react-native',
|
href: '/docs/quick-starts/react-native',
|
||||||
image: `/images/platforms/${$themeInUse}/react-native.svg`
|
image: `/images/platforms/${$themeInUse}/react-native.svg`
|
||||||
},
|
}
|
||||||
|
|
||||||
] as Array<{
|
] as Array<{
|
||||||
name: string;
|
name: string;
|
||||||
href: string;
|
href: string;
|
||||||
@@ -66,12 +65,17 @@
|
|||||||
}>;
|
}>;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ul class="u-flex u-flex-wrap u-gap-16 web-u-margin-block-32-mobile web-u-margin-block-40-not-mobile">
|
<ul class="flex flex-wrap gap-4 web-u-margin-block-32-mobile web-u-margin-block-40-not-mobile">
|
||||||
{#each platforms as platform}
|
{#each platforms as platform}
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<li>
|
<li>
|
||||||
<a href={platform.href} class="web-icon-button web-box-icon has-border-gradient">
|
<a href={platform.href} class="web-icon-button web-box-icon has-border-gradient">
|
||||||
<img src={platform.image} alt="{platform.name} quick start" width="32" height="32" />
|
<img
|
||||||
|
src={platform.image}
|
||||||
|
alt="{platform.name} quick start"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<svelte:fragment slot="tooltip">{platform.name}</svelte:fragment>
|
<svelte:fragment slot="tooltip">{platform.name}</svelte:fragment>
|
||||||
|
|||||||
@@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
<aside class="web-grid-120-1fr-auto-side" class:web-is-mobile-closed={!showToc}>
|
<aside class="web-grid-120-1fr-auto-side" class:web-is-mobile-closed={!showToc}>
|
||||||
<div class="web-page-steps">
|
<div class="web-page-steps">
|
||||||
<div class="web-page-steps-location web-is-not-mobile" style="--location:{progress * 100}%;">
|
<div
|
||||||
|
class="web-page-steps-location web-is-not-mobile"
|
||||||
|
style="--location:{progress * 100}%;"
|
||||||
|
>
|
||||||
<span class="web-page-steps-location-button">
|
<span class="web-page-steps-location-button">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export const GITHUB_STARS = '41.9K';
|
export const GITHUB_STARS = '41.9K';
|
||||||
export const BANNER_KEY = 'discord-banner-01'; // Change key to force banner to show again
|
export const BANNER_KEY = 'discord-banner-01'; // Change key to force banner to show again
|
||||||
export const SENTRY_DSN = 'https://27d41dc8bb67b596f137924ab8599e59@o1063647.ingest.us.sentry.io/4507497727000576'
|
export const SENTRY_DSN =
|
||||||
|
'https://27d41dc8bb67b596f137924ab8599e59@o1063647.ingest.us.sentry.io/4507497727000576';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* History:
|
* History:
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<svelte:window on:keydown={handleKeydown} />
|
<svelte:window on:keydown={handleKeydown} />
|
||||||
|
|
||||||
<div class="u-position-relative">
|
<div class="relative">
|
||||||
<section class="web-mobile-header is-transparent">
|
<section class="web-mobile-header is-transparent">
|
||||||
<div class="web-mobile-header-start">
|
<div class="web-mobile-header-start">
|
||||||
<a href="/" aria-label="homepage">
|
<a href="/" aria-label="homepage">
|
||||||
@@ -102,7 +102,11 @@
|
|||||||
<a href="https://cloud.appwrite.io" class="web-button web-is-only-desktop">
|
<a href="https://cloud.appwrite.io" class="web-button web-is-only-desktop">
|
||||||
<span class="web-sub-body-500">Go to Console</span>
|
<span class="web-sub-body-500">Go to Console</span>
|
||||||
</a>
|
</a>
|
||||||
<button class="web-button is-text" aria-label="open navigation" on:click={toggleSidenav}>
|
<button
|
||||||
|
class="web-button is-text"
|
||||||
|
aria-label="open navigation"
|
||||||
|
on:click={toggleSidenav}
|
||||||
|
>
|
||||||
{#if $layoutState.showSidenav}
|
{#if $layoutState.showSidenav}
|
||||||
<span aria-hidden="true" class="web-icon-close" />
|
<span aria-hidden="true" class="web-icon-close" />
|
||||||
{:else}
|
{:else}
|
||||||
@@ -140,7 +144,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="u-flex u-stretch web-u-margin-inline-start-48">
|
<div class="flex u-stretch web-u-margin-inline-start-48">
|
||||||
<button
|
<button
|
||||||
class="web-input-button web-u-flex-basis-400"
|
class="web-input-button web-u-flex-basis-400"
|
||||||
on:click={() => ($layoutState.showSearch = true)}
|
on:click={() => ($layoutState.showSearch = true)}
|
||||||
@@ -148,7 +152,7 @@
|
|||||||
<span class="web-icon-search" aria-hidden="true" />
|
<span class="web-icon-search" aria-hidden="true" />
|
||||||
<span class="text">Search in docs</span>
|
<span class="text">Search in docs</span>
|
||||||
|
|
||||||
<div class="u-flex u-gap-4 u-margin-inline-start-auto">
|
<div class="flex gap-1 u-margin-inline-start-auto">
|
||||||
{#if isMac()}
|
{#if isMac()}
|
||||||
<span class="web-kbd" aria-label="command">⌘</span>
|
<span class="web-kbd" aria-label="command">⌘</span>
|
||||||
{:else}
|
{:else}
|
||||||
@@ -160,7 +164,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="web-main-header-end">
|
<div class="web-main-header-end">
|
||||||
<div class="u-flex u-gap-8">
|
<div class="flex gap-2">
|
||||||
<a
|
<a
|
||||||
href="https://github.com/appwrite/appwrite/stargazers"
|
href="https://github.com/appwrite/appwrite/stargazers"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|||||||
@@ -39,13 +39,13 @@
|
|||||||
<ul class="web-metadata web-caption-400">
|
<ul class="web-metadata web-caption-400">
|
||||||
<slot name="metadata" />
|
<slot name="metadata" />
|
||||||
</ul>
|
</ul>
|
||||||
<div class="u-position-relative u-flex u-cross-center">
|
<div class="relative flex u-cross-center">
|
||||||
{#if back}
|
{#if back}
|
||||||
<a
|
<a
|
||||||
href={back}
|
href={back}
|
||||||
class="
|
class="
|
||||||
web-button is-text is-icon web-u-cross-center web-u-size-40
|
web-button is-text is-icon web-u-cross-center web-u-size-40
|
||||||
u-position-absolute u-inset-inline-start-0 web-u-translate-x-negative"
|
absolute u-inset-inline-start-0 web-u-translate-x-negative"
|
||||||
aria-label="previous page"
|
aria-label="previous page"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
@@ -66,14 +66,12 @@
|
|||||||
<aside class="web-references-menu web-u-padding-inline-start-24">
|
<aside class="web-references-menu web-u-padding-inline-start-24">
|
||||||
<div class="web-references-menu-content">
|
<div class="web-references-menu-content">
|
||||||
{#if toc && toc.length > 0}
|
{#if toc && toc.length > 0}
|
||||||
<div class="u-flex u-main-space-between u-cross-center u-gap-16">
|
<div class="flex u-main-space-between u-cross-center gap-4">
|
||||||
<h5 class="web-references-menu-title web-eyebrow">On This Page</h5>
|
<h5 class="web-references-menu-title web-eyebrow">On This Page</h5>
|
||||||
</div>
|
</div>
|
||||||
<ol class="web-references-menu-list">
|
<ol class="web-references-menu-list">
|
||||||
{#each toc as parent (parent.href)}
|
{#each toc as parent (parent.href)}
|
||||||
<li
|
<li class="web-references-menu-item">
|
||||||
class="web-references-menu-item"
|
|
||||||
>
|
|
||||||
<a
|
<a
|
||||||
href={parent.href}
|
href={parent.href}
|
||||||
class="web-references-menu-link"
|
class="web-references-menu-link"
|
||||||
@@ -94,7 +92,8 @@
|
|||||||
href={child.href}
|
href={child.href}
|
||||||
class="web-references-menu-link"
|
class="web-references-menu-link"
|
||||||
>
|
>
|
||||||
<span class="web-caption-400">{child.title}</span
|
<span class="web-caption-400"
|
||||||
|
>{child.title}</span
|
||||||
>
|
>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -105,10 +104,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</ol>
|
</ol>
|
||||||
<div class="u-sep-block-start u-padding-block-start-20">
|
<div class="u-sep-block-start u-padding-block-start-20">
|
||||||
<button
|
<button class="web-link u-inline-flex u-cross-center gap-2" use:scrollToTop>
|
||||||
class="web-link u-inline-flex u-cross-center u-gap-8"
|
|
||||||
use:scrollToTop
|
|
||||||
>
|
|
||||||
<span class="web-icon-arrow-up" aria-hidden="true" />
|
<span class="web-icon-arrow-up" aria-hidden="true" />
|
||||||
<span class="web-caption-400">Back to top</span>
|
<span class="web-caption-400">Back to top</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -117,4 +113,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
</article>
|
</article>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -20,22 +20,19 @@
|
|||||||
<article class="web-article u-contents">
|
<article class="web-article u-contents">
|
||||||
<header class="web-article-header">
|
<header class="web-article-header">
|
||||||
<div class="web-article-header-start u-flex-vertical web-u-cross-start">
|
<div class="web-article-header-start u-flex-vertical web-u-cross-start">
|
||||||
<button
|
<button class="web-icon-button web-is-only-mobile" aria-label="previous page">
|
||||||
class="web-icon-button web-is-only-mobile"
|
|
||||||
aria-label="previous page"
|
|
||||||
>
|
|
||||||
<span class="icon-cheveron-left" aria-hidden="true" />
|
<span class="icon-cheveron-left" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul class="web-metadata web-caption-400">
|
<ul class="web-metadata web-caption-400">
|
||||||
<slot name="metadata" />
|
<slot name="metadata" />
|
||||||
</ul>
|
</ul>
|
||||||
<div class="u-position-relative u-flex u-cross-center">
|
<div class="relative flex u-cross-center">
|
||||||
{#if back}
|
{#if back}
|
||||||
<a
|
<a
|
||||||
href={back}
|
href={back}
|
||||||
class="
|
class="
|
||||||
web-button is-text is-only-icon web-u-cross-center web-u-size-40
|
web-button is-text is-only-icon web-u-cross-center web-u-size-40
|
||||||
u-position-absolute u-inset-inline-start-0 web-u-translate-x-negative"
|
absolute u-inset-inline-start-0 web-u-translate-x-negative"
|
||||||
aria-label="previous page"
|
aria-label="previous page"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
@@ -51,7 +48,7 @@
|
|||||||
</header>
|
</header>
|
||||||
<div class="web-article-content">
|
<div class="web-article-content">
|
||||||
<slot />
|
<slot />
|
||||||
<div class="u-flex u-main-space-between">
|
<div class="flex u-main-space-between">
|
||||||
{#if prevStep}
|
{#if prevStep}
|
||||||
<a href={prevStep.href} class="web-button is-text">
|
<a href={prevStep.href} class="web-button is-text">
|
||||||
<span class="icon-cheveron-left" aria-hidden="true" />
|
<span class="icon-cheveron-left" aria-hidden="true" />
|
||||||
@@ -82,7 +79,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<aside class="web-references-menu web-u-padding-inline-start-24">
|
<aside class="web-references-menu web-u-padding-inline-start-24">
|
||||||
<div class="web-references-menu-content">
|
<div class="web-references-menu-content">
|
||||||
<div class="u-flex u-main-space-between u-cross-center u-gap-16">
|
<div class="flex u-main-space-between u-cross-center gap-4">
|
||||||
<h5 class="web-references-menu-title web-eyebrow">Tutorial Steps</h5>
|
<h5 class="web-references-menu-title web-eyebrow">Tutorial Steps</h5>
|
||||||
</div>
|
</div>
|
||||||
<ol class="web-references-menu-list">
|
<ol class="web-references-menu-list">
|
||||||
@@ -100,9 +97,9 @@
|
|||||||
</a>
|
</a>
|
||||||
{#if isCurrentStep}
|
{#if isCurrentStep}
|
||||||
<ol
|
<ol
|
||||||
class="web-references-menu-list u-margin-block-start-16 u-margin-inline-start-32"
|
class="web-references-menu-list u-margin-block-start-16 u-margin-inline-start-32"
|
||||||
>
|
>
|
||||||
{#each toc as parent}
|
{#each toc as parent}
|
||||||
<li class="web-references-menu-item">
|
<li class="web-references-menu-item">
|
||||||
<a
|
<a
|
||||||
href={parent.href}
|
href={parent.href}
|
||||||
@@ -136,14 +133,14 @@
|
|||||||
</ol>
|
</ol>
|
||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ol>
|
</ol>
|
||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ol>
|
</ol>
|
||||||
<div class="u-sep-block-start u-padding-block-start-20">
|
<div class="u-sep-block-start u-padding-block-start-20">
|
||||||
<button class="web-link u-inline-flex u-cross-center u-gap-8" use:scrollToTop>
|
<button class="web-link u-inline-flex u-cross-center gap-2" use:scrollToTop>
|
||||||
<span class="web-icon-arrow-up" aria-hidden="true" />
|
<span class="web-icon-arrow-up" aria-hidden="true" />
|
||||||
<span class="web-caption-400">Back to top</span>
|
<span class="web-caption-400">Back to top</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -152,5 +149,3 @@
|
|||||||
</aside>
|
</aside>
|
||||||
</article>
|
</article>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getVisibleTheme() {
|
function getVisibleTheme() {
|
||||||
const themes = Array.from(document.querySelectorAll('.theme-dark, .theme-light')).filter(
|
const themes = Array.from(document.querySelectorAll('.theme-dark, .light')).filter(
|
||||||
(element) => {
|
(element) => {
|
||||||
const { classList, dataset } = element as HTMLElement;
|
const { classList, dataset } = element as HTMLElement;
|
||||||
if (
|
if (
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
|
|
||||||
for (const theme of themes) {
|
for (const theme of themes) {
|
||||||
if (isInViewport(theme)) {
|
if (isInViewport(theme)) {
|
||||||
return theme.classList.contains('theme-light') ? 'light' : 'dark';
|
return theme.classList.contains('light') ? 'light' : 'dark';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="u-position-relative">
|
<div class="relative">
|
||||||
<section
|
<section
|
||||||
class="web-mobile-header theme-{resolvedTheme}"
|
class="web-mobile-header theme-{resolvedTheme}"
|
||||||
class:is-transparent={browser && !$isMobileNavOpen}
|
class:is-transparent={browser && !$isMobileNavOpen}
|
||||||
|
|||||||
@@ -59,7 +59,8 @@
|
|||||||
<a href={parent.href} aria-label="go back">
|
<a href={parent.href} aria-label="go back">
|
||||||
<span class="icon-cheveron-left" aria-hidden="true" />
|
<span class="icon-cheveron-left" aria-hidden="true" />
|
||||||
</a>
|
</a>
|
||||||
<span class="web-side-nav-wrapper-parent-title web-eyebrow">{parent.label}</span>
|
<span class="web-side-nav-wrapper-parent-title web-eyebrow">{parent.label}</span
|
||||||
|
>
|
||||||
</section>
|
</section>
|
||||||
{/if}
|
{/if}
|
||||||
{#each navigation as navGroup}
|
{#each navigation as navGroup}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export function capitalize(str: string) {
|
export function capitalize(str: string) {
|
||||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,114 +3,114 @@ type Cancel = () => void;
|
|||||||
type Promised<T> = T extends Promise<infer U> ? U : T;
|
type Promised<T> = T extends Promise<infer U> ? U : T;
|
||||||
|
|
||||||
type Args<T> = {
|
type Args<T> = {
|
||||||
returned: Promised<T>;
|
returned: Promised<T>;
|
||||||
cancel: Cancel;
|
cancel: Cancel;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Chain = {
|
export type Chain = {
|
||||||
execute: () => Promise<void>;
|
execute: () => Promise<void>;
|
||||||
cancel: Cancel;
|
cancel: Cancel;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ChainFn {
|
interface ChainFn {
|
||||||
<A>(fn1: (args: Args<undefined>) => A): Chain;
|
<A>(fn1: (args: Args<undefined>) => A): Chain;
|
||||||
<A, B>(fn1: (args: Args<undefined>) => A, fn2: (args: Args<A>) => B): Chain;
|
<A, B>(fn1: (args: Args<undefined>) => A, fn2: (args: Args<A>) => B): Chain;
|
||||||
<A, B, C>(
|
<A, B, C>(
|
||||||
fn1: (args: Args<undefined>) => A,
|
fn1: (args: Args<undefined>) => A,
|
||||||
fn2: (args: Args<A>) => B,
|
fn2: (args: Args<A>) => B,
|
||||||
fn3: (args: Args<B>) => C
|
fn3: (args: Args<B>) => C
|
||||||
): Chain;
|
): Chain;
|
||||||
<A, B, C, D>(
|
<A, B, C, D>(
|
||||||
fn1: (args: Args<undefined>) => A,
|
fn1: (args: Args<undefined>) => A,
|
||||||
fn2: (args: Args<A>) => B,
|
fn2: (args: Args<A>) => B,
|
||||||
fn3: (args: Args<B>) => C,
|
fn3: (args: Args<B>) => C,
|
||||||
fn4: (args: Args<C>) => D
|
fn4: (args: Args<C>) => D
|
||||||
): Chain;
|
): Chain;
|
||||||
<A, B, C, D, E>(
|
<A, B, C, D, E>(
|
||||||
fn1: (args: Args<undefined>) => A,
|
fn1: (args: Args<undefined>) => A,
|
||||||
fn2: (args: Args<A>) => B,
|
fn2: (args: Args<A>) => B,
|
||||||
fn3: (args: Args<B>) => C,
|
fn3: (args: Args<B>) => C,
|
||||||
fn4: (args: Args<C>) => D,
|
fn4: (args: Args<C>) => D,
|
||||||
fn5: (args: Args<D>) => E
|
fn5: (args: Args<D>) => E
|
||||||
): Chain;
|
): Chain;
|
||||||
<A, B, C, D, E, F>(
|
<A, B, C, D, E, F>(
|
||||||
fn1: (args: Args<undefined>) => A,
|
fn1: (args: Args<undefined>) => A,
|
||||||
fn2: (args: Args<A>) => B,
|
fn2: (args: Args<A>) => B,
|
||||||
fn3: (args: Args<B>) => C,
|
fn3: (args: Args<B>) => C,
|
||||||
fn4: (args: Args<C>) => D,
|
fn4: (args: Args<C>) => D,
|
||||||
fn5: (args: Args<D>) => E,
|
fn5: (args: Args<D>) => E,
|
||||||
fn6: (args: Args<E>) => F
|
fn6: (args: Args<E>) => F
|
||||||
): Chain;
|
): Chain;
|
||||||
<A, B, C, D, E, F, G>(
|
<A, B, C, D, E, F, G>(
|
||||||
fn1: (args: Args<undefined>) => A,
|
fn1: (args: Args<undefined>) => A,
|
||||||
fn2: (args: Args<A>) => B,
|
fn2: (args: Args<A>) => B,
|
||||||
fn3: (args: Args<B>) => C,
|
fn3: (args: Args<B>) => C,
|
||||||
fn4: (args: Args<C>) => D,
|
fn4: (args: Args<C>) => D,
|
||||||
fn5: (args: Args<D>) => E,
|
fn5: (args: Args<D>) => E,
|
||||||
fn6: (args: Args<E>) => F,
|
fn6: (args: Args<E>) => F,
|
||||||
fn7: (args: Args<F>) => G
|
fn7: (args: Args<F>) => G
|
||||||
): Chain;
|
): Chain;
|
||||||
<A, B, C, D, E, F, G, H>(
|
<A, B, C, D, E, F, G, H>(
|
||||||
fn1: (args: Args<undefined>) => A,
|
fn1: (args: Args<undefined>) => A,
|
||||||
fn2: (args: Args<A>) => B,
|
fn2: (args: Args<A>) => B,
|
||||||
fn3: (args: Args<B>) => C,
|
fn3: (args: Args<B>) => C,
|
||||||
fn4: (args: Args<C>) => D,
|
fn4: (args: Args<C>) => D,
|
||||||
fn5: (args: Args<D>) => E,
|
fn5: (args: Args<D>) => E,
|
||||||
fn6: (args: Args<E>) => F,
|
fn6: (args: Args<E>) => F,
|
||||||
fn7: (args: Args<F>) => G,
|
fn7: (args: Args<F>) => G,
|
||||||
fn8: (args: Args<G>) => H
|
fn8: (args: Args<G>) => H
|
||||||
): Chain;
|
): Chain;
|
||||||
<A, B, C, D, E, F, G, H, I>(
|
<A, B, C, D, E, F, G, H, I>(
|
||||||
fn1: (args: Args<undefined>) => A,
|
fn1: (args: Args<undefined>) => A,
|
||||||
fn2: (args: Args<A>) => B,
|
fn2: (args: Args<A>) => B,
|
||||||
fn3: (args: Args<B>) => C,
|
fn3: (args: Args<B>) => C,
|
||||||
fn4: (args: Args<C>) => D,
|
fn4: (args: Args<C>) => D,
|
||||||
fn5: (args: Args<D>) => E,
|
fn5: (args: Args<D>) => E,
|
||||||
fn6: (args: Args<E>) => F,
|
fn6: (args: Args<E>) => F,
|
||||||
fn7: (args: Args<F>) => G,
|
fn7: (args: Args<F>) => G,
|
||||||
fn8: (args: Args<G>) => H,
|
fn8: (args: Args<G>) => H,
|
||||||
fn9: (args: Args<H>) => I
|
fn9: (args: Args<H>) => I
|
||||||
): Chain;
|
): Chain;
|
||||||
<A, B, C, D, E, F, G, H, I, J>(
|
<A, B, C, D, E, F, G, H, I, J>(
|
||||||
fn1: (args: Args<undefined>) => A,
|
fn1: (args: Args<undefined>) => A,
|
||||||
fn2: (args: Args<A>) => B,
|
fn2: (args: Args<A>) => B,
|
||||||
fn3: (args: Args<B>) => C,
|
fn3: (args: Args<B>) => C,
|
||||||
fn4: (args: Args<C>) => D,
|
fn4: (args: Args<C>) => D,
|
||||||
fn5: (args: Args<D>) => E,
|
fn5: (args: Args<D>) => E,
|
||||||
fn6: (args: Args<E>) => F,
|
fn6: (args: Args<E>) => F,
|
||||||
fn7: (args: Args<F>) => G,
|
fn7: (args: Args<F>) => G,
|
||||||
fn8: (args: Args<G>) => H,
|
fn8: (args: Args<G>) => H,
|
||||||
fn9: (args: Args<H>) => I,
|
fn9: (args: Args<H>) => I,
|
||||||
fn10: (args: Args<I>) => J
|
fn10: (args: Args<I>) => J
|
||||||
): Chain;
|
): Chain;
|
||||||
<A, B, C, D, E, F, G, H, I, J, K>(
|
<A, B, C, D, E, F, G, H, I, J, K>(
|
||||||
fn1: (args: Args<undefined>) => A,
|
fn1: (args: Args<undefined>) => A,
|
||||||
fn2: (args: Args<A>) => B,
|
fn2: (args: Args<A>) => B,
|
||||||
fn3: (args: Args<B>) => C,
|
fn3: (args: Args<B>) => C,
|
||||||
fn4: (args: Args<C>) => D,
|
fn4: (args: Args<C>) => D,
|
||||||
fn5: (args: Args<D>) => E,
|
fn5: (args: Args<D>) => E,
|
||||||
fn6: (args: Args<E>) => F,
|
fn6: (args: Args<E>) => F,
|
||||||
fn7: (args: Args<F>) => G,
|
fn7: (args: Args<F>) => G,
|
||||||
fn8: (args: Args<G>) => H,
|
fn8: (args: Args<G>) => H,
|
||||||
fn9: (args: Args<H>) => I,
|
fn9: (args: Args<H>) => I,
|
||||||
fn10: (args: Args<I>) => J,
|
fn10: (args: Args<I>) => J,
|
||||||
fn11: (args: Args<J>) => K
|
fn11: (args: Args<J>) => K
|
||||||
): Chain;
|
): Chain;
|
||||||
<A, B, C, D, E, F, G, H, I, J, K, L>(
|
<A, B, C, D, E, F, G, H, I, J, K, L>(
|
||||||
fn1: (args: Args<undefined>) => A,
|
fn1: (args: Args<undefined>) => A,
|
||||||
fn2: (args: Args<A>) => B,
|
fn2: (args: Args<A>) => B,
|
||||||
fn3: (args: Args<B>) => C,
|
fn3: (args: Args<B>) => C,
|
||||||
fn4: (args: Args<C>) => D,
|
fn4: (args: Args<C>) => D,
|
||||||
fn5: (args: Args<D>) => E,
|
fn5: (args: Args<D>) => E,
|
||||||
fn6: (args: Args<E>) => F,
|
fn6: (args: Args<E>) => F,
|
||||||
fn7: (args: Args<F>) => G,
|
fn7: (args: Args<F>) => G,
|
||||||
fn8: (args: Args<G>) => H,
|
fn8: (args: Args<G>) => H,
|
||||||
fn9: (args: Args<H>) => I,
|
fn9: (args: Args<H>) => I,
|
||||||
fn10: (args: Args<I>) => J,
|
fn10: (args: Args<I>) => J,
|
||||||
fn11: (args: Args<J>) => K,
|
fn11: (args: Args<J>) => K,
|
||||||
fn12: (args: Args<K>) => L
|
fn12: (args: Args<K>) => L
|
||||||
): Chain;
|
): Chain;
|
||||||
// So on...
|
// So on...
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,32 +120,32 @@ interface ChainFn {
|
|||||||
* The cancel method will cancel the execution of the remaining callbacks.
|
* The cancel method will cancel the execution of the remaining callbacks.
|
||||||
*/
|
*/
|
||||||
export const chain: ChainFn = (...fns: Function[]) => {
|
export const chain: ChainFn = (...fns: Function[]) => {
|
||||||
const cancelled = {} as Record<string, boolean>;
|
const cancelled = {} as Record<string, boolean>;
|
||||||
|
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
Object.keys(cancelled).forEach((key) => (cancelled[key] = true));
|
Object.keys(cancelled).forEach((key) => (cancelled[key] = true));
|
||||||
};
|
};
|
||||||
|
|
||||||
let lastRes: any = undefined;
|
let lastRes: any = undefined;
|
||||||
|
|
||||||
const execute = async () => {
|
const execute = async () => {
|
||||||
const executionId = stupidId();
|
const executionId = stupidId();
|
||||||
cancelled[executionId] = false;
|
cancelled[executionId] = false;
|
||||||
|
|
||||||
for (let i = 0; i < fns.length; i++) {
|
for (let i = 0; i < fns.length; i++) {
|
||||||
const fn = fns[i];
|
const fn = fns[i];
|
||||||
if (cancelled[executionId]) {
|
if (cancelled[executionId]) {
|
||||||
delete cancelled[executionId];
|
delete cancelled[executionId];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastRes = await fn({ returned: lastRes, cancel });
|
lastRes = await fn({ returned: lastRes, cancel });
|
||||||
}
|
}
|
||||||
|
|
||||||
delete cancelled[executionId];
|
delete cancelled[executionId];
|
||||||
};
|
};
|
||||||
|
|
||||||
return { execute, cancel };
|
return { execute, cancel };
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stupid way of generating unique id
|
// Stupid way of generating unique id
|
||||||
|
|||||||
@@ -4,24 +4,24 @@ import { clamp } from './clamp';
|
|||||||
import type { TestCases } from './test';
|
import type { TestCases } from './test';
|
||||||
|
|
||||||
const testCases: TestCases<typeof clamp> = [
|
const testCases: TestCases<typeof clamp> = [
|
||||||
{
|
{
|
||||||
args: [0, 5, 10],
|
args: [0, 5, 10],
|
||||||
expected: 5
|
expected: 5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: [0, -5, 10],
|
args: [0, -5, 10],
|
||||||
expected: 0
|
expected: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: [0, 15, 10],
|
args: [0, 15, 10],
|
||||||
expected: 10
|
expected: 10
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('clamp', () => {
|
describe('clamp', () => {
|
||||||
testCases.forEach(({ args, expected }) => {
|
testCases.forEach(({ args, expected }) => {
|
||||||
it(`should return ${expected} when given ${JSON.stringify(args)}`, () => {
|
it(`should return ${expected} when given ${JSON.stringify(args)}`, () => {
|
||||||
expect(clamp(...args)).toBe(expected);
|
expect(clamp(...args)).toBe(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export function clamp(min: number, value: number, max: number) {
|
export function clamp(min: number, value: number, max: number) {
|
||||||
return Math.min(Math.max(min, value), max);
|
return Math.min(Math.max(min, value), max);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
let lastScrollPos = 0;
|
let lastScrollPos = 0;
|
||||||
|
|
||||||
export function getScrollDir() {
|
export function getScrollDir() {
|
||||||
const scrollPos = window.scrollY;
|
const scrollPos = window.scrollY;
|
||||||
const scrollDir = scrollPos > lastScrollPos ? 'down' : 'up';
|
const scrollDir = scrollPos > lastScrollPos ? 'down' : 'up';
|
||||||
lastScrollPos = scrollPos;
|
lastScrollPos = scrollPos;
|
||||||
return scrollDir;
|
return scrollDir;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
export function isVisible(
|
export function isVisible(
|
||||||
element: Element,
|
element: Element,
|
||||||
visRect: { left: number; right: number; top: number; bottom: number }
|
visRect: { left: number; right: number; top: number; bottom: number }
|
||||||
) {
|
) {
|
||||||
const rect = element.getBoundingClientRect();
|
const rect = element.getBoundingClientRect();
|
||||||
const vertInView = rect.top <= visRect.bottom && rect.bottom >= visRect.top;
|
const vertInView = rect.top <= visRect.bottom && rect.bottom >= visRect.top;
|
||||||
const horInView = rect.left <= visRect.right && rect.right >= visRect.left;
|
const horInView = rect.left <= visRect.right && rect.right >= visRect.left;
|
||||||
|
|
||||||
return vertInView && horInView;
|
return vertInView && horInView;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,35 @@
|
|||||||
import type { AuthorData, PostsData } from "$routes/blog/content";
|
import type { AuthorData, PostsData } from '$routes/blog/content';
|
||||||
|
|
||||||
export const DEFAULT_HOST = 'https://appwrite.io';
|
export const DEFAULT_HOST = 'https://appwrite.io';
|
||||||
export const DEFAULT_DESCRIPTION = 'Appwrite is an open-source platform for building applications at any scale, using your preferred programming languages and tools.';
|
export const DEFAULT_DESCRIPTION =
|
||||||
|
'Appwrite is an open-source platform for building applications at any scale, using your preferred programming languages and tools.';
|
||||||
export function buildOpenGraphImage(title: string, description: string): string {
|
export function buildOpenGraphImage(title: string, description: string): string {
|
||||||
return `https://og.appwrite.global/image.png?title=${encodeURIComponent(
|
return `https://og.appwrite.global/image.png?title=${encodeURIComponent(
|
||||||
title
|
title
|
||||||
)}&subtitle=${encodeURIComponent(description)}`;
|
)}&subtitle=${encodeURIComponent(description)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createSchemaAuthor(author: AuthorData): string {
|
export function createSchemaAuthor(author: AuthorData): string {
|
||||||
return (
|
return (
|
||||||
`< script type="application/ld+json">${JSON.stringify({
|
`< script type="application/ld+json">${JSON.stringify({
|
||||||
'@context': 'https://schema.org',
|
'@context': 'https://schema.org',
|
||||||
'@type': 'Person',
|
'@type': 'Person',
|
||||||
name: author.name,
|
name: author.name,
|
||||||
url: author.href,
|
url: author.href,
|
||||||
image: author.avatar
|
image: author.avatar
|
||||||
})}</` + 'script>'
|
})}</` + 'script>'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createSchemaPost(post: PostsData): string {
|
export function createSchemaPost(post: PostsData): string {
|
||||||
return (
|
return (
|
||||||
`< script type="application/ld+json">${JSON.stringify({
|
`< script type="application/ld+json">${JSON.stringify({
|
||||||
'@context': 'https://schema.org',
|
'@context': 'https://schema.org',
|
||||||
'@type': 'BlogPosting',
|
'@type': 'BlogPosting',
|
||||||
headline: post.title,
|
headline: post.title,
|
||||||
image: post.cover,
|
image: post.cover,
|
||||||
datePublished: post.date,
|
datePublished: post.date,
|
||||||
dateModified: post.date
|
dateModified: post.date
|
||||||
})}</` + 'script>'
|
})}</` + 'script>'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export const noop = () => {
|
export const noop = () => {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export function objectKeys<T extends object>(obj: T): Array<keyof T> {
|
export function objectKeys<T extends object>(obj: T): Array<keyof T> {
|
||||||
return Object.keys(obj) as Array<keyof T>;
|
return Object.keys(obj) as Array<keyof T>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export function randomPick<T>(arr: T[]): T {
|
export function randomPick<T>(arr: T[]): T {
|
||||||
return arr[Math.floor(Math.random() * arr.length)];
|
return arr[Math.floor(Math.random() * arr.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const deterministicRandom = <T>(options: T[], seed: string): T => {
|
export const deterministicRandom = <T>(options: T[], seed: string): T => {
|
||||||
|
|||||||
@@ -2,7 +2,16 @@ import { writable } from 'svelte/store';
|
|||||||
import type { Language } from './code';
|
import type { Language } from './code';
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
|
|
||||||
const allVersions = ['1.5.x', '1.4.x', '1.3.x', '1.2.x', '1.1.x', '1.0.x', '0.15.x', 'cloud'] as const;
|
const allVersions = [
|
||||||
|
'1.5.x',
|
||||||
|
'1.4.x',
|
||||||
|
'1.3.x',
|
||||||
|
'1.2.x',
|
||||||
|
'1.1.x',
|
||||||
|
'1.0.x',
|
||||||
|
'0.15.x',
|
||||||
|
'cloud'
|
||||||
|
] as const;
|
||||||
|
|
||||||
export type Version = (typeof allVersions)[number];
|
export type Version = (typeof allVersions)[number];
|
||||||
|
|
||||||
@@ -20,7 +29,7 @@ export enum Service {
|
|||||||
Locale = 'locale',
|
Locale = 'locale',
|
||||||
Storage = 'storage',
|
Storage = 'storage',
|
||||||
Teams = 'teams',
|
Teams = 'teams',
|
||||||
Users = 'users',
|
Users = 'users'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Platform {
|
export enum Platform {
|
||||||
@@ -114,7 +123,7 @@ export const serviceMap: Record<Service, string> = {
|
|||||||
[Service.Locale]: 'Locale',
|
[Service.Locale]: 'Locale',
|
||||||
[Service.Storage]: 'Storage',
|
[Service.Storage]: 'Storage',
|
||||||
[Service.Teams]: 'Teams',
|
[Service.Teams]: 'Teams',
|
||||||
[Service.Users]: 'Users',
|
[Service.Users]: 'Users'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const preferredVersion = writable<Version | null>(
|
export const preferredVersion = writable<Version | null>(
|
||||||
|
|||||||
@@ -52,11 +52,11 @@ export type AppwriteSchemaObject = OpenAPIV3.SchemaObject & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface Property {
|
export interface Property {
|
||||||
name: string;
|
name: string;
|
||||||
items?: {
|
items?: {
|
||||||
type?: string;
|
type?: string;
|
||||||
oneOf?: OpenAPIV3.ReferenceObject[];
|
oneOf?: OpenAPIV3.ReferenceObject[];
|
||||||
} & OpenAPIV3.ReferenceObject;
|
} & OpenAPIV3.ReferenceObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ModelType {
|
export enum ModelType {
|
||||||
@@ -182,7 +182,8 @@ export function getSchema(id: string, api: OpenAPIV3.Document): OpenAPIV3.Schema
|
|||||||
if (schema) {
|
if (schema) {
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
throw new Error(`Schema doesn't exist for id: ${id}`);}
|
throw new Error(`Schema doesn't exist for id: ${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
const specs = import.meta.glob(
|
const specs = import.meta.glob(
|
||||||
'$appwrite/app/config/specs/open-api3*-(client|server|console).json',
|
'$appwrite/app/config/specs/open-api3*-(client|server|console).json',
|
||||||
@@ -354,15 +355,18 @@ export function resolveReference(
|
|||||||
throw new Error("Schema doesn't exist");
|
throw new Error("Schema doesn't exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateExample = (schema: OpenAPIV3.SchemaObject, api: OpenAPIV3.Document<{}>, modelType: ModelType = ModelType.REST): Object => {
|
export const generateExample = (
|
||||||
|
schema: OpenAPIV3.SchemaObject,
|
||||||
const properties = Object.keys(schema.properties ?? {}).map((key) =>{
|
api: OpenAPIV3.Document<{}>,
|
||||||
|
modelType: ModelType = ModelType.REST
|
||||||
|
): Object => {
|
||||||
|
const properties = Object.keys(schema.properties ?? {}).map((key) => {
|
||||||
const name = key;
|
const name = key;
|
||||||
const fields = schema.properties?.[key];
|
const fields = schema.properties?.[key];
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
...fields
|
...fields
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const example = properties.reduce((carry, currentValue) => {
|
const example = properties.reduce((carry, currentValue) => {
|
||||||
@@ -370,29 +374,32 @@ export const generateExample = (schema: OpenAPIV3.SchemaObject, api: OpenAPIV3.D
|
|||||||
let propertyName;
|
let propertyName;
|
||||||
switch (modelType) {
|
switch (modelType) {
|
||||||
case ModelType.REST:
|
case ModelType.REST:
|
||||||
propertyName = property.name;
|
propertyName = property.name;
|
||||||
break;
|
break;
|
||||||
case ModelType.GRAPHQL:
|
case ModelType.GRAPHQL:
|
||||||
propertyName = property.name.replace('$', '_');
|
propertyName = property.name.replace('$', '_');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
propertyName = property.name;
|
propertyName = property.name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property.type === 'array') {
|
if (property.type === 'array') {
|
||||||
// If it's an array type containing primatives
|
// If it's an array type containing primatives
|
||||||
if (property.items?.type){
|
if (property.items?.type) {
|
||||||
return {
|
return {
|
||||||
...carry,
|
...carry,
|
||||||
[propertyName]: property['x-example']
|
[propertyName]: property['x-example']
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property.items && 'anyOf' in property.items) {
|
if (property.items && 'anyOf' in property.items) {
|
||||||
// default to first child type if multiple available
|
// default to first child type if multiple available
|
||||||
const firstSchema = (property.items as unknown as AppwriteSchemaObject)?.anyOf?.[0];
|
const firstSchema = (property.items as unknown as AppwriteSchemaObject)?.anyOf?.[0];
|
||||||
const schema = getSchema(getIdFromReference(firstSchema as OpenAPIV3.ReferenceObject), api)
|
const schema = getSchema(
|
||||||
|
getIdFromReference(firstSchema as OpenAPIV3.ReferenceObject),
|
||||||
|
api
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...carry,
|
...carry,
|
||||||
@@ -401,37 +408,43 @@ export const generateExample = (schema: OpenAPIV3.SchemaObject, api: OpenAPIV3.D
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if an array of objects without child types
|
// if an array of objects without child types
|
||||||
const schema = getSchema(getIdFromReference(property.items as OpenAPIV3.ReferenceObject), api);
|
const schema = getSchema(
|
||||||
|
getIdFromReference(property.items as OpenAPIV3.ReferenceObject),
|
||||||
|
api
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
...carry,
|
...carry,
|
||||||
[propertyName]: [generateExample(schema, api, modelType)]
|
[propertyName]: [generateExample(schema, api, modelType)]
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's an object type, but not in an array.
|
// If it's an object type, but not in an array.
|
||||||
if (property.type === 'object') {
|
if (property.type === 'object') {
|
||||||
if (property.items?.oneOf){
|
if (property.items?.oneOf) {
|
||||||
// default to first child type if multiple available
|
// default to first child type if multiple available
|
||||||
const schema = getSchema(getIdFromReference(property.items.oneOf[0] as OpenAPIV3.ReferenceObject), api);
|
const schema = getSchema(
|
||||||
|
getIdFromReference(property.items.oneOf[0] as OpenAPIV3.ReferenceObject),
|
||||||
|
api
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
...carry,
|
...carry,
|
||||||
[propertyName]: generateExample(schema, api, modelType)
|
[propertyName]: generateExample(schema, api, modelType)
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property.items){
|
if (property.items) {
|
||||||
const schema = getSchema(getIdFromReference(property.items), api);
|
const schema = getSchema(getIdFromReference(property.items), api);
|
||||||
return {
|
return {
|
||||||
...carry,
|
...carry,
|
||||||
[propertyName]: generateExample(schema, api, modelType)
|
[propertyName]: generateExample(schema, api, modelType)
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...carry,
|
...carry,
|
||||||
[propertyName]: property['x-example']
|
[propertyName]: property['x-example']
|
||||||
}
|
};
|
||||||
}, {});
|
}, {});
|
||||||
return example;
|
return example;
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
type UnknownFn = (...args: any[]) => any;
|
type UnknownFn = (...args: any[]) => any;
|
||||||
|
|
||||||
export type TestCases<Fn extends UnknownFn> = {
|
export type TestCases<Fn extends UnknownFn> = {
|
||||||
args: Parameters<Fn>;
|
args: Parameters<Fn>;
|
||||||
expected: ReturnType<Fn>;
|
expected: ReturnType<Fn>;
|
||||||
}[];
|
}[];
|
||||||
|
|||||||
@@ -4,24 +4,24 @@ import { toScale } from './toScale';
|
|||||||
import type { TestCases } from './test';
|
import type { TestCases } from './test';
|
||||||
|
|
||||||
const testCases: TestCases<typeof toScale> = [
|
const testCases: TestCases<typeof toScale> = [
|
||||||
{
|
{
|
||||||
args: [5, [0, 10], [0, 100]],
|
args: [5, [0, 10], [0, 100]],
|
||||||
expected: 50
|
expected: 50
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: [0.5, [0, 1], [0, 100]],
|
args: [0.5, [0, 1], [0, 100]],
|
||||||
expected: 50
|
expected: 50
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: [0.4, [0.2, 1], [0, 1]],
|
args: [0.4, [0.2, 1], [0, 1]],
|
||||||
expected: 0.25
|
expected: 0.25
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('toScale', () => {
|
describe('toScale', () => {
|
||||||
testCases.forEach(({ args, expected }) => {
|
testCases.forEach(({ args, expected }) => {
|
||||||
it(`should return ${expected} when given ${JSON.stringify(args)}`, () => {
|
it(`should return ${expected} when given ${JSON.stringify(args)}`, () => {
|
||||||
expect(toScale(...args)).toBe(expected);
|
expect(toScale(...args)).toBe(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ export type Scale = [number, number];
|
|||||||
* `to` { lower: 0, upper: 100 } => `number` 30
|
* `to` { lower: 0, upper: 100 } => `number` 30
|
||||||
*/
|
*/
|
||||||
export function toScale(value: number, from: Scale, to: Scale): number {
|
export function toScale(value: number, from: Scale, to: Scale): number {
|
||||||
return ((value - from[0]) * (to[1] - to[0])) / (from[1] - from[0]) + to[0];
|
return ((value - from[0]) * (to[1] - to[0])) / (from[1] - from[0]) + to[0];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,21 +2,21 @@ import { base } from '$app/paths';
|
|||||||
import type { Tutorial } from '$markdoc/layouts/Tutorial.svelte';
|
import type { Tutorial } from '$markdoc/layouts/Tutorial.svelte';
|
||||||
|
|
||||||
export function globToTutorial(data: { tutorials: Record<string, unknown>; pathname: string }) {
|
export function globToTutorial(data: { tutorials: Record<string, unknown>; pathname: string }) {
|
||||||
return Object.entries(data.tutorials)
|
return Object.entries(data.tutorials)
|
||||||
.map(([filepath, tutorial]) => {
|
.map(([filepath, tutorial]) => {
|
||||||
const { frontmatter } = tutorial as {
|
const { frontmatter } = tutorial as {
|
||||||
frontmatter: Tutorial;
|
frontmatter: Tutorial;
|
||||||
};
|
};
|
||||||
const slug = filepath.replace('./', '').replace('/+page.markdoc', '');
|
const slug = filepath.replace('./', '').replace('/+page.markdoc', '');
|
||||||
const tutorialName = data.pathname.split('/').slice(0, -1).join('/');
|
const tutorialName = data.pathname.split('/').slice(0, -1).join('/');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: frontmatter.title,
|
title: frontmatter.title,
|
||||||
step: frontmatter.step,
|
step: frontmatter.step,
|
||||||
href: `${base}${tutorialName}/${slug}`
|
href: `${base}${tutorialName}/${slug}`
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return a.step - b.step;
|
return a.step - b.step;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,10 +45,8 @@
|
|||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<Main>
|
<Main>
|
||||||
<div class="web-big-padding-section-level-1 u-position-relative u-overflow-hidden">
|
<div class="web-big-padding-section-level-1 relative overflow-hidden">
|
||||||
<div
|
<div class="absolute u-inset-inline-start-0 u-inset-block-end-0 web-u-pointer-events-none">
|
||||||
class="u-position-absolute u-inset-inline-start-0 u-inset-block-end-0 web-u-pointer-events-none"
|
|
||||||
>
|
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="660"
|
width="660"
|
||||||
@@ -102,9 +100,9 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="web-big-padding-section-level-2 u-position-relative">
|
<div class="web-big-padding-section-level-2 relative">
|
||||||
<div class="web-container">
|
<div class="web-container">
|
||||||
<div class="web-author-section u-block">
|
<div class="web-author-section block">
|
||||||
{#if avatar}
|
{#if avatar}
|
||||||
<FloatingHead --position="relative" src={avatar} alt={name} size={112} />
|
<FloatingHead --position="relative" src={avatar} alt={name} size={112} />
|
||||||
{/if}
|
{/if}
|
||||||
@@ -119,7 +117,7 @@
|
|||||||
{bio}
|
{bio}
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
<ul class="u-flex u-main-center u-gap-8 u-margin-block-start-16">
|
<ul class="flex u-main-center gap-2 u-margin-block-start-16">
|
||||||
{#if github}
|
{#if github}
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
@@ -171,7 +169,7 @@
|
|||||||
<h2 class="web-title web-u-color-text-primary">Articles</h2>
|
<h2 class="web-title web-u-color-text-primary">Articles</h2>
|
||||||
|
|
||||||
<!-- <div class="web-is-only-mobile u-margin-block-start-32">
|
<!-- <div class="web-is-only-mobile u-margin-block-start-32">
|
||||||
<label class="u-block web-select is-colored" for="articles">
|
<label class="block web-select is-colored" for="articles">
|
||||||
<select id="articles">
|
<select id="articles">
|
||||||
<option>Latest</option>
|
<option>Latest</option>
|
||||||
<option>News</option>
|
<option>News</option>
|
||||||
@@ -183,7 +181,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div> -->
|
</div> -->
|
||||||
<!--<div class="web-is-not-mobile">
|
<!--<div class="web-is-not-mobile">
|
||||||
<div class="u-flex u-main-space-between u-gap-16 u-margin-block-start-24">
|
<div class="flex u-main-space-between gap-4 u-margin-block-start-24">
|
||||||
<ul
|
<ul
|
||||||
class="web-secondary-tabs is-transparent"
|
class="web-secondary-tabs is-transparent"
|
||||||
role="tablist"
|
role="tablist"
|
||||||
@@ -264,7 +262,7 @@
|
|||||||
</ul> -->
|
</ul> -->
|
||||||
<!-- <div class="web-input-text-search-wrapper">
|
<!-- <div class="web-input-text-search-wrapper">
|
||||||
<span class="icon-search" aria-hidden="true" />
|
<span class="icon-search" aria-hidden="true" />
|
||||||
<input class="web-input-text web-u-block-size-48" type="search" placeholder="Search" />
|
<input class="web-input-text web-block-size-48" type="search" placeholder="Search" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>-->
|
</div>-->
|
||||||
@@ -287,7 +285,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="web-big-padding-section-level-2 is-margin-replace-padding u-position-relative u-overflow-hidden"
|
class="web-big-padding-section-level-2 is-margin-replace-padding relative overflow-hidden"
|
||||||
>
|
>
|
||||||
<div class="web-container">
|
<div class="web-container">
|
||||||
<FooterNav />
|
<FooterNav />
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- <div class="web-input-text-search-wrapper u-inline-width-100-percent-mobile">
|
<!-- <div class="web-input-text-search-wrapper u-inline-width-100-percent-mobile">
|
||||||
<span class="icon-search" aria-hidden="true" />
|
<span class="icon-search" aria-hidden="true" />
|
||||||
<input class="web-input-text web-u-block-size-48" type="search" placeholder="Search" />
|
<input class="web-input-text web-block-size-48" type="search" placeholder="Search" />
|
||||||
</div> -->
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="web-big-padding-section-level-2 is-margin-replace-padding u-position-relative u-overflow-hidden"
|
class="web-big-padding-section-level-2 is-margin-replace-padding relative overflow-hidden"
|
||||||
>
|
>
|
||||||
<div class="web-container">
|
<div class="web-container">
|
||||||
<FooterNav />
|
<FooterNav />
|
||||||
|
|||||||
@@ -72,7 +72,7 @@
|
|||||||
<h1 class="web-title web-u-color-text-primary">{title}</h1>
|
<h1 class="web-title web-u-color-text-primary">{title}</h1>
|
||||||
</header>
|
</header>
|
||||||
<button
|
<button
|
||||||
class="toc-btn u-position-sticky u-flex u-width-full-line u-main-space-between u-cross-center
|
class="toc-btn sticky flex u-width-full-line u-main-space-between u-cross-center
|
||||||
web-u-padding-20 web-u-margin-inline-20-negative web-u-color-text-primary web-is-only-mobile
|
web-u-padding-20 web-u-margin-inline-20-negative web-u-color-text-primary web-is-only-mobile
|
||||||
u-margin-block-start-24 web-u-sep-block web-u-filter-blur-8"
|
u-margin-block-start-24 web-u-sep-block web-u-filter-blur-8"
|
||||||
style:--inset-block-start="4.5rem"
|
style:--inset-block-start="4.5rem"
|
||||||
|
|||||||
@@ -88,10 +88,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{#if authorData}
|
{#if authorData}
|
||||||
<div class="web-author u-margin-block-start-16">
|
<div class="web-author u-margin-block-start-16">
|
||||||
<a
|
<a href={authorData.href} class="flex u-cross-center gap-2">
|
||||||
href={authorData.href}
|
|
||||||
class="u-flex u-cross-center u-gap-8"
|
|
||||||
>
|
|
||||||
{#if authorData.avatar}
|
{#if authorData.avatar}
|
||||||
<img
|
<img
|
||||||
class="web-author-image"
|
class="web-author-image"
|
||||||
@@ -103,13 +100,15 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="u-flex-vertical">
|
<div class="u-flex-vertical">
|
||||||
<h4 class="web-sub-body-400 web-u-color-text-primary">
|
<h4
|
||||||
|
class="web-sub-body-400 web-u-color-text-primary"
|
||||||
|
>
|
||||||
{authorData.name}
|
{authorData.name}
|
||||||
</h4>
|
</h4>
|
||||||
<p class="web-caption-400">{authorData.role}</p>
|
<p class="web-caption-400">{authorData.role}</p>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<!-- <ul class="u-flex u-gap-8 u-margin-inline-start-auto u-cross-child-center">
|
<!-- <ul class="flex gap-2 u-margin-inline-start-auto u-cross-child-center">
|
||||||
{#if authorData.twitter}
|
{#if authorData.twitter}
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
@@ -155,7 +154,7 @@
|
|||||||
</header>
|
</header>
|
||||||
{#if cover}
|
{#if cover}
|
||||||
<div class="web-media-container">
|
<div class="web-media-container">
|
||||||
<Media class="u-block" src={cover} />
|
<Media class="block" src={cover} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -164,7 +163,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<!-- {#if categories?.length}
|
<!-- {#if categories?.length}
|
||||||
<div class="u-flex u-gap-16">
|
<div class="flex gap-4">
|
||||||
{#each categories as cat}
|
{#each categories as cat}
|
||||||
<a href={cat.href} class="web-tag">{cat.name}</a>
|
<a href={cat.href} class="web-tag">{cat.name}</a>
|
||||||
{/each}
|
{/each}
|
||||||
@@ -200,7 +199,7 @@
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="web-big-padding-section-level-2 u-position-relative u-overflow-hidden">
|
<div class="web-big-padding-section-level-2 relative overflow-hidden">
|
||||||
<div class="web-container">
|
<div class="web-container">
|
||||||
<Newsletter />
|
<Newsletter />
|
||||||
<FooterNav />
|
<FooterNav />
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { setContext } from "svelte";
|
import { setContext } from 'svelte';
|
||||||
|
|
||||||
setContext("no-paragraph", true);
|
setContext('no-paragraph', true);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<blockquote class="web-blockquote">
|
<blockquote class="web-blockquote">
|
||||||
<p class="web-description">
|
<p class="web-description">
|
||||||
<slot />
|
<slot />
|
||||||
</p>
|
</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let content: string;
|
export let content: string;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<span class="web-inline-code web-code">{content}</span>
|
<span class="web-inline-code web-code">{content}</span>
|
||||||
|
|||||||
@@ -65,13 +65,13 @@
|
|||||||
<header class="web-code-snippet-header">
|
<header class="web-code-snippet-header">
|
||||||
<div class="web-code-snippet-header-start">
|
<div class="web-code-snippet-header-start">
|
||||||
{#if badgeValue}
|
{#if badgeValue}
|
||||||
<div class="u-flex u-gap-16">
|
<div class="flex gap-4">
|
||||||
<div class="web-tag"><span class="text">{badgeValue}</span></div>
|
<div class="web-tag"><span class="text">{badgeValue}</span></div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="web-code-snippet-header-end">
|
<div class="web-code-snippet-header-end">
|
||||||
<ul class="buttons-list u-flex u-gap-8">
|
<ul class="buttons-list flex gap-2">
|
||||||
<li class="buttons-list-item web-u-padding-inline-start-20">
|
<li class="buttons-list-item web-u-padding-inline-start-20">
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<strong class="u-bold"><slot /></strong>
|
<strong class="u-bold"><slot /></strong>
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLTdAttributes } from 'svelte/elements';
|
import type { HTMLTdAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
export let align: HTMLTdAttributes['align'] = undefined;
|
export let align: HTMLTdAttributes['align'] = undefined;
|
||||||
export let width: HTMLTdAttributes['width'] = undefined;
|
export let width: HTMLTdAttributes['width'] = undefined;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
style:width={width ? `${width}px` : undefined}
|
style:width={width ? `${width}px` : undefined}
|
||||||
style:min-inline-size={width ? 'unset' : undefined}
|
style:min-inline-size={width ? 'unset' : undefined}
|
||||||
role="columnheader"
|
role="columnheader"
|
||||||
class="web-table-head-col"
|
class="web-table-head-col"
|
||||||
{align}
|
{align}
|
||||||
>
|
>
|
||||||
<span class="web-eyebrow">
|
<span class="web-eyebrow">
|
||||||
<slot />
|
<slot />
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<tr class="web-table-row">
|
<tr class="web-table-row">
|
||||||
<slot />
|
<slot />
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<script context="module">
|
<script context="module">
|
||||||
export { default as Blockquote } from './Blockquote.svelte';
|
export { default as Blockquote } from './Blockquote.svelte';
|
||||||
export { default as Code } from './Code.svelte';
|
export { default as Code } from './Code.svelte';
|
||||||
export { default as Fence } from './Fence.svelte';
|
export { default as Fence } from './Fence.svelte';
|
||||||
export { default as Heading } from './Heading.svelte';
|
export { default as Heading } from './Heading.svelte';
|
||||||
export { default as List } from './List.svelte';
|
export { default as List } from './List.svelte';
|
||||||
export { default as Paragraph } from './Paragraph.svelte';
|
export { default as Paragraph } from './Paragraph.svelte';
|
||||||
export { default as Strong } from './Strong.svelte';
|
export { default as Strong } from './Strong.svelte';
|
||||||
export { default as Image } from './Image.svelte';
|
export { default as Image } from './Image.svelte';
|
||||||
export { default as Item } from './Item.svelte';
|
export { default as Item } from './Item.svelte';
|
||||||
export { default as Link } from './Link.svelte';
|
export { default as Link } from './Link.svelte';
|
||||||
export { default as Table } from './Table.svelte';
|
export { default as Table } from './Table.svelte';
|
||||||
export { default as Tbody } from './Tbody.svelte';
|
export { default as Tbody } from './Tbody.svelte';
|
||||||
export { default as Td } from './Td.svelte';
|
export { default as Td } from './Td.svelte';
|
||||||
export { default as Th } from './Th.svelte';
|
export { default as Th } from './Th.svelte';
|
||||||
export { default as Thead } from './Thead.svelte';
|
export { default as Thead } from './Thead.svelte';
|
||||||
export { default as Tr } from './Tr.svelte';
|
export { default as Tr } from './Tr.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user