Compare commits
	
		
			93 Commits
		
	
	
		
			da1123d84b
			...
			develop/fu
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2c5adad2fc | ||
| 
						 | 
					7d8439c615 | ||
| 
						 | 
					ebfb103911 | ||
| 
						 | 
					b1b87d3b52 | ||
| 
						 | 
					8811398040 | ||
| 
						 | 
					653ce3cb19 | ||
| 
						 | 
					eadbedb713 | ||
| 
						 | 
					37cd6d3ab5 | ||
| 
						 | 
					88be3a045b | ||
| 
						 | 
					45b51ab156 | ||
| 
						 | 
					3bee01cfa7 | ||
| 
						 | 
					567c6a8758 | ||
| 
						 | 
					81a91da743 | ||
| 
						 | 
					70a61ee1eb | ||
| 
						 | 
					9d89a4413b | ||
| 
						 | 
					6ea17d54c6 | ||
| 
						 | 
					11a828b073 | ||
| 
						 | 
					37022fb11e | ||
| 
						 | 
					dd50d4927b | ||
| 
						 | 
					fdaf3af3af | ||
| 
						 | 
					3f2a8f862c | ||
| 
						 | 
					58c7be6e95 | ||
| 
						 | 
					829b4e7134 | ||
| 
						 | 
					77870b39cc | ||
| 
						 | 
					8e0ae9b867 | ||
| 
						 | 
					543f1df5ce | ||
| 
						 | 
					341aae4587 | ||
| 
						 | 
					7f62907385 | ||
| 
						 | 
					7c4aa683a2 | ||
| 
						 | 
					b48b0eeb0e | ||
| 
						 | 
					cddc793915 | ||
| 
						 | 
					94e6db10bb | ||
| 
						 | 
					26e1d5fec3 | ||
| 
						 | 
					66be87b688 | ||
| 
						 | 
					f7b4e32218 | ||
| 
						 | 
					57407112fb | ||
| 
						 | 
					b280cc2e01 | ||
| 
						 | 
					e6ebf892c5 | ||
| 
						 | 
					b754641058 | ||
| 
						 | 
					722f4f760e | ||
| 
						 | 
					01e04a209f | ||
| 
						 | 
					0299fd1ea0 | ||
| 
						 | 
					cf8dec53ca | ||
| 
						 | 
					d5c012d748 | ||
| 
						 | 
					2ccbd9a44c | ||
| 
						 | 
					ccd89d48d9 | ||
| 
						 | 
					87d788ddef | ||
| 
						 | 
					809b625a34 | ||
| 
						 | 
					95c753a549 | ||
| 
						 | 
					0bb8b7ec5c | ||
| 
						 | 
					c6d084f5dc | ||
| 
						 | 
					0024ce36c8 | ||
| 
						 | 
					c44e746807 | ||
| 
						 | 
					b1826066f4 | ||
| 
						 | 
					b0b8acc45b | ||
| 
						 | 
					e2b9ffc072 | ||
| 
						 | 
					68c43ea372 | ||
| 
						 | 
					3b46baca4f | ||
| 
						 | 
					772e461c08 | ||
| 
						 | 
					5c6018a0f9 | ||
| 
						 | 
					0b7989c3d3 | ||
| 
						 | 
					8cfcc3e39c | ||
| 
						 | 
					3a57261590 | ||
| 
						 | 
					a86a1a461c | ||
| 
						 | 
					2257e1df0c | ||
| 
						 | 
					ccb72c8970 | ||
| 
						 | 
					740ff941a5 | ||
| 
						 | 
					117a683d9a | ||
| 
						 | 
					9eba4b7373 | ||
| 
						 | 
					91306dc0c7 | ||
| 
						 | 
					1716dd5a65 | ||
| 
						 | 
					66f9a674f1 | ||
| 
						 | 
					41fc5274ff | ||
| 
						 | 
					bcebdb5fd9 | ||
| 
						 | 
					876487ad11 | ||
| 
						 | 
					18da75ad97 | ||
| 
						 | 
					c80ac1415d | ||
| 
						 | 
					bb21184ea2 | ||
| 
						 | 
					0c3740fdf2 | ||
| 
						 | 
					701819d018 | ||
| 
						 | 
					68e151b2bd | ||
| 
						 | 
					06ff272541 | ||
| 
						 | 
					4154d5e4b1 | ||
| 
						 | 
					1862491496 | ||
| 
						 | 
					073b5e897c | ||
| 
						 | 
					7e1d6ebd19 | ||
| 
						 | 
					9a332e79e4 | ||
| 
						 | 
					72450b9217 | ||
| 
						 | 
					7e1dc33a08 | ||
| 
						 | 
					aa240009ab | ||
| 
						 | 
					41b258e4d8 | ||
| 
						 | 
					28b9cca413 | ||
| 
						 | 
					8aaee2c40c | 
							
								
								
									
										0
									
								
								.assets/manifest.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -37,3 +37,5 @@ Thumbs.db
 | 
			
		||||
# Db
 | 
			
		||||
db.sqlite
 | 
			
		||||
/searxng
 | 
			
		||||
 | 
			
		||||
certificates
 | 
			
		||||
							
								
								
									
										10
									
								
								README.md
									
									
									
									
									
								
							
							
						
						@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
<hr/>
 | 
			
		||||
 | 
			
		||||
[](https://discord.gg/26aArMy8tT)
 | 
			
		||||
[](https://discord.gg/26aArMy8tT)
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
@@ -90,6 +90,9 @@ There are mainly 2 ways of installing Perplexica - With Docker, Without Docker.
 | 
			
		||||
   - `OLLAMA`: Your Ollama API URL. You should enter it as `http://host.docker.internal:PORT_NUMBER`. If you installed Ollama on port 11434, use `http://host.docker.internal:11434`. For other ports, adjust accordingly. **You need to fill this if you wish to use Ollama's models instead of OpenAI's**.
 | 
			
		||||
   - `GROQ`: Your Groq API key. **You only need to fill this if you wish to use Groq's hosted models**.
 | 
			
		||||
   - `ANTHROPIC`: Your Anthropic API key. **You only need to fill this if you wish to use Anthropic models**.
 | 
			
		||||
   - `Gemini`: Your Gemini API key. **You only need to fill this if you wish to use Google's models**.
 | 
			
		||||
   - `DEEPSEEK`: Your Deepseek API key. **Only needed if you want Deepseek models.**
 | 
			
		||||
   - `AIMLAPI`: Your AI/ML API key. **Only needed if you want to use AI/ML API models and embeddings.**
 | 
			
		||||
 | 
			
		||||
     **Note**: You can change these after starting Perplexica from the settings dialog.
 | 
			
		||||
 | 
			
		||||
@@ -111,7 +114,7 @@ There are mainly 2 ways of installing Perplexica - With Docker, Without Docker.
 | 
			
		||||
2. Clone the repository and rename the `sample.config.toml` file to `config.toml` in the root directory. Ensure you complete all required fields in this file.
 | 
			
		||||
3. After populating the configuration run `npm i`.
 | 
			
		||||
4. Install the dependencies and then execute `npm run build`.
 | 
			
		||||
5. Finally, start the app by running `npm rum start`
 | 
			
		||||
5. Finally, start the app by running `npm run start`
 | 
			
		||||
 | 
			
		||||
**Note**: Using Docker is recommended as it simplifies the setup process, especially for managing environment variables and dependencies.
 | 
			
		||||
 | 
			
		||||
@@ -132,7 +135,7 @@ If you're encountering an Ollama connection error, it is likely due to the backe
 | 
			
		||||
 | 
			
		||||
3. **Linux Users - Expose Ollama to Network:**
 | 
			
		||||
 | 
			
		||||
   - Inside `/etc/systemd/system/ollama.service`, you need to add `Environment="OLLAMA_HOST=0.0.0.0"`. Then restart Ollama by `systemctl restart ollama`. For more information see [Ollama docs](https://github.com/ollama/ollama/blob/main/docs/faq.md#setting-environment-variables-on-linux)
 | 
			
		||||
   - Inside `/etc/systemd/system/ollama.service`, you need to add `Environment="OLLAMA_HOST=0.0.0.0:11434"`. (Change the port number if you are using a different one.) Then reload the systemd manager configuration with `systemctl daemon-reload`, and restart Ollama by `systemctl restart ollama`. For more information see [Ollama docs](https://github.com/ollama/ollama/blob/main/docs/faq.md#setting-environment-variables-on-linux)
 | 
			
		||||
 | 
			
		||||
   - Ensure that the port (default is 11434) is not blocked by your firewall.
 | 
			
		||||
 | 
			
		||||
@@ -159,6 +162,7 @@ Perplexica runs on Next.js and handles all API requests. It works right away on
 | 
			
		||||
 | 
			
		||||
[](https://usw.sealos.io/?openapp=system-template%3FtemplateName%3Dperplexica)
 | 
			
		||||
[](https://repocloud.io/details/?app_id=267)
 | 
			
		||||
[](https://template.run.claw.cloud/?referralCode=U11MRQ8U9RM4&openapp=system-fastdeploy%3FtemplateName%3Dperplexica)
 | 
			
		||||
 | 
			
		||||
## Upcoming Features
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,9 @@ COPY public ./public
 | 
			
		||||
RUN mkdir -p /home/perplexica/data
 | 
			
		||||
RUN yarn build
 | 
			
		||||
 | 
			
		||||
RUN yarn add --dev @vercel/ncc
 | 
			
		||||
RUN yarn ncc build ./src/lib/db/migrate.ts -o migrator
 | 
			
		||||
 | 
			
		||||
FROM node:20.18.0-slim
 | 
			
		||||
 | 
			
		||||
WORKDIR /home/perplexica
 | 
			
		||||
@@ -21,7 +24,12 @@ COPY --from=builder /home/perplexica/.next/static ./public/_next/static
 | 
			
		||||
 | 
			
		||||
COPY --from=builder /home/perplexica/.next/standalone ./
 | 
			
		||||
COPY --from=builder /home/perplexica/data ./data
 | 
			
		||||
COPY drizzle ./drizzle
 | 
			
		||||
COPY --from=builder /home/perplexica/migrator/build ./build
 | 
			
		||||
COPY --from=builder /home/perplexica/migrator/index.js ./migrate.js
 | 
			
		||||
 | 
			
		||||
RUN mkdir /home/perplexica/uploads
 | 
			
		||||
 | 
			
		||||
CMD ["node", "server.js"]
 | 
			
		||||
COPY entrypoint.sh ./entrypoint.sh
 | 
			
		||||
RUN chmod +x ./entrypoint.sh
 | 
			
		||||
CMD ["./entrypoint.sh"]
 | 
			
		||||
@@ -16,6 +16,7 @@ services:
 | 
			
		||||
      dockerfile: app.dockerfile
 | 
			
		||||
    environment:
 | 
			
		||||
      - SEARXNG_API_URL=http://searxng:8080
 | 
			
		||||
      - DATA_DIR=/home/perplexica
 | 
			
		||||
    ports:
 | 
			
		||||
      - 3000:3000
 | 
			
		||||
    networks:
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,6 @@ To update Perplexica to the latest version, follow these steps:
 | 
			
		||||
3. Check for changes in the configuration files. If the `sample.config.toml` file contains new fields, delete your existing `config.toml` file, rename `sample.config.toml` to `config.toml`, and update the configuration accordingly.
 | 
			
		||||
4. After populating the configuration run `npm i`.
 | 
			
		||||
5. Install the dependencies and then execute `npm run build`.
 | 
			
		||||
6. Finally, start the app by running `npm rum start`
 | 
			
		||||
6. Finally, start the app by running `npm run start`
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,11 @@
 | 
			
		||||
import { defineConfig } from 'drizzle-kit';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
 | 
			
		||||
export default defineConfig({
 | 
			
		||||
  dialect: 'sqlite',
 | 
			
		||||
  schema: './src/lib/db/schema.ts',
 | 
			
		||||
  out: './drizzle',
 | 
			
		||||
  dbCredentials: {
 | 
			
		||||
    url: './data/db.sqlite',
 | 
			
		||||
    url: path.join(process.cwd(), 'data', 'db.sqlite'),
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								drizzle/0000_fuzzy_randall.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,16 @@
 | 
			
		||||
CREATE TABLE IF NOT EXISTS `chats` (
 | 
			
		||||
	`id` text PRIMARY KEY NOT NULL,
 | 
			
		||||
	`title` text NOT NULL,
 | 
			
		||||
	`createdAt` text NOT NULL,
 | 
			
		||||
	`focusMode` text NOT NULL,
 | 
			
		||||
	`files` text DEFAULT '[]'
 | 
			
		||||
);
 | 
			
		||||
--> statement-breakpoint
 | 
			
		||||
CREATE TABLE IF NOT EXISTS `messages` (
 | 
			
		||||
	`id` integer PRIMARY KEY NOT NULL,
 | 
			
		||||
	`content` text NOT NULL,
 | 
			
		||||
	`chatId` text NOT NULL,
 | 
			
		||||
	`messageId` text NOT NULL,
 | 
			
		||||
	`type` text,
 | 
			
		||||
	`metadata` text
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										116
									
								
								drizzle/meta/0000_snapshot.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,116 @@
 | 
			
		||||
{
 | 
			
		||||
  "version": "6",
 | 
			
		||||
  "dialect": "sqlite",
 | 
			
		||||
  "id": "ef3a044b-0f34-40b5-babb-2bb3a909ba27",
 | 
			
		||||
  "prevId": "00000000-0000-0000-0000-000000000000",
 | 
			
		||||
  "tables": {
 | 
			
		||||
    "chats": {
 | 
			
		||||
      "name": "chats",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "autoincrement": false
 | 
			
		||||
        },
 | 
			
		||||
        "title": {
 | 
			
		||||
          "name": "title",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "autoincrement": false
 | 
			
		||||
        },
 | 
			
		||||
        "createdAt": {
 | 
			
		||||
          "name": "createdAt",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "autoincrement": false
 | 
			
		||||
        },
 | 
			
		||||
        "focusMode": {
 | 
			
		||||
          "name": "focusMode",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "autoincrement": false
 | 
			
		||||
        },
 | 
			
		||||
        "files": {
 | 
			
		||||
          "name": "files",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false,
 | 
			
		||||
          "autoincrement": false,
 | 
			
		||||
          "default": "'[]'"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {},
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {},
 | 
			
		||||
      "checkConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "messages": {
 | 
			
		||||
      "name": "messages",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "integer",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "autoincrement": false
 | 
			
		||||
        },
 | 
			
		||||
        "content": {
 | 
			
		||||
          "name": "content",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "autoincrement": false
 | 
			
		||||
        },
 | 
			
		||||
        "chatId": {
 | 
			
		||||
          "name": "chatId",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "autoincrement": false
 | 
			
		||||
        },
 | 
			
		||||
        "messageId": {
 | 
			
		||||
          "name": "messageId",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "autoincrement": false
 | 
			
		||||
        },
 | 
			
		||||
        "type": {
 | 
			
		||||
          "name": "type",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false,
 | 
			
		||||
          "autoincrement": false
 | 
			
		||||
        },
 | 
			
		||||
        "metadata": {
 | 
			
		||||
          "name": "metadata",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false,
 | 
			
		||||
          "autoincrement": false
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {},
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {},
 | 
			
		||||
      "checkConstraints": {}
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "views": {},
 | 
			
		||||
  "enums": {},
 | 
			
		||||
  "_meta": {
 | 
			
		||||
    "schemas": {},
 | 
			
		||||
    "tables": {},
 | 
			
		||||
    "columns": {}
 | 
			
		||||
  },
 | 
			
		||||
  "internal": {
 | 
			
		||||
    "indexes": {}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								drizzle/meta/_journal.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,13 @@
 | 
			
		||||
{
 | 
			
		||||
  "version": "7",
 | 
			
		||||
  "dialect": "sqlite",
 | 
			
		||||
  "entries": [
 | 
			
		||||
    {
 | 
			
		||||
      "idx": 0,
 | 
			
		||||
      "version": "6",
 | 
			
		||||
      "when": 1748405503809,
 | 
			
		||||
      "tag": "0000_fuzzy_randall",
 | 
			
		||||
      "breakpoints": true
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								entrypoint.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,6 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
node migrate.js
 | 
			
		||||
 | 
			
		||||
exec node server.js
 | 
			
		||||
							
								
								
									
										24
									
								
								package.json
									
									
									
									
									
								
							
							
						
						@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "perplexica-frontend",
 | 
			
		||||
  "version": "1.10.2",
 | 
			
		||||
  "version": "1.11.0-rc2",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "author": "ItzCrazyKns",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
@@ -15,11 +15,14 @@
 | 
			
		||||
    "@headlessui/react": "^2.2.0",
 | 
			
		||||
    "@iarna/toml": "^2.2.5",
 | 
			
		||||
    "@icons-pack/react-simple-icons": "^12.3.0",
 | 
			
		||||
    "@langchain/anthropic": "^0.3.15",
 | 
			
		||||
    "@langchain/community": "^0.3.36",
 | 
			
		||||
    "@langchain/core": "^0.3.42",
 | 
			
		||||
    "@langchain/google-genai": "^0.1.12",
 | 
			
		||||
    "@langchain/openai": "^0.0.25",
 | 
			
		||||
    "@langchain/anthropic": "^0.3.24",
 | 
			
		||||
    "@langchain/community": "^0.3.49",
 | 
			
		||||
    "@langchain/core": "^0.3.66",
 | 
			
		||||
    "@langchain/google-genai": "^0.2.15",
 | 
			
		||||
    "@langchain/groq": "^0.2.3",
 | 
			
		||||
    "@langchain/langgraph": "^0.4.0",
 | 
			
		||||
    "@langchain/ollama": "^0.2.3",
 | 
			
		||||
    "@langchain/openai": "^0.6.2",
 | 
			
		||||
    "@langchain/textsplitters": "^0.1.0",
 | 
			
		||||
    "@tailwindcss/typography": "^0.5.12",
 | 
			
		||||
    "@xenova/transformers": "^2.17.2",
 | 
			
		||||
@@ -30,14 +33,17 @@
 | 
			
		||||
    "compute-dot": "^1.1.0",
 | 
			
		||||
    "drizzle-orm": "^0.40.1",
 | 
			
		||||
    "html-to-text": "^9.0.5",
 | 
			
		||||
    "langchain": "^0.1.30",
 | 
			
		||||
    "jspdf": "^3.0.1",
 | 
			
		||||
    "langchain": "^0.3.30",
 | 
			
		||||
    "lucide-react": "^0.363.0",
 | 
			
		||||
    "mammoth": "^1.9.1",
 | 
			
		||||
    "markdown-to-jsx": "^7.7.2",
 | 
			
		||||
    "next": "^15.2.2",
 | 
			
		||||
    "next-themes": "^0.3.0",
 | 
			
		||||
    "pdf-parse": "^1.1.1",
 | 
			
		||||
    "react": "^18",
 | 
			
		||||
    "react-dom": "^18",
 | 
			
		||||
    "react-syntax-highlighter": "^15.6.1",
 | 
			
		||||
    "react-text-to-speech": "^0.14.5",
 | 
			
		||||
    "react-textarea-autosize": "^8.5.3",
 | 
			
		||||
    "sonner": "^1.4.41",
 | 
			
		||||
@@ -49,10 +55,12 @@
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/better-sqlite3": "^7.6.12",
 | 
			
		||||
    "@types/html-to-text": "^9.0.4",
 | 
			
		||||
    "@types/jspdf": "^2.0.0",
 | 
			
		||||
    "@types/node": "^20",
 | 
			
		||||
    "@types/pdf-parse": "^1.1.4",
 | 
			
		||||
    "@types/react": "^18",
 | 
			
		||||
    "@types/react-dom": "^18",
 | 
			
		||||
    "@types/react-syntax-highlighter": "^15.5.13",
 | 
			
		||||
    "autoprefixer": "^10.0.1",
 | 
			
		||||
    "drizzle-kit": "^0.30.5",
 | 
			
		||||
    "eslint": "^8",
 | 
			
		||||
@@ -60,6 +68,6 @@
 | 
			
		||||
    "postcss": "^8",
 | 
			
		||||
    "prettier": "^3.2.5",
 | 
			
		||||
    "tailwindcss": "^3.3.0",
 | 
			
		||||
    "typescript": "^5"
 | 
			
		||||
    "typescript": "5.8.3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								public/icon-100.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 916 B  | 
							
								
								
									
										
											BIN
										
									
								
								public/icon-50.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 515 B  | 
							
								
								
									
										
											BIN
										
									
								
								public/icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 30 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/screenshots/p1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 183 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/screenshots/p1_small.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 130 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/screenshots/p2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 627 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/screenshots/p2_small.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 202 KiB  | 
							
								
								
									
										131
									
								
								public/weather-ico/clear-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,131 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.34167" y="-.34167" width="1.6833" height="1.85">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-sun {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(360deg);
 | 
			
		||||
          -moz-transform: rotate(360deg);
 | 
			
		||||
          -ms-transform: rotate(360deg);
 | 
			
		||||
          transform: rotate(360deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun;
 | 
			
		||||
        -moz-animation-name: am-weather-sun;
 | 
			
		||||
        -ms-animation-name: am-weather-sun;
 | 
			
		||||
        animation-name: am-weather-sun;
 | 
			
		||||
        -webkit-animation-duration: 9s;
 | 
			
		||||
        -moz-animation-duration: 9s;
 | 
			
		||||
        -ms-animation-duration: 9s;
 | 
			
		||||
        animation-duration: 9s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-sun-shiny {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dasharray: 3px 10px;
 | 
			
		||||
          stroke-dashoffset: 0px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          stroke-dasharray: 0.1px 10px;
 | 
			
		||||
          stroke-dashoffset: -1px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dasharray: 3px 10px;
 | 
			
		||||
          stroke-dashoffset: 0px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun-shiny line {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -moz-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -ms-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="translate(0,16)">
 | 
			
		||||
      <g class="am-weather-sun"
 | 
			
		||||
        style="-moz-animation-duration:9s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-sun;-moz-animation-timing-function:linear;-ms-animation-duration:9s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-sun;-ms-animation-timing-function:linear;-webkit-animation-duration:9s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-sun;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round" stroke-width="2" />
 | 
			
		||||
        <g transform="rotate(45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(135)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="scale(-1)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(225)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <circle r="5" fill="#ffa500" stroke="#ffa500" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 4.9 KiB  | 
							
								
								
									
										159
									
								
								public/weather-ico/clear-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,159 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.3038" y="-.3318" width="1.6076" height="1.894">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** MOON
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-moon {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: rotate(15deg);
 | 
			
		||||
          -moz-transform: rotate(15deg);
 | 
			
		||||
          -ms-transform: rotate(15deg);
 | 
			
		||||
          transform: rotate(15deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon;
 | 
			
		||||
        -moz-animation-name: am-weather-moon;
 | 
			
		||||
        -ms-animation-name: am-weather-moon;
 | 
			
		||||
        animation-name: am-weather-moon;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
        -webkit-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -moz-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -ms-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -webkit-animation-delay: 3s;
 | 
			
		||||
        -moz-animation-delay: 3s;
 | 
			
		||||
        -ms-animation-delay: 3s;
 | 
			
		||||
        animation-delay: 3s;
 | 
			
		||||
        -webkit-animation-duration: 5s;
 | 
			
		||||
        -moz-animation-duration: 5s;
 | 
			
		||||
        -ms-animation-duration: 5s;
 | 
			
		||||
        animation-duration: 5s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -webkit-animation-delay: 5s;
 | 
			
		||||
        -moz-animation-delay: 5s;
 | 
			
		||||
        -ms-animation-delay: 5s;
 | 
			
		||||
        animation-delay: 5s;
 | 
			
		||||
        -webkit-animation-duration: 4s;
 | 
			
		||||
        -moz-animation-duration: 4s;
 | 
			
		||||
        -ms-animation-duration: 4s;
 | 
			
		||||
        animation-duration: 4s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g id="night" transform="translate(-4,-18)" filter="url(#blur)">
 | 
			
		||||
    <g transform="matrix(.8 0 0 .78534 36 20.022)" stroke-width="1.2616">
 | 
			
		||||
      <g class="am-weather-moon-star-1"
 | 
			
		||||
        style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon points="4 2.7 5.2 3.3 4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5" fill="#ffa500" stroke-miterlimit="10"
 | 
			
		||||
          stroke-width="1.4105" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon-star-2"
 | 
			
		||||
        style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon transform="translate(20,10)" points="4 2.7 5.2 3.3 4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5"
 | 
			
		||||
          fill="#ffa500" stroke-miterlimit="10" stroke-width="1.4105" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon"
 | 
			
		||||
        style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
        <path
 | 
			
		||||
          d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
          fill="#ffa500" stroke="#ffa500" stroke-linejoin="round" stroke-width="2.5232" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 6.7 KiB  | 
							
								
								
									
										178
									
								
								public/weather-ico/cloudy-1-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,178 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.28472" width="1.403" height="1.6944">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-sun {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(360deg);
 | 
			
		||||
          -moz-transform: rotate(360deg);
 | 
			
		||||
          -ms-transform: rotate(360deg);
 | 
			
		||||
          transform: rotate(360deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun;
 | 
			
		||||
        -moz-animation-name: am-weather-sun;
 | 
			
		||||
        -ms-animation-name: am-weather-sun;
 | 
			
		||||
        animation-name: am-weather-sun;
 | 
			
		||||
        -webkit-animation-duration: 9s;
 | 
			
		||||
        -moz-animation-duration: 9s;
 | 
			
		||||
        -ms-animation-duration: 9s;
 | 
			
		||||
        animation-duration: 9s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-sun-shiny {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dasharray: 3px 10px;
 | 
			
		||||
          stroke-dashoffset: 0px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          stroke-dasharray: 0.1px 10px;
 | 
			
		||||
          stroke-dashoffset: -1px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dasharray: 3px 10px;
 | 
			
		||||
          stroke-dashoffset: 0px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun-shiny line {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -moz-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -ms-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="translate(0,16)">
 | 
			
		||||
      <g class="am-weather-sun"
 | 
			
		||||
        style="-moz-animation-duration:9s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-sun;-moz-animation-timing-function:linear;-ms-animation-duration:9s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-sun;-ms-animation-timing-function:linear;-webkit-animation-duration:9s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-sun;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round" stroke-width="2" />
 | 
			
		||||
        <g transform="rotate(45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(135)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="scale(-1)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(225)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <circle r="5" fill="#ffa500" stroke="#ffa500" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-2"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#c6deff" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 6.8 KiB  | 
							
								
								
									
										206
									
								
								public/weather-ico/cloudy-1-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,206 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.19471" y="-.26087" width="1.3744" height="1.6884">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** MOON
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-moon {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: rotate(15deg);
 | 
			
		||||
          -moz-transform: rotate(15deg);
 | 
			
		||||
          -ms-transform: rotate(15deg);
 | 
			
		||||
          transform: rotate(15deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon;
 | 
			
		||||
        -moz-animation-name: am-weather-moon;
 | 
			
		||||
        -ms-animation-name: am-weather-moon;
 | 
			
		||||
        animation-name: am-weather-moon;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
        -webkit-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -moz-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -ms-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -webkit-animation-delay: 3s;
 | 
			
		||||
        -moz-animation-delay: 3s;
 | 
			
		||||
        -ms-animation-delay: 3s;
 | 
			
		||||
        animation-delay: 3s;
 | 
			
		||||
        -webkit-animation-duration: 5s;
 | 
			
		||||
        -moz-animation-duration: 5s;
 | 
			
		||||
        -ms-animation-duration: 5s;
 | 
			
		||||
        animation-duration: 5s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -webkit-animation-delay: 5s;
 | 
			
		||||
        -moz-animation-delay: 5s;
 | 
			
		||||
        -ms-animation-delay: 5s;
 | 
			
		||||
        animation-delay: 5s;
 | 
			
		||||
        -webkit-animation-duration: 4s;
 | 
			
		||||
        -moz-animation-duration: 4s;
 | 
			
		||||
        -ms-animation-duration: 4s;
 | 
			
		||||
        animation-duration: 4s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="matrix(.8 0 0 .8 16 4)">
 | 
			
		||||
      <g class="am-weather-moon-star-1"
 | 
			
		||||
        style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon points="1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3 4 4 3.3 5.2 2.7 4" fill="#ffa500"
 | 
			
		||||
          stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon-star-2"
 | 
			
		||||
        style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon transform="translate(20,10)" points="1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3 4 4 3.3 5.2 2.7 4"
 | 
			
		||||
          fill="#ffa500" stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon"
 | 
			
		||||
        style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
        <path
 | 
			
		||||
          d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
          fill="#ffa500" stroke="#ffa500" stroke-linejoin="round" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-2"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#c6deff" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 8.6 KiB  | 
							
								
								
									
										244
									
								
								public/weather-ico/fog-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,244 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.21122" width="1.403" height="1.4997">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-sun {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(360deg);
 | 
			
		||||
          -moz-transform: rotate(360deg);
 | 
			
		||||
          -ms-transform: rotate(360deg);
 | 
			
		||||
          transform: rotate(360deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun;
 | 
			
		||||
        -moz-animation-name: am-weather-sun;
 | 
			
		||||
        -ms-animation-name: am-weather-sun;
 | 
			
		||||
        animation-name: am-weather-sun;
 | 
			
		||||
        -webkit-animation-duration: 9s;
 | 
			
		||||
        -moz-animation-duration: 9s;
 | 
			
		||||
        -ms-animation-duration: 9s;
 | 
			
		||||
        animation-duration: 9s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** FOG
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-fog-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          transform: translate(7px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-fog-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-fog-1;
 | 
			
		||||
        -moz-animation-name: am-weather-fog-1;
 | 
			
		||||
        -ms-animation-name: am-weather-fog-1;
 | 
			
		||||
        animation-name: am-weather-fog-1;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-fog-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        21.05% {
 | 
			
		||||
          transform: translate(-6px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        78.95% {
 | 
			
		||||
          transform: translate(9px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-fog-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-fog-2;
 | 
			
		||||
        -moz-animation-name: am-weather-fog-2;
 | 
			
		||||
        -ms-animation-name: am-weather-fog-2;
 | 
			
		||||
        animation-name: am-weather-fog-2;
 | 
			
		||||
        -webkit-animation-duration: 20s;
 | 
			
		||||
        -moz-animation-duration: 20s;
 | 
			
		||||
        -ms-animation-duration: 20s;
 | 
			
		||||
        animation-duration: 20s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-fog-3 {
 | 
			
		||||
        0% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        25% {
 | 
			
		||||
          transform: translate(4px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        75% {
 | 
			
		||||
          transform: translate(-4px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-fog-3 {
 | 
			
		||||
        -webkit-animation-name: am-weather-fog-3;
 | 
			
		||||
        -moz-animation-name: am-weather-fog-3;
 | 
			
		||||
        -ms-animation-name: am-weather-fog-3;
 | 
			
		||||
        animation-name: am-weather-fog-3;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-fog-4 {
 | 
			
		||||
        0% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          transform: translate(-4px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-fog-4 {
 | 
			
		||||
        -webkit-animation-name: am-weather-fog-4;
 | 
			
		||||
        -moz-animation-name: am-weather-fog-4;
 | 
			
		||||
        -ms-animation-name: am-weather-fog-4;
 | 
			
		||||
        animation-name: am-weather-fog-4;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="translate(0,16)">
 | 
			
		||||
      <g class="am-weather-sun" transform="translate(0,16)">
 | 
			
		||||
        <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round" stroke-width="2" />
 | 
			
		||||
        <g transform="rotate(45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(135)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="scale(-1)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />F
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(225)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <circle r="5" fill="#ffc04a" stroke="#ffc04a" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-fog" transform="translate(-10,20)" fill="none" stroke="#c6deff" stroke-linecap="round"
 | 
			
		||||
      stroke-width="2">
 | 
			
		||||
      <line class="am-weather-fog-1" y1="0" y2="0" x1="1" x2="37" stroke-dasharray="3, 5, 17, 5, 7" />
 | 
			
		||||
      <line class="am-weather-fog-2" y1="5" y2="5" x1="9" x2="33" stroke-dasharray="11, 7, 15" />
 | 
			
		||||
      <line class="am-weather-fog-3" y1="10" y2="10" x1="5" x2="40" stroke-dasharray="11, 7, 3, 5, 9" />
 | 
			
		||||
      <line class="am-weather-fog-4" y1="15" y2="15" x1="7" x2="42" stroke-dasharray="13, 5, 9, 5, 3" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 8.0 KiB  | 
							
								
								
									
										309
									
								
								public/weather-ico/fog-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,309 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.21122" width="1.403" height="1.4997">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** MOON
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-moon {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: rotate(15deg);
 | 
			
		||||
          -moz-transform: rotate(15deg);
 | 
			
		||||
          -ms-transform: rotate(15deg);
 | 
			
		||||
          transform: rotate(15deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon;
 | 
			
		||||
        -moz-animation-name: am-weather-moon;
 | 
			
		||||
        -ms-animation-name: am-weather-moon;
 | 
			
		||||
        animation-name: am-weather-moon;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
        -webkit-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -moz-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -ms-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -webkit-animation-delay: 3s;
 | 
			
		||||
        -moz-animation-delay: 3s;
 | 
			
		||||
        -ms-animation-delay: 3s;
 | 
			
		||||
        animation-delay: 3s;
 | 
			
		||||
        -webkit-animation-duration: 5s;
 | 
			
		||||
        -moz-animation-duration: 5s;
 | 
			
		||||
        -ms-animation-duration: 5s;
 | 
			
		||||
        animation-duration: 5s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -webkit-animation-delay: 5s;
 | 
			
		||||
        -moz-animation-delay: 5s;
 | 
			
		||||
        -ms-animation-delay: 5s;
 | 
			
		||||
        animation-delay: 5s;
 | 
			
		||||
        -webkit-animation-duration: 4s;
 | 
			
		||||
        -moz-animation-duration: 4s;
 | 
			
		||||
        -ms-animation-duration: 4s;
 | 
			
		||||
        animation-duration: 4s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** FOG
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-fog-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          transform: translate(7px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-fog-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-fog-1;
 | 
			
		||||
        -moz-animation-name: am-weather-fog-1;
 | 
			
		||||
        -ms-animation-name: am-weather-fog-1;
 | 
			
		||||
        animation-name: am-weather-fog-1;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-fog-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        21.05% {
 | 
			
		||||
          transform: translate(-6px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        78.95% {
 | 
			
		||||
          transform: translate(9px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-fog-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-fog-2;
 | 
			
		||||
        -moz-animation-name: am-weather-fog-2;
 | 
			
		||||
        -ms-animation-name: am-weather-fog-2;
 | 
			
		||||
        animation-name: am-weather-fog-2;
 | 
			
		||||
        -webkit-animation-duration: 20s;
 | 
			
		||||
        -moz-animation-duration: 20s;
 | 
			
		||||
        -ms-animation-duration: 20s;
 | 
			
		||||
        animation-duration: 20s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-fog-3 {
 | 
			
		||||
        0% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        25% {
 | 
			
		||||
          transform: translate(4px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        75% {
 | 
			
		||||
          transform: translate(-4px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-fog-3 {
 | 
			
		||||
        -webkit-animation-name: am-weather-fog-3;
 | 
			
		||||
        -moz-animation-name: am-weather-fog-3;
 | 
			
		||||
        -ms-animation-name: am-weather-fog-3;
 | 
			
		||||
        animation-name: am-weather-fog-3;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-fog-4 {
 | 
			
		||||
        0% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          transform: translate(-4px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          transform: translate(0px, 0px)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-fog-4 {
 | 
			
		||||
        -webkit-animation-name: am-weather-fog-4;
 | 
			
		||||
        -moz-animation-name: am-weather-fog-4;
 | 
			
		||||
        -ms-animation-name: am-weather-fog-4;
 | 
			
		||||
        animation-name: am-weather-fog-4;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="matrix(.8 0 0 .8 16 4)">
 | 
			
		||||
      <g class="am-weather-moon-star-1"
 | 
			
		||||
        style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3" fill="#ffc04a"
 | 
			
		||||
          stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon-star-2"
 | 
			
		||||
        style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon transform="translate(20,10)" points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3"
 | 
			
		||||
          fill="#ffc04a" stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon"
 | 
			
		||||
        style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
        <path
 | 
			
		||||
          d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
          fill="#ffc04a" stroke="#ffc04a" stroke-linejoin="round" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-fog" transform="translate(-10,20)" fill="none" stroke="#c6deff" stroke-linecap="round"
 | 
			
		||||
      stroke-width="2">
 | 
			
		||||
      <line class="am-weather-fog-1" y1="0" y2="0" x1="1" x2="37" stroke-dasharray="3, 5, 17, 5, 7" />
 | 
			
		||||
      <line class="am-weather-fog-2" y1="5" y2="5" x1="9" x2="33" stroke-dasharray="11, 7, 15" />
 | 
			
		||||
      <line class="am-weather-fog-3" y1="10" y2="10" x1="5" x2="40" stroke-dasharray="11, 7, 3, 5, 9" />
 | 
			
		||||
      <line class="am-weather-fog-4" y1="15" y2="15" x1="7" x2="42" stroke-dasharray="13, 5, 9, 5, 3" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 11 KiB  | 
							
								
								
									
										204
									
								
								public/weather-ico/frost-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,204 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.21122" width="1.403" height="1.4997">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-sun {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(360deg);
 | 
			
		||||
          -moz-transform: rotate(360deg);
 | 
			
		||||
          -ms-transform: rotate(360deg);
 | 
			
		||||
          transform: rotate(360deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun;
 | 
			
		||||
        -moz-animation-name: am-weather-sun;
 | 
			
		||||
        -ms-animation-name: am-weather-sun;
 | 
			
		||||
        animation-name: am-weather-sun;
 | 
			
		||||
        -webkit-animation-duration: 9s;
 | 
			
		||||
        -moz-animation-duration: 9s;
 | 
			
		||||
        -ms-animation-duration: 9s;
 | 
			
		||||
        animation-duration: 9s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** FROST
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-frost {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        1% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        3% {
 | 
			
		||||
          -webkit-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          transform: translate(-0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        5% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        7% {
 | 
			
		||||
          -webkit-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          transform: translate(-0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        9% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        11% {
 | 
			
		||||
          -webkit-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          transform: translate(-0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        13% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        15% {
 | 
			
		||||
          -webkit-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          transform: translate(-0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        16% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-frost {
 | 
			
		||||
        -webkit-animation-name: am-weather-frost;
 | 
			
		||||
        -moz-animation-name: am-weather-frost;
 | 
			
		||||
        animation-name: am-weather-frost;
 | 
			
		||||
        -webkit-animation-duration: 1.11s;
 | 
			
		||||
        -moz-animation-duration: 1.11s;
 | 
			
		||||
        animation-duration: 1.11s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="translate(0,16)">
 | 
			
		||||
      <g class="am-weather-sun" transform="translate(0,16)">
 | 
			
		||||
        <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round" stroke-width="2" />
 | 
			
		||||
        <g transform="rotate(45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(135)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="scale(-1)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />F
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(225)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffc04a" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <circle r="5" fill="#ffc04a" stroke="#ffc04a" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g transform="translate(-16,4)">
 | 
			
		||||
      <g class="am-weather-frost" stroke="#57a0ee" transform="translate(0,2)" fill="none" stroke-width="2"
 | 
			
		||||
        stroke-linecap="round"
 | 
			
		||||
        style="-moz-animation-duration:1.11s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-frost;-moz-animation-timing-function:linear;-webkit-animation-duration:1.11s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-frost;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <path d="M11,32H45" />
 | 
			
		||||
        <path d="M15.5,37H40.5" />
 | 
			
		||||
        <path d="M22.5,42H33.5" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g>
 | 
			
		||||
        <path stroke="#57a0ee" transform="translate(0,0)" fill="none" stroke-width="2" stroke-linecap="round"
 | 
			
		||||
          d="M28,31V9M28,22l11,-3.67M34,20l2,-4M34,20l4,2M28,22l-11,-3.67M22,20l-2,-4M22,20l-4,2M28,14.27l3.01,-3.02M28,14.27l-3.01,-3.02" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 7.3 KiB  | 
							
								
								
									
										269
									
								
								public/weather-ico/frost-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,269 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.21122" width="1.403" height="1.4997">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** MOON
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-moon {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: rotate(15deg);
 | 
			
		||||
          -moz-transform: rotate(15deg);
 | 
			
		||||
          -ms-transform: rotate(15deg);
 | 
			
		||||
          transform: rotate(15deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon;
 | 
			
		||||
        -moz-animation-name: am-weather-moon;
 | 
			
		||||
        -ms-animation-name: am-weather-moon;
 | 
			
		||||
        animation-name: am-weather-moon;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
        -webkit-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -moz-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -ms-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -webkit-animation-delay: 3s;
 | 
			
		||||
        -moz-animation-delay: 3s;
 | 
			
		||||
        -ms-animation-delay: 3s;
 | 
			
		||||
        animation-delay: 3s;
 | 
			
		||||
        -webkit-animation-duration: 5s;
 | 
			
		||||
        -moz-animation-duration: 5s;
 | 
			
		||||
        -ms-animation-duration: 5s;
 | 
			
		||||
        animation-duration: 5s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -webkit-animation-delay: 5s;
 | 
			
		||||
        -moz-animation-delay: 5s;
 | 
			
		||||
        -ms-animation-delay: 5s;
 | 
			
		||||
        animation-delay: 5s;
 | 
			
		||||
        -webkit-animation-duration: 4s;
 | 
			
		||||
        -moz-animation-duration: 4s;
 | 
			
		||||
        -ms-animation-duration: 4s;
 | 
			
		||||
        animation-duration: 4s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** FROST
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-frost {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        1% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        3% {
 | 
			
		||||
          -webkit-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          transform: translate(-0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        5% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        7% {
 | 
			
		||||
          -webkit-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          transform: translate(-0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        9% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        11% {
 | 
			
		||||
          -webkit-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          transform: translate(-0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        13% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        15% {
 | 
			
		||||
          -webkit-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(-0.3px, 0.0px);
 | 
			
		||||
          transform: translate(-0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        16% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-frost {
 | 
			
		||||
        -webkit-animation-name: am-weather-frost;
 | 
			
		||||
        -moz-animation-name: am-weather-frost;
 | 
			
		||||
        animation-name: am-weather-frost;
 | 
			
		||||
        -webkit-animation-duration: 1.11s;
 | 
			
		||||
        -moz-animation-duration: 1.11s;
 | 
			
		||||
        animation-duration: 1.11s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="matrix(.8 0 0 .8 16 4)">
 | 
			
		||||
      <g class="am-weather-moon-star-1"
 | 
			
		||||
        style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3" fill="#ffc04a"
 | 
			
		||||
          stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon-star-2"
 | 
			
		||||
        style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon transform="translate(20,10)" points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3"
 | 
			
		||||
          fill="#ffc04a" stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon"
 | 
			
		||||
        style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
        <path
 | 
			
		||||
          d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
          fill="#ffc04a" stroke="#ffc04a" stroke-linejoin="round" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g transform="translate(-16,4)">
 | 
			
		||||
      <g class="am-weather-frost" stroke="#57a0ee" transform="translate(0,2)" fill="none" stroke-width="2"
 | 
			
		||||
        stroke-linecap="round"
 | 
			
		||||
        style="-moz-animation-duration:1.11s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-frost;-moz-animation-timing-function:linear;-webkit-animation-duration:1.11s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-frost;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <path d="M11,32H45" />
 | 
			
		||||
        <path d="M15.5,37H40.5" />
 | 
			
		||||
        <path d="M22.5,42H33.5" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g>
 | 
			
		||||
        <path stroke="#57a0ee" transform="translate(0,0)" fill="none" stroke-width="2" stroke-linecap="round"
 | 
			
		||||
          d="M28,31V9M28,22l11,-3.67M34,20l2,-4M34,20l4,2M28,22l-11,-3.67M22,20l-2,-4M22,20l-4,2M28,14.27l3.01,-3.02M28,14.27l-3.01,-3.02" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 11 KiB  | 
							
								
								
									
										141
									
								
								public/weather-ico/rain-and-sleet-mix.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,141 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<!-- Mix of Rain and Sleet | Contributed by hsoJ95 on GitHub: https://github.com/hsoj95 -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.24684" y="-.22776" width="1.4937" height="1.5756">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** RAIN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-rain {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dashoffset: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dashoffset: -100;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-delay: 0.25s;
 | 
			
		||||
        -moz-animation-delay: 0.25s;
 | 
			
		||||
        -ms-animation-delay: 0.25s;
 | 
			
		||||
        animation-delay: 0.25s;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-3 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-3 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-3;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-3;
 | 
			
		||||
        animation-name: am-weather-cloud-3;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-3;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-3;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-sleet-2" transform="translate(-20,-10) rotate(10,-247.39,200.17)" fill="none" stroke="#91c0f8"
 | 
			
		||||
      stroke-linecap="round">
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(-5,1)" y2="8" stroke-dasharray="0.1, 7" stroke-width="2"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(5)" y2="8" stroke-dasharray="0.1, 7" stroke-width="2"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-rain-3" transform="translate(-20,-10) rotate(10,-245.89,217.31)" fill="none" stroke="#91c0f8"
 | 
			
		||||
      stroke-dasharray="4, 7" stroke-linecap="round" stroke-width="2">
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(-13,1)" y2="8"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(-3,2)" y2="8"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
      <line class="am-weather-rain-2" transform="translate(7,-1)" y2="8"
 | 
			
		||||
        style="-moz-animation-delay:0.25s;-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-delay:0.25s;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-delay:0.25s;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 7.6 KiB  | 
							
								
								
									
										179
									
								
								public/weather-ico/rainy-1-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,179 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.21122" width="1.403" height="1.4997">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-sun {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(360deg);
 | 
			
		||||
          -moz-transform: rotate(360deg);
 | 
			
		||||
          -ms-transform: rotate(360deg);
 | 
			
		||||
          transform: rotate(360deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun;
 | 
			
		||||
        -moz-animation-name: am-weather-sun;
 | 
			
		||||
        -ms-animation-name: am-weather-sun;
 | 
			
		||||
        animation-name: am-weather-sun;
 | 
			
		||||
        -webkit-animation-duration: 9s;
 | 
			
		||||
        -moz-animation-duration: 9s;
 | 
			
		||||
        -ms-animation-duration: 9s;
 | 
			
		||||
        animation-duration: 9s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** RAIN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-rain {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dashoffset: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dashoffset: -100;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="translate(0,16)">
 | 
			
		||||
      <g class="am-weather-sun"
 | 
			
		||||
        style="-moz-animation-duration:9s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-sun;-moz-animation-timing-function:linear;-ms-animation-duration:9s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-sun;-ms-animation-timing-function:linear;-webkit-animation-duration:9s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-sun;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round" stroke-width="2" />
 | 
			
		||||
        <g transform="rotate(45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(135)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="scale(-1)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(225)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <circle r="5" fill="#ffa500" stroke="#ffa500" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-rain-1" transform="translate(-20,-10) rotate(10,-238.68,233.96)">
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(-6,1)" y2="8" fill="none" stroke="#91c0f8"
 | 
			
		||||
        stroke-dasharray="4, 7" stroke-linecap="round" stroke-width="2"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 7.4 KiB  | 
							
								
								
									
										243
									
								
								public/weather-ico/rainy-1-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,243 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.21122" width="1.403" height="1.4997">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** MOON
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-moon {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: rotate(15deg);
 | 
			
		||||
          -moz-transform: rotate(15deg);
 | 
			
		||||
          -ms-transform: rotate(15deg);
 | 
			
		||||
          transform: rotate(15deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon;
 | 
			
		||||
        -moz-animation-name: am-weather-moon;
 | 
			
		||||
        -ms-animation-name: am-weather-moon;
 | 
			
		||||
        animation-name: am-weather-moon;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
        -webkit-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -moz-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -ms-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -webkit-animation-delay: 3s;
 | 
			
		||||
        -moz-animation-delay: 3s;
 | 
			
		||||
        -ms-animation-delay: 3s;
 | 
			
		||||
        animation-delay: 3s;
 | 
			
		||||
        -webkit-animation-duration: 5s;
 | 
			
		||||
        -moz-animation-duration: 5s;
 | 
			
		||||
        -ms-animation-duration: 5s;
 | 
			
		||||
        animation-duration: 5s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -webkit-animation-delay: 5s;
 | 
			
		||||
        -moz-animation-delay: 5s;
 | 
			
		||||
        -ms-animation-delay: 5s;
 | 
			
		||||
        animation-delay: 5s;
 | 
			
		||||
        -webkit-animation-duration: 4s;
 | 
			
		||||
        -moz-animation-duration: 4s;
 | 
			
		||||
        -ms-animation-duration: 4s;
 | 
			
		||||
        animation-duration: 4s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** RAIN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-rain {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dashoffset: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dashoffset: -100;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="matrix(.8 0 0 .8 16 4)">
 | 
			
		||||
      <g class="am-weather-moon-star-1"
 | 
			
		||||
        style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3" fill="#ffa500"
 | 
			
		||||
          stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon-star-2"
 | 
			
		||||
        style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon transform="translate(20,10)" points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3"
 | 
			
		||||
          fill="#ffa500" stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon"
 | 
			
		||||
        style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
        <path
 | 
			
		||||
          d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
          fill="#ffa500" stroke="#ffa500" stroke-linejoin="round" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weaher-rain-1" transform="translate(-20,-10) rotate(10,-238.68,233.96)">
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(-6,1)" y2="8" fill="none" stroke="#91c0f8"
 | 
			
		||||
        stroke-dasharray="4, 7" stroke-linecap="round" stroke-width="2"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 10 KiB  | 
							
								
								
									
										204
									
								
								public/weather-ico/rainy-2-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,204 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.20592" width="1.403" height="1.4872">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-sun {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(360deg);
 | 
			
		||||
          -moz-transform: rotate(360deg);
 | 
			
		||||
          -ms-transform: rotate(360deg);
 | 
			
		||||
          transform: rotate(360deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun;
 | 
			
		||||
        -moz-animation-name: am-weather-sun;
 | 
			
		||||
        -ms-animation-name: am-weather-sun;
 | 
			
		||||
        animation-name: am-weather-sun;
 | 
			
		||||
        -webkit-animation-duration: 9s;
 | 
			
		||||
        -moz-animation-duration: 9s;
 | 
			
		||||
        -ms-animation-duration: 9s;
 | 
			
		||||
        animation-duration: 9s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** RAIN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-rain {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dashoffset: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dashoffset: -100;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-delay: 0.25s;
 | 
			
		||||
        -moz-animation-delay: 0.25s;
 | 
			
		||||
        -ms-animation-delay: 0.25s;
 | 
			
		||||
        animation-delay: 0.25s;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="translate(0,16)">
 | 
			
		||||
      <g class="am-weather-sun"
 | 
			
		||||
        style="-moz-animation-duration:9s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-sun;-moz-animation-timing-function:linear;-ms-animation-duration:9s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-sun;-ms-animation-timing-function:linear;-webkit-animation-duration:9s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-sun;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <line transform="translate(0,9)" y2="3" stroke="#ffa500" stroke-linecap="round" stroke-width="2" fifll="none" />
 | 
			
		||||
        <g transform="rotate(45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(135)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="scale(-1)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(225)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <circle r="5" fill="#ffa500" stroke="#ffa500" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g transform="translate(-20,-10) rotate(10,-245.89,217.31)" fill="none" stroke="#91c0f8" stroke-dasharray="4, 7" stroke-linecap="round"
 | 
			
		||||
      stroke-width="2">
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(-6,1)" y2="8"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
      <line class="am-weather-rain-2" transform="translate(0,-1)" y2="8"
 | 
			
		||||
        style="-moz-animation-delay:0.25s;-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-delay:0.25s;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-delay:0.25s;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 8.8 KiB  | 
							
								
								
									
										256
									
								
								public/weather-ico/rainy-2-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,256 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** MOON
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-moon {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: rotate(15deg);
 | 
			
		||||
          -moz-transform: rotate(15deg);
 | 
			
		||||
          -ms-transform: rotate(15deg);
 | 
			
		||||
          transform: rotate(15deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon;
 | 
			
		||||
        -moz-animation-name: am-weather-moon;
 | 
			
		||||
        -ms-animation-name: am-weather-moon;
 | 
			
		||||
        animation-name: am-weather-moon;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
        -webkit-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -moz-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -ms-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -webkit-animation-delay: 3s;
 | 
			
		||||
        -moz-animation-delay: 3s;
 | 
			
		||||
        -ms-animation-delay: 3s;
 | 
			
		||||
        animation-delay: 3s;
 | 
			
		||||
        -webkit-animation-duration: 5s;
 | 
			
		||||
        -moz-animation-duration: 5s;
 | 
			
		||||
        -ms-animation-duration: 5s;
 | 
			
		||||
        animation-duration: 5s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -webkit-animation-delay: 5s;
 | 
			
		||||
        -moz-animation-delay: 5s;
 | 
			
		||||
        -ms-animation-delay: 5s;
 | 
			
		||||
        animation-delay: 5s;
 | 
			
		||||
        -webkit-animation-duration: 4s;
 | 
			
		||||
        -moz-animation-duration: 4s;
 | 
			
		||||
        -ms-animation-duration: 4s;
 | 
			
		||||
        animation-duration: 4s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** RAIN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-rain {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dashoffset: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dashoffset: -100;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-delay: 0.25s;
 | 
			
		||||
        -moz-animation-delay: 0.25s;
 | 
			
		||||
        -ms-animation-delay: 0.25s;
 | 
			
		||||
        animation-delay: 0.25s;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g class="layer" transform="translate(16,-2)">
 | 
			
		||||
    <g transform="matrix(.8 0 0 .8 16 4)">
 | 
			
		||||
      <g class="am-weather-moon-star-1"
 | 
			
		||||
        style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3" fill="#ffa500"
 | 
			
		||||
          stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon-star-2"
 | 
			
		||||
        style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon transform="translate(20,10)" points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3"
 | 
			
		||||
          fill="#ffa500" stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon"
 | 
			
		||||
        style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
        <path
 | 
			
		||||
          d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
          fill="#ffa500" stroke="#ffa500" stroke-linejoin="round" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-rain-2" transform="translate(-20,-10) rotate(10,34,46)" fill="none" stroke="#91c0f8"
 | 
			
		||||
      stroke-dasharray="4, 7" stroke-linecap="round" stroke-width="2">
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(-6,1)" x1="34" x2="34" y1="46" y2="54"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
      <line class="am-weather-rain-2" transform="translate(0,-1)" x1="34" x2="34" y1="46" y2="54"
 | 
			
		||||
        style="-moz-animation-delay:0.25s;-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-delay:0.25s;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-delay:0.25s;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 11 KiB  | 
							
								
								
									
										206
									
								
								public/weather-ico/rainy-3-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,206 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.24684" y="-.22892" width="1.4937" height="1.5576">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-sun {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(360deg);
 | 
			
		||||
          -moz-transform: rotate(360deg);
 | 
			
		||||
          -ms-transform: rotate(360deg);
 | 
			
		||||
          transform: rotate(360deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun;
 | 
			
		||||
        -moz-animation-name: am-weather-sun;
 | 
			
		||||
        -ms-animation-name: am-weather-sun;
 | 
			
		||||
        animation-name: am-weather-sun;
 | 
			
		||||
        -webkit-animation-duration: 9s;
 | 
			
		||||
        -moz-animation-duration: 9s;
 | 
			
		||||
        -ms-animation-duration: 9s;
 | 
			
		||||
        animation-duration: 9s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** RAIN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-rain {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dashoffset: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dashoffset: -100;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-delay: 0.25s;
 | 
			
		||||
        -moz-animation-delay: 0.25s;
 | 
			
		||||
        -ms-animation-delay: 0.25s;
 | 
			
		||||
        animation-delay: 0.25s;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="translate(0,16)">
 | 
			
		||||
      <g class="am-weather-sun"
 | 
			
		||||
        style="-moz-animation-duration:9s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-sun;-moz-animation-timing-function:linear;-ms-animation-duration:9s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-sun;-ms-animation-timing-function:linear;-webkit-animation-duration:9s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-sun;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <line transform="translate(0,9)" y2="3" stroke="#ffa500" stroke-linecap="round" stroke-width="2" fifll="none" />
 | 
			
		||||
        <g transform="rotate(45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(135)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="scale(-1)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(225)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <circle r="5" fill="#ffa500" stroke="#ffa500" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g transform="translate(-20,-10) rotate(10,-247.39,200.17)" fill="none" stroke="#91c0f8" stroke-dasharray="4, 4"
 | 
			
		||||
      stroke-linecap="round" stroke-width="2">
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(-4,1)" y2="8"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
      <line class="am-weather-rain-2" transform="translate(0,-1)" y2="8"
 | 
			
		||||
        style="-moz-animation-delay:0.25s;-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-delay:0.25s;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-delay:0.25s;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(4)" y2="8"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 9.3 KiB  | 
							
								
								
									
										270
									
								
								public/weather-ico/rainy-3-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,270 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.24684" y="-.22892" width="1.4937" height="1.5576">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** RAIN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-rain {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dashoffset: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dashoffset: -100;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-rain-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-rain;
 | 
			
		||||
        -moz-animation-name: am-weather-rain;
 | 
			
		||||
        -ms-animation-name: am-weather-rain;
 | 
			
		||||
        animation-name: am-weather-rain;
 | 
			
		||||
        -webkit-animation-delay: 0.25s;
 | 
			
		||||
        -moz-animation-delay: 0.25s;
 | 
			
		||||
        -ms-animation-delay: 0.25s;
 | 
			
		||||
        animation-delay: 0.25s;
 | 
			
		||||
        -webkit-animation-duration: 8s;
 | 
			
		||||
        -moz-animation-duration: 8s;
 | 
			
		||||
        -ms-animation-duration: 8s;
 | 
			
		||||
        animation-duration: 8s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** MOON
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-moon {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: rotate(15deg);
 | 
			
		||||
          -moz-transform: rotate(15deg);
 | 
			
		||||
          -ms-transform: rotate(15deg);
 | 
			
		||||
          transform: rotate(15deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon;
 | 
			
		||||
        -moz-animation-name: am-weather-moon;
 | 
			
		||||
        -ms-animation-name: am-weather-moon;
 | 
			
		||||
        animation-name: am-weather-moon;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
        -webkit-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -moz-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -ms-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -webkit-animation-delay: 3s;
 | 
			
		||||
        -moz-animation-delay: 3s;
 | 
			
		||||
        -ms-animation-delay: 3s;
 | 
			
		||||
        animation-delay: 3s;
 | 
			
		||||
        -webkit-animation-duration: 5s;
 | 
			
		||||
        -moz-animation-duration: 5s;
 | 
			
		||||
        -ms-animation-duration: 5s;
 | 
			
		||||
        animation-duration: 5s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -webkit-animation-delay: 5s;
 | 
			
		||||
        -moz-animation-delay: 5s;
 | 
			
		||||
        -ms-animation-delay: 5s;
 | 
			
		||||
        animation-delay: 5s;
 | 
			
		||||
        -webkit-animation-duration: 4s;
 | 
			
		||||
        -moz-animation-duration: 4s;
 | 
			
		||||
        -ms-animation-duration: 4s;
 | 
			
		||||
        animation-duration: 4s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="matrix(.8 0 0 .8 16 4)">
 | 
			
		||||
      <g class="am-weather-moon-star-1"
 | 
			
		||||
        style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3" fill="#ffa500"
 | 
			
		||||
          stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon-star-2"
 | 
			
		||||
        style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon transform="translate(20,10)" points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3"
 | 
			
		||||
          fill="#ffa500" stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon"
 | 
			
		||||
        style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
        <path
 | 
			
		||||
          d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
          fill="#ffa500" stroke="#ffa500" stroke-linejoin="round" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g transform="translate(-20,-10) rotate(10,-247.39,200.17)" fill="none" stroke="#91c0f8" stroke-dasharray="4, 4"
 | 
			
		||||
      stroke-linecap="round" stroke-width="2">
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(-4,1)" y2="8"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
      <line class="am-weather-rain-2" transform="translate(0,-1)" y2="8"
 | 
			
		||||
        style="-moz-animation-delay:0.25s;-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-delay:0.25s;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-delay:0.25s;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
      <line class="am-weather-rain-1" transform="translate(4)" y2="8"
 | 
			
		||||
        style="-moz-animation-duration:8s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-rain;-moz-animation-timing-function:linear;-ms-animation-duration:8s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-rain;-ms-animation-timing-function:linear;-webkit-animation-duration:8s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-rain;-webkit-animation-timing-function:linear" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 12 KiB  | 
							
								
								
									
										374
									
								
								public/weather-ico/scattered-thunderstorms-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,374 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<!-- Scattered Thunderstorms | Contributed by hsoJ95 on GitHub: https://github.com/hsoj95 -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.1975" width="1.403" height="1.4766">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-3 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(-5px, 0px);
 | 
			
		||||
          -moz-transform: translate(-5px, 0px);
 | 
			
		||||
          -ms-transform: translate(-5px, 0px);
 | 
			
		||||
          transform: translate(-5px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(10px, 0px);
 | 
			
		||||
          -moz-transform: translate(10px, 0px);
 | 
			
		||||
          -ms-transform: translate(10px, 0px);
 | 
			
		||||
          transform: translate(10px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(-5px, 0px);
 | 
			
		||||
          -moz-transform: translate(-5px, 0px);
 | 
			
		||||
          -ms-transform: translate(-5px, 0px);
 | 
			
		||||
          transform: translate(-5px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-3 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-3;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-3;
 | 
			
		||||
        animation-name: am-weather-cloud-3;
 | 
			
		||||
        -webkit-animation-duration: 7s;
 | 
			
		||||
        -moz-animation-duration: 7s;
 | 
			
		||||
        animation-duration: 7s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-sun {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(360deg);
 | 
			
		||||
          -moz-transform: rotate(360deg);
 | 
			
		||||
          -ms-transform: rotate(360deg);
 | 
			
		||||
          transform: rotate(360deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun;
 | 
			
		||||
        -moz-animation-name: am-weather-sun;
 | 
			
		||||
        -ms-animation-name: am-weather-sun;
 | 
			
		||||
        animation-name: am-weather-sun;
 | 
			
		||||
        -webkit-animation-duration: 9s;
 | 
			
		||||
        -moz-animation-duration: 9s;
 | 
			
		||||
        -ms-animation-duration: 9s;
 | 
			
		||||
        animation-duration: 9s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-sun-shiny {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dasharray: 3px 10px;
 | 
			
		||||
          stroke-dashoffset: 0px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          stroke-dasharray: 0.1px 10px;
 | 
			
		||||
          stroke-dashoffset: -1px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dasharray: 3px 10px;
 | 
			
		||||
          stroke-dashoffset: 0px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun-shiny line {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -moz-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -ms-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** STROKE
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-stroke {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        2% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        4% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        6% {
 | 
			
		||||
          -webkit-transform: translate(0.5px, 0.4px);
 | 
			
		||||
          -moz-transform: translate(0.5px, 0.4px);
 | 
			
		||||
          -ms-transform: translate(0.5px, 0.4px);
 | 
			
		||||
          transform: translate(0.5px, 0.4px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        8% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        10% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        12% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        14% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        16% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        18% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        20% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        22% {
 | 
			
		||||
          -webkit-transform: translate(1px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(1px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(1px, 0.0px);
 | 
			
		||||
          transform: translate(1px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        24% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        26% {
 | 
			
		||||
          -webkit-transform: translate(-1px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(-1px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(-1px, 0.0px);
 | 
			
		||||
          transform: translate(-1px, 0.0px);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        28% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        40% {
 | 
			
		||||
          fill: orange;
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        65% {
 | 
			
		||||
          fill: white;
 | 
			
		||||
          -webkit-transform: translate(-1px, 5.0px);
 | 
			
		||||
          -moz-transform: translate(-1px, 5.0px);
 | 
			
		||||
          -ms-transform: translate(-1px, 5.0px);
 | 
			
		||||
          transform: translate(-1px, 5.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        61% {
 | 
			
		||||
          fill: orange;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-stroke {
 | 
			
		||||
        -webkit-animation-name: am-weather-stroke;
 | 
			
		||||
        -moz-animation-name: am-weather-stroke;
 | 
			
		||||
        animation-name: am-weather-stroke;
 | 
			
		||||
        -webkit-animation-duration: 1.11s;
 | 
			
		||||
        -moz-animation-duration: 1.11s;
 | 
			
		||||
        animation-duration: 1.11s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g id="thunder" transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="translate(0,16)">
 | 
			
		||||
      <g class="am-weather-sun"
 | 
			
		||||
        style="-moz-animation-duration:9s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-sun;-moz-animation-timing-function:linear;-ms-animation-duration:9s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-sun;-ms-animation-timing-function:linear;-webkit-animation-duration:9s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-sun;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round" stroke-width="2" />
 | 
			
		||||
        <g transform="rotate(45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(135)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="scale(-1)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(225)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <circle r="5" fill="#ffa500" stroke="#ffa500" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-lightning" transform="matrix(1.2,0,0,1.2,-4,28)">
 | 
			
		||||
      <polygon class="am-weather-stroke" points="11.1 6.9 14.3 -2.9 20.5 -2.9 16.4 4.3 20.3 4.3 11.5 14.6 14.9 6.9"
 | 
			
		||||
        fill="#ffa500" stroke="#fff"
 | 
			
		||||
        style="-moz-animation-duration:1.11s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-stroke;-moz-animation-timing-function:linear;-webkit-animation-duration:1.11s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-stroke;-webkit-animation-timing-function:linear" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 13 KiB  | 
							
								
								
									
										283
									
								
								public/weather-ico/scattered-thunderstorms-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,283 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<!-- Scattered Thunderstorms | Contributed by hsoJ95 on GitHub: https://github.com/hsoj95 -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.1975" width="1.403" height="1.4766">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-3 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(-5px, 0px);
 | 
			
		||||
          -moz-transform: translate(-5px, 0px);
 | 
			
		||||
          -ms-transform: translate(-5px, 0px);
 | 
			
		||||
          transform: translate(-5px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(10px, 0px);
 | 
			
		||||
          -moz-transform: translate(10px, 0px);
 | 
			
		||||
          -ms-transform: translate(10px, 0px);
 | 
			
		||||
          transform: translate(10px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(-5px, 0px);
 | 
			
		||||
          -moz-transform: translate(-5px, 0px);
 | 
			
		||||
          -ms-transform: translate(-5px, 0px);
 | 
			
		||||
          transform: translate(-5px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-3 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-3;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-3;
 | 
			
		||||
        animation-name: am-weather-cloud-3;
 | 
			
		||||
        -webkit-animation-duration: 7s;
 | 
			
		||||
        -moz-animation-duration: 7s;
 | 
			
		||||
        animation-duration: 7s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** STROKE
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-stroke {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        2% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        4% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        6% {
 | 
			
		||||
          -webkit-transform: translate(0.5px, 0.4px);
 | 
			
		||||
          -moz-transform: translate(0.5px, 0.4px);
 | 
			
		||||
          -ms-transform: translate(0.5px, 0.4px);
 | 
			
		||||
          transform: translate(0.5px, 0.4px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        8% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        10% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        12% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        14% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        16% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        18% {
 | 
			
		||||
          -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
          transform: translate(0.3px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        20% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        22% {
 | 
			
		||||
          -webkit-transform: translate(1px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(1px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(1px, 0.0px);
 | 
			
		||||
          transform: translate(1px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        24% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        26% {
 | 
			
		||||
          -webkit-transform: translate(-1px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(-1px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(-1px, 0.0px);
 | 
			
		||||
          transform: translate(-1px, 0.0px);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        28% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        40% {
 | 
			
		||||
          fill: orange;
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        65% {
 | 
			
		||||
          fill: white;
 | 
			
		||||
          -webkit-transform: translate(-1px, 5.0px);
 | 
			
		||||
          -moz-transform: translate(-1px, 5.0px);
 | 
			
		||||
          -ms-transform: translate(-1px, 5.0px);
 | 
			
		||||
          transform: translate(-1px, 5.0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        61% {
 | 
			
		||||
          fill: orange;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
          transform: translate(0.0px, 0.0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-stroke {
 | 
			
		||||
        -webkit-animation-name: am-weather-stroke;
 | 
			
		||||
        -moz-animation-name: am-weather-stroke;
 | 
			
		||||
        animation-name: am-weather-stroke;
 | 
			
		||||
        -webkit-animation-duration: 1.11s;
 | 
			
		||||
        -moz-animation-duration: 1.11s;
 | 
			
		||||
        animation-duration: 1.11s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g id="thunder" transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="matrix(.8 0 0 .8 16 4)">
 | 
			
		||||
      <g class="am-weather-moon-star-1"
 | 
			
		||||
        style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon points="3.3 1.5 4 2.7 5.2 3.3 4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7" fill="#ffa500"
 | 
			
		||||
          stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon-star-2"
 | 
			
		||||
        style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon transform="translate(20,10)" points="3.3 1.5 4 2.7 5.2 3.3 4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7"
 | 
			
		||||
          fill="#ffa500" stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon"
 | 
			
		||||
        style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
        <path
 | 
			
		||||
          d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
          fill="#ffa500" stroke="#ffa500" stroke-linejoin="round" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-lightning" transform="matrix(1.2,0,0,1.2,-4,28)">
 | 
			
		||||
      <polygon class="am-weather-stroke" points="11.1 6.9 14.3 -2.9 20.5 -2.9 16.4 4.3 20.3 4.3 11.5 14.6 14.9 6.9"
 | 
			
		||||
        fill="#ffa500" stroke="#fff"
 | 
			
		||||
        style="-moz-animation-duration:1.11s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-stroke;-moz-animation-timing-function:linear;-webkit-animation-duration:1.11s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-stroke;-webkit-animation-timing-function:linear" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 11 KiB  | 
							
								
								
									
										307
									
								
								public/weather-ico/severe-thunderstorm.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,307 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<!-- Severe Thunderstorm | Contributed by hsoJ95 on GitHub: https://github.com/hsoj95 -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
    <defs>
 | 
			
		||||
        <filter id="blur" x="-.17571" y="-.19575" width="1.3379" height="1.4959">
 | 
			
		||||
            <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
            <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
            <feComponentTransfer>
 | 
			
		||||
                <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
            </feComponentTransfer>
 | 
			
		||||
            <feMerge>
 | 
			
		||||
                <feMergeNode />
 | 
			
		||||
                <feMergeNode in="SourceGraphic" />
 | 
			
		||||
            </feMerge>
 | 
			
		||||
        </filter>
 | 
			
		||||
        <style type="text/css">
 | 
			
		||||
            <![CDATA[
 | 
			
		||||
            /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
            @keyframes am-weather-cloud-3 {
 | 
			
		||||
                0% {
 | 
			
		||||
                    -webkit-transform: translate(-5px, 0px);
 | 
			
		||||
                    -moz-transform: translate(-5px, 0px);
 | 
			
		||||
                    -ms-transform: translate(-5px, 0px);
 | 
			
		||||
                    transform: translate(-5px, 0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                50% {
 | 
			
		||||
                    -webkit-transform: translate(10px, 0px);
 | 
			
		||||
                    -moz-transform: translate(10px, 0px);
 | 
			
		||||
                    -ms-transform: translate(10px, 0px);
 | 
			
		||||
                    transform: translate(10px, 0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                100% {
 | 
			
		||||
                    -webkit-transform: translate(-5px, 0px);
 | 
			
		||||
                    -moz-transform: translate(-5px, 0px);
 | 
			
		||||
                    -ms-transform: translate(-5px, 0px);
 | 
			
		||||
                    transform: translate(-5px, 0px);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .am-weather-cloud-3 {
 | 
			
		||||
                -webkit-animation-name: am-weather-cloud-3;
 | 
			
		||||
                -moz-animation-name: am-weather-cloud-3;
 | 
			
		||||
                animation-name: am-weather-cloud-3;
 | 
			
		||||
                -webkit-animation-duration: 7s;
 | 
			
		||||
                -moz-animation-duration: 7s;
 | 
			
		||||
                animation-duration: 7s;
 | 
			
		||||
                -webkit-animation-timing-function: linear;
 | 
			
		||||
                -moz-animation-timing-function: linear;
 | 
			
		||||
                animation-timing-function: linear;
 | 
			
		||||
                -webkit-animation-iteration-count: infinite;
 | 
			
		||||
                -moz-animation-iteration-count: infinite;
 | 
			
		||||
                animation-iteration-count: infinite;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @keyframes am-weather-cloud-1 {
 | 
			
		||||
                0% {
 | 
			
		||||
                    -webkit-transform: translate(0px, 0px);
 | 
			
		||||
                    -moz-transform: translate(0px, 0px);
 | 
			
		||||
                    -ms-transform: translate(0px, 0px);
 | 
			
		||||
                    transform: translate(0px, 0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                50% {
 | 
			
		||||
                    -webkit-transform: translate(2px, 0px);
 | 
			
		||||
                    -moz-transform: translate(2px, 0px);
 | 
			
		||||
                    -ms-transform: translate(2px, 0px);
 | 
			
		||||
                    transform: translate(2px, 0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                100% {
 | 
			
		||||
                    -webkit-transform: translate(0px, 0px);
 | 
			
		||||
                    -moz-transform: translate(0px, 0px);
 | 
			
		||||
                    -ms-transform: translate(0px, 0px);
 | 
			
		||||
                    transform: translate(0px, 0px);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .am-weather-cloud-1 {
 | 
			
		||||
                -webkit-animation-name: am-weather-cloud-1;
 | 
			
		||||
                -moz-animation-name: am-weather-cloud-1;
 | 
			
		||||
                animation-name: am-weather-cloud-1;
 | 
			
		||||
                -webkit-animation-duration: 3s;
 | 
			
		||||
                -moz-animation-duration: 3s;
 | 
			
		||||
                animation-duration: 3s;
 | 
			
		||||
                -webkit-animation-timing-function: linear;
 | 
			
		||||
                -moz-animation-timing-function: linear;
 | 
			
		||||
                animation-timing-function: linear;
 | 
			
		||||
                -webkit-animation-iteration-count: infinite;
 | 
			
		||||
                -moz-animation-iteration-count: infinite;
 | 
			
		||||
                animation-iteration-count: infinite;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /*
 | 
			
		||||
** STROKE
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
            @keyframes am-weather-stroke {
 | 
			
		||||
                0% {
 | 
			
		||||
                    -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    transform: translate(0.0px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                2% {
 | 
			
		||||
                    -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    transform: translate(0.3px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                4% {
 | 
			
		||||
                    -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    transform: translate(0.0px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                6% {
 | 
			
		||||
                    -webkit-transform: translate(0.5px, 0.4px);
 | 
			
		||||
                    -moz-transform: translate(0.5px, 0.4px);
 | 
			
		||||
                    -ms-transform: translate(0.5px, 0.4px);
 | 
			
		||||
                    transform: translate(0.5px, 0.4px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                8% {
 | 
			
		||||
                    -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    transform: translate(0.0px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                10% {
 | 
			
		||||
                    -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    transform: translate(0.3px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                12% {
 | 
			
		||||
                    -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    transform: translate(0.0px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                14% {
 | 
			
		||||
                    -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    transform: translate(0.3px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                16% {
 | 
			
		||||
                    -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    transform: translate(0.0px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                18% {
 | 
			
		||||
                    -webkit-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.3px, 0.0px);
 | 
			
		||||
                    transform: translate(0.3px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                20% {
 | 
			
		||||
                    -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    transform: translate(0.0px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                22% {
 | 
			
		||||
                    -webkit-transform: translate(1px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(1px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(1px, 0.0px);
 | 
			
		||||
                    transform: translate(1px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                24% {
 | 
			
		||||
                    -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    transform: translate(0.0px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                26% {
 | 
			
		||||
                    -webkit-transform: translate(-1px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(-1px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(-1px, 0.0px);
 | 
			
		||||
                    transform: translate(-1px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                28% {
 | 
			
		||||
                    -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    transform: translate(0.0px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                40% {
 | 
			
		||||
                    fill: orange;
 | 
			
		||||
                    -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    transform: translate(0.0px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                65% {
 | 
			
		||||
                    fill: white;
 | 
			
		||||
                    -webkit-transform: translate(-1px, 5.0px);
 | 
			
		||||
                    -moz-transform: translate(-1px, 5.0px);
 | 
			
		||||
                    -ms-transform: translate(-1px, 5.0px);
 | 
			
		||||
                    transform: translate(-1px, 5.0px);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                61% {
 | 
			
		||||
                    fill: orange;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                100% {
 | 
			
		||||
                    -webkit-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -moz-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    -ms-transform: translate(0.0px, 0.0px);
 | 
			
		||||
                    transform: translate(0.0px, 0.0px);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .am-weather-stroke {
 | 
			
		||||
                -webkit-animation-name: am-weather-stroke;
 | 
			
		||||
                -moz-animation-name: am-weather-stroke;
 | 
			
		||||
                animation-name: am-weather-stroke;
 | 
			
		||||
                -webkit-animation-duration: 1.11s;
 | 
			
		||||
                -moz-animation-duration: 1.11s;
 | 
			
		||||
                animation-duration: 1.11s;
 | 
			
		||||
                -webkit-animation-timing-function: linear;
 | 
			
		||||
                -moz-animation-timing-function: linear;
 | 
			
		||||
                animation-timing-function: linear;
 | 
			
		||||
                -webkit-animation-iteration-count: infinite;
 | 
			
		||||
                -moz-animation-iteration-count: infinite;
 | 
			
		||||
                animation-iteration-count: infinite;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @keyframes error {
 | 
			
		||||
                0% {
 | 
			
		||||
                    fill: #cc0000;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                50% {
 | 
			
		||||
                    fill: #ff0000;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                100% {
 | 
			
		||||
                    fill: #cc0000;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #Shape {
 | 
			
		||||
                -webkit-animation-name: error;
 | 
			
		||||
                -moz-animation-name: error;
 | 
			
		||||
                animation-name: error;
 | 
			
		||||
                -webkit-animation-duration: 1s;
 | 
			
		||||
                -moz-animation-duration: 1s;
 | 
			
		||||
                animation-duration: 1s;
 | 
			
		||||
                -webkit-animation-timing-function: linear;
 | 
			
		||||
                -moz-animation-timing-function: linear;
 | 
			
		||||
                animation-timing-function: linear;
 | 
			
		||||
                -webkit-animation-iteration-count: infinite;
 | 
			
		||||
                -moz-animation-iteration-count: infinite;
 | 
			
		||||
                animation-iteration-count: infinite;
 | 
			
		||||
            }
 | 
			
		||||
            ]]>
 | 
			
		||||
        </style>
 | 
			
		||||
    </defs>
 | 
			
		||||
    <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
        <g class="am-weather-cloud-1"
 | 
			
		||||
            style="-moz-animation-duration:7s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-1;-moz-animation-timing-function:linear;-webkit-animation-duration:7s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
            <path transform="matrix(.6 0 0 .6 -10 -6)"
 | 
			
		||||
                d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
                fill="#666" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g class="am-weather-cloud-3">
 | 
			
		||||
            <path transform="translate(-20,-11)"
 | 
			
		||||
                d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
                fill="#333" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="matrix(1.2,0,0,1.2,-4,28)">
 | 
			
		||||
            <polygon class="am-weather-stroke"
 | 
			
		||||
                points="11.1 6.9 14.3 -2.9 20.5 -2.9 16.4 4.3 20.3 4.3 11.5 14.6 14.9 6.9" fill="#ffa500" stroke="#fff"
 | 
			
		||||
                style="-moz-animation-duration:1.11s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-stroke;-moz-animation-timing-function:linear;-webkit-animation-duration:1.11s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-stroke;-webkit-animation-timing-function:linear" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g class="warning" transform="translate(20,30)">
 | 
			
		||||
            <path
 | 
			
		||||
                d="m7.7791 2.906-5.9912 10.117c-0.56283 0.95042-0.24862 2.1772 0.7018 2.74 0.30853 0.18271 0.66051 0.27911 1.0191 0.27911h11.982c1.1046 0 2-0.89543 2-2 0-0.35857-0.0964-0.71056-0.27911-1.0191l-5.9912-10.117c-0.56283-0.95042-1.7896-1.2646-2.74-0.7018-0.28918 0.17125-0.53055 0.41262-0.7018 0.7018z"
 | 
			
		||||
                fill="#c00" />
 | 
			
		||||
            <path d="m9.5 10.5v-5" stroke="#fff" stroke-linecap="round" stroke-width="1.5" />
 | 
			
		||||
            <circle cx="9.5" cy="13" r="1" fill="#fff" />
 | 
			
		||||
        </g>
 | 
			
		||||
    </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 13 KiB  | 
							
								
								
									
										241
									
								
								public/weather-ico/snowy-1-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,241 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.23099" width="1.403" height="1.5634">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-sun {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(360deg);
 | 
			
		||||
          -moz-transform: rotate(360deg);
 | 
			
		||||
          -ms-transform: rotate(360deg);
 | 
			
		||||
          transform: rotate(360deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun;
 | 
			
		||||
        -moz-animation-name: am-weather-sun;
 | 
			
		||||
        -ms-animation-name: am-weather-sun;
 | 
			
		||||
        animation-name: am-weather-sun;
 | 
			
		||||
        -webkit-animation-duration: 9s;
 | 
			
		||||
        -moz-animation-duration: 9s;
 | 
			
		||||
        -ms-animation-duration: 9s;
 | 
			
		||||
        animation-duration: 9s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-sun-shiny {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dasharray: 3px 10px;
 | 
			
		||||
          stroke-dashoffset: 0px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          stroke-dasharray: 0.1px 10px;
 | 
			
		||||
          stroke-dashoffset: -1px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dasharray: 3px 10px;
 | 
			
		||||
          stroke-dashoffset: 0px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun-shiny line {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -moz-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -ms-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** SNOW
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-snow {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translateX(0) translateY(0);
 | 
			
		||||
          -moz-transform: translateX(0) translateY(0);
 | 
			
		||||
          -ms-transform: translateX(0) translateY(0);
 | 
			
		||||
          transform: translateX(0) translateY(0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        33.33% {
 | 
			
		||||
          -webkit-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          -moz-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          -ms-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        66.66% {
 | 
			
		||||
          -webkit-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          -moz-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          -ms-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          -moz-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          -ms-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-snow-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-snow;
 | 
			
		||||
        -moz-animation-name: am-weather-snow;
 | 
			
		||||
        -ms-animation-name: am-weather-snow;
 | 
			
		||||
        animation-name: am-weather-snow;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="translate(0,16)">
 | 
			
		||||
      <g class="am-weather-sun" transform="translate(0,16)"
 | 
			
		||||
        style="-moz-animation-duration:9s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-sun;-moz-animation-timing-function:linear;-ms-animation-duration:9s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-sun;-ms-animation-timing-function:linear;-webkit-animation-duration:9s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-sun;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round" stroke-width="2" />
 | 
			
		||||
        <g transform="rotate(45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(135)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="scale(-1)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(225)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <circle r="5" fill="#ffa500" stroke="#ffa500" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-snow-1"
 | 
			
		||||
      style="-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow;-moz-animation-timing-function:linear;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow;-ms-animation-timing-function:linear;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <g transform="translate(12,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
        <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
        <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 9.6 KiB  | 
							
								
								
									
										269
									
								
								public/weather-ico/snowy-1-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,269 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.23099" width="1.403" height="1.5634">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** MOON
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-moon {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: rotate(15deg);
 | 
			
		||||
          -moz-transform: rotate(15deg);
 | 
			
		||||
          -ms-transform: rotate(15deg);
 | 
			
		||||
          transform: rotate(15deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon;
 | 
			
		||||
        -moz-animation-name: am-weather-moon;
 | 
			
		||||
        -ms-animation-name: am-weather-moon;
 | 
			
		||||
        animation-name: am-weather-moon;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
        -webkit-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -moz-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -ms-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -webkit-animation-delay: 3s;
 | 
			
		||||
        -moz-animation-delay: 3s;
 | 
			
		||||
        -ms-animation-delay: 3s;
 | 
			
		||||
        animation-delay: 3s;
 | 
			
		||||
        -webkit-animation-duration: 5s;
 | 
			
		||||
        -moz-animation-duration: 5s;
 | 
			
		||||
        -ms-animation-duration: 5s;
 | 
			
		||||
        animation-duration: 5s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -webkit-animation-delay: 5s;
 | 
			
		||||
        -moz-animation-delay: 5s;
 | 
			
		||||
        -ms-animation-delay: 5s;
 | 
			
		||||
        animation-delay: 5s;
 | 
			
		||||
        -webkit-animation-duration: 4s;
 | 
			
		||||
        -moz-animation-duration: 4s;
 | 
			
		||||
        -ms-animation-duration: 4s;
 | 
			
		||||
        animation-duration: 4s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** SNOW
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-snow {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translateX(0) translateY(0);
 | 
			
		||||
          -moz-transform: translateX(0) translateY(0);
 | 
			
		||||
          -ms-transform: translateX(0) translateY(0);
 | 
			
		||||
          transform: translateX(0) translateY(0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        33.33% {
 | 
			
		||||
          -webkit-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          -moz-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          -ms-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        66.66% {
 | 
			
		||||
          -webkit-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          -moz-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          -ms-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          -moz-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          -ms-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-snow-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-snow;
 | 
			
		||||
        -moz-animation-name: am-weather-snow;
 | 
			
		||||
        -ms-animation-name: am-weather-snow;
 | 
			
		||||
        animation-name: am-weather-snow;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="matrix(.8 0 0 .8 16 4)">
 | 
			
		||||
      <g class="am-weather-moon-star-1"
 | 
			
		||||
        style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3" fill="#ffa500"
 | 
			
		||||
          stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon-star-2"
 | 
			
		||||
        style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon transform="translate(20,10)" points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3"
 | 
			
		||||
          fill="#ffa500" stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon"
 | 
			
		||||
        style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
        <path
 | 
			
		||||
          d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
          fill="#ffa500" stroke="#ffa500" stroke-linejoin="round" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-snow-1"
 | 
			
		||||
      style="-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow;-moz-animation-timing-function:linear;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow;-ms-animation-timing-function:linear;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <g transform="translate(12,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
        <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
        <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 11 KiB  | 
							
								
								
									
										273
									
								
								public/weather-ico/snowy-2-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,273 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.23099" width="1.403" height="1.5634">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-sun {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(360deg);
 | 
			
		||||
          -moz-transform: rotate(360deg);
 | 
			
		||||
          -ms-transform: rotate(360deg);
 | 
			
		||||
          transform: rotate(360deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun;
 | 
			
		||||
        -moz-animation-name: am-weather-sun;
 | 
			
		||||
        -ms-animation-name: am-weather-sun;
 | 
			
		||||
        animation-name: am-weather-sun;
 | 
			
		||||
        -webkit-animation-duration: 9s;
 | 
			
		||||
        -moz-animation-duration: 9s;
 | 
			
		||||
        -ms-animation-duration: 9s;
 | 
			
		||||
        animation-duration: 9s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-sun-shiny {
 | 
			
		||||
        0% {
 | 
			
		||||
          stroke-dasharray: 3px 10px;
 | 
			
		||||
          stroke-dashoffset: 0px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          stroke-dasharray: 0.1px 10px;
 | 
			
		||||
          stroke-dashoffset: -1px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          stroke-dasharray: 3px 10px;
 | 
			
		||||
          stroke-dashoffset: 0px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-sun-shiny line {
 | 
			
		||||
        -webkit-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -moz-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -ms-animation-name: am-weather-sun-shiny;
 | 
			
		||||
        animation-name: am-weather-sun-shiny;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** SNOW
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-snow {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translateX(0) translateY(0);
 | 
			
		||||
          -moz-transform: translateX(0) translateY(0);
 | 
			
		||||
          -ms-transform: translateX(0) translateY(0);
 | 
			
		||||
          transform: translateX(0) translateY(0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        33.33% {
 | 
			
		||||
          -webkit-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          -moz-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          -ms-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        66.66% {
 | 
			
		||||
          -webkit-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          -moz-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          -ms-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          -moz-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          -ms-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-snow-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-snow;
 | 
			
		||||
        -moz-animation-name: am-weather-snow;
 | 
			
		||||
        -ms-animation-name: am-weather-snow;
 | 
			
		||||
        animation-name: am-weather-snow;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-snow-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-snow;
 | 
			
		||||
        -moz-animation-name: am-weather-snow;
 | 
			
		||||
        -ms-animation-name: am-weather-snow;
 | 
			
		||||
        animation-name: am-weather-snow;
 | 
			
		||||
        -webkit-animation-delay: 1.2s;
 | 
			
		||||
        -moz-animation-delay: 1.2s;
 | 
			
		||||
        -ms-animation-delay: 1.2s;
 | 
			
		||||
        animation-delay: 1.2s;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="translate(0,16)">
 | 
			
		||||
      <g class="am-weather-sun"
 | 
			
		||||
        style="-moz-animation-duration:9s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-sun;-moz-animation-timing-function:linear;-ms-animation-duration:9s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-sun;-ms-animation-timing-function:linear;-webkit-animation-duration:9s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-sun;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round" stroke-width="2" />
 | 
			
		||||
        <g transform="rotate(45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(135)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="scale(-1)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(225)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-90)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
        <g transform="rotate(-45)">
 | 
			
		||||
          <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
            stroke-width="2" />
 | 
			
		||||
        </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <circle r="5" fill="#ffa500" stroke="#ffa500" stroke-width="2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-snow-1"
 | 
			
		||||
      style="-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow;-moz-animation-timing-function:linear;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow;-ms-animation-timing-function:linear;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <g transform="translate(7,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
        <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
        <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-snow-2"
 | 
			
		||||
      style="-moz-animation-delay:1.2s;-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow;-moz-animation-timing-function:linear;-ms-animation-delay:1.2s;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow;-ms-animation-timing-function:linear;-webkit-animation-delay:1.2s;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <g transform="translate(16,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
        <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
        <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 11 KiB  | 
							
								
								
									
										301
									
								
								public/weather-ico/snowy-2-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,301 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
  <defs>
 | 
			
		||||
    <filter id="blur" x="-.20655" y="-.23099" width="1.403" height="1.5634">
 | 
			
		||||
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
      <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
      <feComponentTransfer>
 | 
			
		||||
        <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
      </feComponentTransfer>
 | 
			
		||||
      <feMerge>
 | 
			
		||||
        <feMergeNode />
 | 
			
		||||
        <feMergeNode in="SourceGraphic" />
 | 
			
		||||
      </feMerge>
 | 
			
		||||
    </filter>
 | 
			
		||||
    <style type="text/css">
 | 
			
		||||
      <![CDATA[
 | 
			
		||||
      /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-cloud-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: translate(2px, 0px);
 | 
			
		||||
          -moz-transform: translate(2px, 0px);
 | 
			
		||||
          -ms-transform: translate(2px, 0px);
 | 
			
		||||
          transform: translate(2px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translate(0px, 0px);
 | 
			
		||||
          -moz-transform: translate(0px, 0px);
 | 
			
		||||
          -ms-transform: translate(0px, 0px);
 | 
			
		||||
          transform: translate(0px, 0px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-cloud-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
        -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
        animation-name: am-weather-cloud-2;
 | 
			
		||||
        -webkit-animation-duration: 3s;
 | 
			
		||||
        -moz-animation-duration: 3s;
 | 
			
		||||
        animation-duration: 3s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** MOON
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-moon {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        50% {
 | 
			
		||||
          -webkit-transform: rotate(15deg);
 | 
			
		||||
          -moz-transform: rotate(15deg);
 | 
			
		||||
          -ms-transform: rotate(15deg);
 | 
			
		||||
          transform: rotate(15deg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: rotate(0deg);
 | 
			
		||||
          -moz-transform: rotate(0deg);
 | 
			
		||||
          -ms-transform: rotate(0deg);
 | 
			
		||||
          transform: rotate(0deg);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon;
 | 
			
		||||
        -moz-animation-name: am-weather-moon;
 | 
			
		||||
        -ms-animation-name: am-weather-moon;
 | 
			
		||||
        animation-name: am-weather-moon;
 | 
			
		||||
        -webkit-animation-duration: 6s;
 | 
			
		||||
        -moz-animation-duration: 6s;
 | 
			
		||||
        -ms-animation-duration: 6s;
 | 
			
		||||
        animation-duration: 6s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
        -webkit-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -moz-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        -ms-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
        transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
        /* TODO FF CENTER ISSUE */
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-1 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-1;
 | 
			
		||||
        animation-name: am-weather-moon-star-1;
 | 
			
		||||
        -webkit-animation-delay: 3s;
 | 
			
		||||
        -moz-animation-delay: 3s;
 | 
			
		||||
        -ms-animation-delay: 3s;
 | 
			
		||||
        animation-delay: 3s;
 | 
			
		||||
        -webkit-animation-duration: 5s;
 | 
			
		||||
        -moz-animation-duration: 5s;
 | 
			
		||||
        -ms-animation-duration: 5s;
 | 
			
		||||
        animation-duration: 5s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @keyframes am-weather-moon-star-2 {
 | 
			
		||||
        0% {
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-moon-star-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -moz-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -ms-animation-name: am-weather-moon-star-2;
 | 
			
		||||
        animation-name: am-weather-moon-star-2;
 | 
			
		||||
        -webkit-animation-delay: 5s;
 | 
			
		||||
        -moz-animation-delay: 5s;
 | 
			
		||||
        -ms-animation-delay: 5s;
 | 
			
		||||
        animation-delay: 5s;
 | 
			
		||||
        -webkit-animation-duration: 4s;
 | 
			
		||||
        -moz-animation-duration: 4s;
 | 
			
		||||
        -ms-animation-duration: 4s;
 | 
			
		||||
        animation-duration: 4s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: 1;
 | 
			
		||||
        -moz-animation-iteration-count: 1;
 | 
			
		||||
        -ms-animation-iteration-count: 1;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
** SNOW
 | 
			
		||||
*/
 | 
			
		||||
      @keyframes am-weather-snow {
 | 
			
		||||
        0% {
 | 
			
		||||
          -webkit-transform: translateX(0) translateY(0);
 | 
			
		||||
          -moz-transform: translateX(0) translateY(0);
 | 
			
		||||
          -ms-transform: translateX(0) translateY(0);
 | 
			
		||||
          transform: translateX(0) translateY(0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        33.33% {
 | 
			
		||||
          -webkit-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          -moz-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          -ms-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
          transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        66.66% {
 | 
			
		||||
          -webkit-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          -moz-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          -ms-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
          opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        100% {
 | 
			
		||||
          -webkit-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          -moz-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          -ms-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
          opacity: 0;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-snow-1 {
 | 
			
		||||
        -webkit-animation-name: am-weather-snow;
 | 
			
		||||
        -moz-animation-name: am-weather-snow;
 | 
			
		||||
        -ms-animation-name: am-weather-snow;
 | 
			
		||||
        animation-name: am-weather-snow;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .am-weather-snow-2 {
 | 
			
		||||
        -webkit-animation-name: am-weather-snow;
 | 
			
		||||
        -moz-animation-name: am-weather-snow;
 | 
			
		||||
        -ms-animation-name: am-weather-snow;
 | 
			
		||||
        animation-name: am-weather-snow;
 | 
			
		||||
        -webkit-animation-delay: 1.2s;
 | 
			
		||||
        -moz-animation-delay: 1.2s;
 | 
			
		||||
        -ms-animation-delay: 1.2s;
 | 
			
		||||
        animation-delay: 1.2s;
 | 
			
		||||
        -webkit-animation-duration: 2s;
 | 
			
		||||
        -moz-animation-duration: 2s;
 | 
			
		||||
        -ms-animation-duration: 2s;
 | 
			
		||||
        animation-duration: 2s;
 | 
			
		||||
        -webkit-animation-timing-function: linear;
 | 
			
		||||
        -moz-animation-timing-function: linear;
 | 
			
		||||
        -ms-animation-timing-function: linear;
 | 
			
		||||
        animation-timing-function: linear;
 | 
			
		||||
        -webkit-animation-iteration-count: infinite;
 | 
			
		||||
        -moz-animation-iteration-count: infinite;
 | 
			
		||||
        -ms-animation-iteration-count: infinite;
 | 
			
		||||
        animation-iteration-count: infinite;
 | 
			
		||||
      }
 | 
			
		||||
      ]]>
 | 
			
		||||
    </style>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
    <g transform="matrix(.8 0 0 .8 16 4)">
 | 
			
		||||
      <g class="am-weather-moon-star-1"
 | 
			
		||||
        style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3" fill="#ffa500"
 | 
			
		||||
          stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon-star-2"
 | 
			
		||||
        style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
        <polygon transform="translate(20,10)" points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3"
 | 
			
		||||
          fill="#ffa500" stroke-miterlimit="10" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-moon"
 | 
			
		||||
        style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
        <path
 | 
			
		||||
          d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
          fill="#ffa500" stroke="#ffa500" stroke-linejoin="round" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-cloud-3"
 | 
			
		||||
      style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <path transform="translate(-20,-11)"
 | 
			
		||||
        d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
        fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-snow-1"
 | 
			
		||||
      style="-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow;-moz-animation-timing-function:linear;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow;-ms-animation-timing-function:linear;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <g transform="translate(7,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
        <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
        <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
    <g class="am-weather-snow-2"
 | 
			
		||||
      style="-moz-animation-delay:1.2s;-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow;-moz-animation-timing-function:linear;-ms-animation-delay:1.2s;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow;-ms-animation-timing-function:linear;-webkit-animation-delay:1.2s;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow;-webkit-animation-timing-function:linear">
 | 
			
		||||
      <g transform="translate(16,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
        <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
        <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
        <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 13 KiB  | 
							
								
								
									
										334
									
								
								public/weather-ico/snowy-3-day.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,334 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
   <defs>
 | 
			
		||||
      <filter id="blur" x="-.24684" y="-.26897" width="1.4937" height="1.6759">
 | 
			
		||||
         <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
         <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
         <feComponentTransfer>
 | 
			
		||||
            <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
         </feComponentTransfer>
 | 
			
		||||
         <feMerge>
 | 
			
		||||
            <feMergeNode />
 | 
			
		||||
            <feMergeNode in="SourceGraphic" />
 | 
			
		||||
         </feMerge>
 | 
			
		||||
      </filter>
 | 
			
		||||
      <style type="text/css">
 | 
			
		||||
         <![CDATA[
 | 
			
		||||
         /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
         @keyframes am-weather-cloud-2 {
 | 
			
		||||
            0% {
 | 
			
		||||
               -webkit-transform: translate(0px, 0px);
 | 
			
		||||
               -moz-transform: translate(0px, 0px);
 | 
			
		||||
               -ms-transform: translate(0px, 0px);
 | 
			
		||||
               transform: translate(0px, 0px);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            50% {
 | 
			
		||||
               -webkit-transform: translate(2px, 0px);
 | 
			
		||||
               -moz-transform: translate(2px, 0px);
 | 
			
		||||
               -ms-transform: translate(2px, 0px);
 | 
			
		||||
               transform: translate(2px, 0px);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               -webkit-transform: translate(0px, 0px);
 | 
			
		||||
               -moz-transform: translate(0px, 0px);
 | 
			
		||||
               -ms-transform: translate(0px, 0px);
 | 
			
		||||
               transform: translate(0px, 0px);
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-cloud-2 {
 | 
			
		||||
            -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
            -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
            animation-name: am-weather-cloud-2;
 | 
			
		||||
            -webkit-animation-duration: 3s;
 | 
			
		||||
            -moz-animation-duration: 3s;
 | 
			
		||||
            animation-duration: 3s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         /*
 | 
			
		||||
** SUN
 | 
			
		||||
*/
 | 
			
		||||
         @keyframes am-weather-sun {
 | 
			
		||||
            0% {
 | 
			
		||||
               -webkit-transform: rotate(0deg);
 | 
			
		||||
               -moz-transform: rotate(0deg);
 | 
			
		||||
               -ms-transform: rotate(0deg);
 | 
			
		||||
               transform: rotate(0deg);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               -webkit-transform: rotate(360deg);
 | 
			
		||||
               -moz-transform: rotate(360deg);
 | 
			
		||||
               -ms-transform: rotate(360deg);
 | 
			
		||||
               transform: rotate(360deg);
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-sun {
 | 
			
		||||
            -webkit-animation-name: am-weather-sun;
 | 
			
		||||
            -moz-animation-name: am-weather-sun;
 | 
			
		||||
            -ms-animation-name: am-weather-sun;
 | 
			
		||||
            animation-name: am-weather-sun;
 | 
			
		||||
            -webkit-animation-duration: 9s;
 | 
			
		||||
            -moz-animation-duration: 9s;
 | 
			
		||||
            -ms-animation-duration: 9s;
 | 
			
		||||
            animation-duration: 9s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            -ms-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         @keyframes am-weather-sun-shiny {
 | 
			
		||||
            0% {
 | 
			
		||||
               stroke-dasharray: 3px 10px;
 | 
			
		||||
               stroke-dashoffset: 0px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            50% {
 | 
			
		||||
               stroke-dasharray: 0.1px 10px;
 | 
			
		||||
               stroke-dashoffset: -1px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               stroke-dasharray: 3px 10px;
 | 
			
		||||
               stroke-dashoffset: 0px;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-sun-shiny line {
 | 
			
		||||
            -webkit-animation-name: am-weather-sun-shiny;
 | 
			
		||||
            -moz-animation-name: am-weather-sun-shiny;
 | 
			
		||||
            -ms-animation-name: am-weather-sun-shiny;
 | 
			
		||||
            animation-name: am-weather-sun-shiny;
 | 
			
		||||
            -webkit-animation-duration: 2s;
 | 
			
		||||
            -moz-animation-duration: 2s;
 | 
			
		||||
            -ms-animation-duration: 2s;
 | 
			
		||||
            animation-duration: 2s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            -ms-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         /*
 | 
			
		||||
** SNOW
 | 
			
		||||
*/
 | 
			
		||||
         @keyframes am-weather-snow {
 | 
			
		||||
            0% {
 | 
			
		||||
               -webkit-transform: translateX(0) translateY(0);
 | 
			
		||||
               -moz-transform: translateX(0) translateY(0);
 | 
			
		||||
               -ms-transform: translateX(0) translateY(0);
 | 
			
		||||
               transform: translateX(0) translateY(0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            33.33% {
 | 
			
		||||
               -webkit-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
               -moz-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
               -ms-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
               transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            66.66% {
 | 
			
		||||
               -webkit-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
               -moz-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
               -ms-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
               transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
               opacity: 1;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               -webkit-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
               -moz-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
               -ms-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
               transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
               opacity: 0;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         @keyframes am-weather-snow-reverse {
 | 
			
		||||
            0% {
 | 
			
		||||
               -webkit-transform: translateX(0) translateY(0);
 | 
			
		||||
               -moz-transform: translateX(0) translateY(0);
 | 
			
		||||
               -ms-transform: translateX(0) translateY(0);
 | 
			
		||||
               transform: translateX(0) translateY(0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            33.33% {
 | 
			
		||||
               -webkit-transform: translateX(1.2px) translateY(2px);
 | 
			
		||||
               -moz-transform: translateX(1.2px) translateY(2px);
 | 
			
		||||
               -ms-transform: translateX(1.2px) translateY(2px);
 | 
			
		||||
               transform: translateX(1.2px) translateY(2px);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            66.66% {
 | 
			
		||||
               -webkit-transform: translateX(-1.4px) translateY(4px);
 | 
			
		||||
               -moz-transform: translateX(-1.4px) translateY(4px);
 | 
			
		||||
               -ms-transform: translateX(-1.4px) translateY(4px);
 | 
			
		||||
               transform: translateX(-1.4px) translateY(4px);
 | 
			
		||||
               opacity: 1;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               -webkit-transform: translateX(1.6px) translateY(6px);
 | 
			
		||||
               -moz-transform: translateX(1.6px) translateY(6px);
 | 
			
		||||
               -ms-transform: translateX(1.6px) translateY(6px);
 | 
			
		||||
               transform: translateX(1.6px) translateY(6px);
 | 
			
		||||
               opacity: 0;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-snow-1 {
 | 
			
		||||
            -webkit-animation-name: am-weather-snow;
 | 
			
		||||
            -moz-animation-name: am-weather-snow;
 | 
			
		||||
            -ms-animation-name: am-weather-snow;
 | 
			
		||||
            animation-name: am-weather-snow;
 | 
			
		||||
            -webkit-animation-duration: 2s;
 | 
			
		||||
            -moz-animation-duration: 2s;
 | 
			
		||||
            -ms-animation-duration: 2s;
 | 
			
		||||
            animation-duration: 2s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            -ms-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-snow-2 {
 | 
			
		||||
            -webkit-animation-name: am-weather-snow;
 | 
			
		||||
            -moz-animation-name: am-weather-snow;
 | 
			
		||||
            -ms-animation-name: am-weather-snow;
 | 
			
		||||
            animation-name: am-weather-snow;
 | 
			
		||||
            -webkit-animation-delay: 1.2s;
 | 
			
		||||
            -moz-animation-delay: 1.2s;
 | 
			
		||||
            -ms-animation-delay: 1.2s;
 | 
			
		||||
            animation-delay: 1.2s;
 | 
			
		||||
            -webkit-animation-duration: 2s;
 | 
			
		||||
            -moz-animation-duration: 2s;
 | 
			
		||||
            -ms-animation-duration: 2s;
 | 
			
		||||
            animation-duration: 2s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            -ms-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-snow-3 {
 | 
			
		||||
            -webkit-animation-name: am-weather-snow-reverse;
 | 
			
		||||
            -moz-animation-name: am-weather-snow-reverse;
 | 
			
		||||
            -ms-animation-name: am-weather-snow-reverse;
 | 
			
		||||
            animation-name: am-weather-snow-reverse;
 | 
			
		||||
            -webkit-animation-duration: 2s;
 | 
			
		||||
            -moz-animation-duration: 2s;
 | 
			
		||||
            -ms-animation-duration: 2s;
 | 
			
		||||
            animation-duration: 2s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            -ms-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
         }
 | 
			
		||||
         ]]>
 | 
			
		||||
      </style>
 | 
			
		||||
   </defs>
 | 
			
		||||
   <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
      <g transform="translate(0,16)">
 | 
			
		||||
         <g class="am-weather-sun"
 | 
			
		||||
            style="-moz-animation-duration:9s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-sun;-moz-animation-timing-function:linear;-ms-animation-duration:9s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-sun;-ms-animation-timing-function:linear;-webkit-animation-duration:9s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-sun;-webkit-animation-timing-function:linear">
 | 
			
		||||
            <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
               stroke-width="2" />
 | 
			
		||||
            <g transform="rotate(45)">
 | 
			
		||||
               <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
                  stroke-width="2" />
 | 
			
		||||
            </g>
 | 
			
		||||
            <g transform="rotate(90)">
 | 
			
		||||
               <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
                  stroke-width="2" />
 | 
			
		||||
            </g>
 | 
			
		||||
            <g transform="rotate(135)">
 | 
			
		||||
               <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
                  stroke-width="2" />
 | 
			
		||||
            </g>
 | 
			
		||||
            <g transform="scale(-1)">
 | 
			
		||||
               <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
                  stroke-width="2" />
 | 
			
		||||
            </g>
 | 
			
		||||
            <g transform="rotate(225)">
 | 
			
		||||
               <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
                  stroke-width="2" />
 | 
			
		||||
            </g>
 | 
			
		||||
            <g transform="rotate(-90)">
 | 
			
		||||
               <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
                  stroke-width="2" />
 | 
			
		||||
            </g>
 | 
			
		||||
            <g transform="rotate(-45)">
 | 
			
		||||
               <line transform="translate(0,9)" y2="3" fill="none" stroke="#ffa500" stroke-linecap="round"
 | 
			
		||||
                  stroke-width="2" />
 | 
			
		||||
            </g>
 | 
			
		||||
         </g>
 | 
			
		||||
         <circle r="5" fill="#ffa500" stroke="#ffa500" stroke-width="2" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-cloud-2"
 | 
			
		||||
         style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
         <path transform="translate(-20,-11)"
 | 
			
		||||
            d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
            fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-snow-1"
 | 
			
		||||
         style="-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow;-moz-animation-timing-function:linear;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow;-ms-animation-timing-function:linear;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow;-webkit-animation-timing-function:linear">
 | 
			
		||||
         <g transform="translate(3,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
            <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
            <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
         </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-snow-2"
 | 
			
		||||
         style="-moz-animation-delay:1.2s;-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow;-moz-animation-timing-function:linear;-ms-animation-delay:1.2s;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow;-ms-animation-timing-function:linear;-webkit-animation-delay:1.2s;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow;-webkit-animation-timing-function:linear">
 | 
			
		||||
         <g transform="translate(11,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
            <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
            <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
         </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-snow-3"
 | 
			
		||||
         style="-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow-reverse;-moz-animation-timing-function:linear;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow-reverse;-ms-animation-timing-function:linear;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow-reverse;-webkit-animation-timing-function:linear">
 | 
			
		||||
         <g transform="translate(20,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
            <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
            <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
         </g>
 | 
			
		||||
      </g>
 | 
			
		||||
   </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 15 KiB  | 
							
								
								
									
										361
									
								
								public/weather-ico/snowy-3-night.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,361 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- (c) ammap.com | SVG weather icons -->
 | 
			
		||||
<svg width="56" height="48" version="1.1" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
   <defs>
 | 
			
		||||
      <filter id="blur" x="-.24684" y="-.26897" width="1.4937" height="1.6759">
 | 
			
		||||
         <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
 | 
			
		||||
         <feOffset dx="0" dy="4" result="offsetblur" />
 | 
			
		||||
         <feComponentTransfer>
 | 
			
		||||
            <feFuncA slope="0.05" type="linear" />
 | 
			
		||||
         </feComponentTransfer>
 | 
			
		||||
         <feMerge>
 | 
			
		||||
            <feMergeNode />
 | 
			
		||||
            <feMergeNode in="SourceGraphic" />
 | 
			
		||||
         </feMerge>
 | 
			
		||||
      </filter>
 | 
			
		||||
      <style type="text/css">
 | 
			
		||||
         <![CDATA[
 | 
			
		||||
         /*
 | 
			
		||||
** CLOUDS
 | 
			
		||||
*/
 | 
			
		||||
         @keyframes am-weather-cloud-2 {
 | 
			
		||||
            0% {
 | 
			
		||||
               -webkit-transform: translate(0px, 0px);
 | 
			
		||||
               -moz-transform: translate(0px, 0px);
 | 
			
		||||
               -ms-transform: translate(0px, 0px);
 | 
			
		||||
               transform: translate(0px, 0px);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            50% {
 | 
			
		||||
               -webkit-transform: translate(2px, 0px);
 | 
			
		||||
               -moz-transform: translate(2px, 0px);
 | 
			
		||||
               -ms-transform: translate(2px, 0px);
 | 
			
		||||
               transform: translate(2px, 0px);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               -webkit-transform: translate(0px, 0px);
 | 
			
		||||
               -moz-transform: translate(0px, 0px);
 | 
			
		||||
               -ms-transform: translate(0px, 0px);
 | 
			
		||||
               transform: translate(0px, 0px);
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-cloud-2 {
 | 
			
		||||
            -webkit-animation-name: am-weather-cloud-2;
 | 
			
		||||
            -moz-animation-name: am-weather-cloud-2;
 | 
			
		||||
            animation-name: am-weather-cloud-2;
 | 
			
		||||
            -webkit-animation-duration: 3s;
 | 
			
		||||
            -moz-animation-duration: 3s;
 | 
			
		||||
            animation-duration: 3s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         /*
 | 
			
		||||
** MOON
 | 
			
		||||
*/
 | 
			
		||||
         @keyframes am-weather-moon {
 | 
			
		||||
            0% {
 | 
			
		||||
               -webkit-transform: rotate(0deg);
 | 
			
		||||
               -moz-transform: rotate(0deg);
 | 
			
		||||
               -ms-transform: rotate(0deg);
 | 
			
		||||
               transform: rotate(0deg);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            50% {
 | 
			
		||||
               -webkit-transform: rotate(15deg);
 | 
			
		||||
               -moz-transform: rotate(15deg);
 | 
			
		||||
               -ms-transform: rotate(15deg);
 | 
			
		||||
               transform: rotate(15deg);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               -webkit-transform: rotate(0deg);
 | 
			
		||||
               -moz-transform: rotate(0deg);
 | 
			
		||||
               -ms-transform: rotate(0deg);
 | 
			
		||||
               transform: rotate(0deg);
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-moon {
 | 
			
		||||
            -webkit-animation-name: am-weather-moon;
 | 
			
		||||
            -moz-animation-name: am-weather-moon;
 | 
			
		||||
            -ms-animation-name: am-weather-moon;
 | 
			
		||||
            animation-name: am-weather-moon;
 | 
			
		||||
            -webkit-animation-duration: 6s;
 | 
			
		||||
            -moz-animation-duration: 6s;
 | 
			
		||||
            -ms-animation-duration: 6s;
 | 
			
		||||
            animation-duration: 6s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            -ms-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
            -webkit-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
            /* TODO FF CENTER ISSUE */
 | 
			
		||||
            -moz-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
            /* TODO FF CENTER ISSUE */
 | 
			
		||||
            -ms-transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
            /* TODO FF CENTER ISSUE */
 | 
			
		||||
            transform-origin: 12.5px 15.15px 0;
 | 
			
		||||
            /* TODO FF CENTER ISSUE */
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         @keyframes am-weather-moon-star-1 {
 | 
			
		||||
            0% {
 | 
			
		||||
               opacity: 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               opacity: 1;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-moon-star-1 {
 | 
			
		||||
            -webkit-animation-name: am-weather-moon-star-1;
 | 
			
		||||
            -moz-animation-name: am-weather-moon-star-1;
 | 
			
		||||
            -ms-animation-name: am-weather-moon-star-1;
 | 
			
		||||
            animation-name: am-weather-moon-star-1;
 | 
			
		||||
            -webkit-animation-delay: 3s;
 | 
			
		||||
            -moz-animation-delay: 3s;
 | 
			
		||||
            -ms-animation-delay: 3s;
 | 
			
		||||
            animation-delay: 3s;
 | 
			
		||||
            -webkit-animation-duration: 5s;
 | 
			
		||||
            -moz-animation-duration: 5s;
 | 
			
		||||
            -ms-animation-duration: 5s;
 | 
			
		||||
            animation-duration: 5s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: 1;
 | 
			
		||||
            -moz-animation-iteration-count: 1;
 | 
			
		||||
            -ms-animation-iteration-count: 1;
 | 
			
		||||
            animation-iteration-count: 1;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         @keyframes am-weather-moon-star-2 {
 | 
			
		||||
            0% {
 | 
			
		||||
               opacity: 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               opacity: 1;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-moon-star-2 {
 | 
			
		||||
            -webkit-animation-name: am-weather-moon-star-2;
 | 
			
		||||
            -moz-animation-name: am-weather-moon-star-2;
 | 
			
		||||
            -ms-animation-name: am-weather-moon-star-2;
 | 
			
		||||
            animation-name: am-weather-moon-star-2;
 | 
			
		||||
            -webkit-animation-delay: 5s;
 | 
			
		||||
            -moz-animation-delay: 5s;
 | 
			
		||||
            -ms-animation-delay: 5s;
 | 
			
		||||
            animation-delay: 5s;
 | 
			
		||||
            -webkit-animation-duration: 4s;
 | 
			
		||||
            -moz-animation-duration: 4s;
 | 
			
		||||
            -ms-animation-duration: 4s;
 | 
			
		||||
            animation-duration: 4s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: 1;
 | 
			
		||||
            -moz-animation-iteration-count: 1;
 | 
			
		||||
            -ms-animation-iteration-count: 1;
 | 
			
		||||
            animation-iteration-count: 1;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         /*
 | 
			
		||||
** SNOW
 | 
			
		||||
*/
 | 
			
		||||
         @keyframes am-weather-snow {
 | 
			
		||||
            0% {
 | 
			
		||||
               -webkit-transform: translateX(0) translateY(0);
 | 
			
		||||
               -moz-transform: translateX(0) translateY(0);
 | 
			
		||||
               -ms-transform: translateX(0) translateY(0);
 | 
			
		||||
               transform: translateX(0) translateY(0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            33.33% {
 | 
			
		||||
               -webkit-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
               -moz-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
               -ms-transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
               transform: translateX(-1.2px) translateY(2px);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            66.66% {
 | 
			
		||||
               -webkit-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
               -moz-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
               -ms-transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
               transform: translateX(1.4px) translateY(4px);
 | 
			
		||||
               opacity: 1;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               -webkit-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
               -moz-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
               -ms-transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
               transform: translateX(-1.6px) translateY(6px);
 | 
			
		||||
               opacity: 0;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         @keyframes am-weather-snow-reverse {
 | 
			
		||||
            0% {
 | 
			
		||||
               -webkit-transform: translateX(0) translateY(0);
 | 
			
		||||
               -moz-transform: translateX(0) translateY(0);
 | 
			
		||||
               -ms-transform: translateX(0) translateY(0);
 | 
			
		||||
               transform: translateX(0) translateY(0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            33.33% {
 | 
			
		||||
               -webkit-transform: translateX(1.2px) translateY(2px);
 | 
			
		||||
               -moz-transform: translateX(1.2px) translateY(2px);
 | 
			
		||||
               -ms-transform: translateX(1.2px) translateY(2px);
 | 
			
		||||
               transform: translateX(1.2px) translateY(2px);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            66.66% {
 | 
			
		||||
               -webkit-transform: translateX(-1.4px) translateY(4px);
 | 
			
		||||
               -moz-transform: translateX(-1.4px) translateY(4px);
 | 
			
		||||
               -ms-transform: translateX(-1.4px) translateY(4px);
 | 
			
		||||
               transform: translateX(-1.4px) translateY(4px);
 | 
			
		||||
               opacity: 1;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            100% {
 | 
			
		||||
               -webkit-transform: translateX(1.6px) translateY(6px);
 | 
			
		||||
               -moz-transform: translateX(1.6px) translateY(6px);
 | 
			
		||||
               -ms-transform: translateX(1.6px) translateY(6px);
 | 
			
		||||
               transform: translateX(1.6px) translateY(6px);
 | 
			
		||||
               opacity: 0;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-snow-1 {
 | 
			
		||||
            -webkit-animation-name: am-weather-snow;
 | 
			
		||||
            -moz-animation-name: am-weather-snow;
 | 
			
		||||
            -ms-animation-name: am-weather-snow;
 | 
			
		||||
            animation-name: am-weather-snow;
 | 
			
		||||
            -webkit-animation-duration: 2s;
 | 
			
		||||
            -moz-animation-duration: 2s;
 | 
			
		||||
            -ms-animation-duration: 2s;
 | 
			
		||||
            animation-duration: 2s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            -ms-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-snow-2 {
 | 
			
		||||
            -webkit-animation-name: am-weather-snow;
 | 
			
		||||
            -moz-animation-name: am-weather-snow;
 | 
			
		||||
            -ms-animation-name: am-weather-snow;
 | 
			
		||||
            animation-name: am-weather-snow;
 | 
			
		||||
            -webkit-animation-delay: 1.2s;
 | 
			
		||||
            -moz-animation-delay: 1.2s;
 | 
			
		||||
            -ms-animation-delay: 1.2s;
 | 
			
		||||
            animation-delay: 1.2s;
 | 
			
		||||
            -webkit-animation-duration: 2s;
 | 
			
		||||
            -moz-animation-duration: 2s;
 | 
			
		||||
            -ms-animation-duration: 2s;
 | 
			
		||||
            animation-duration: 2s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            -ms-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         .am-weather-snow-3 {
 | 
			
		||||
            -webkit-animation-name: am-weather-snow-reverse;
 | 
			
		||||
            -moz-animation-name: am-weather-snow-reverse;
 | 
			
		||||
            -ms-animation-name: am-weather-snow-reverse;
 | 
			
		||||
            animation-name: am-weather-snow-reverse;
 | 
			
		||||
            -webkit-animation-duration: 2s;
 | 
			
		||||
            -moz-animation-duration: 2s;
 | 
			
		||||
            -ms-animation-duration: 2s;
 | 
			
		||||
            animation-duration: 2s;
 | 
			
		||||
            -webkit-animation-timing-function: linear;
 | 
			
		||||
            -moz-animation-timing-function: linear;
 | 
			
		||||
            -ms-animation-timing-function: linear;
 | 
			
		||||
            animation-timing-function: linear;
 | 
			
		||||
            -webkit-animation-iteration-count: infinite;
 | 
			
		||||
            -moz-animation-iteration-count: infinite;
 | 
			
		||||
            -ms-animation-iteration-count: infinite;
 | 
			
		||||
            animation-iteration-count: infinite;
 | 
			
		||||
         }
 | 
			
		||||
         ]]>
 | 
			
		||||
      </style>
 | 
			
		||||
   </defs>
 | 
			
		||||
   <g transform="translate(16,-2)" filter="url(#blur)">
 | 
			
		||||
      <g transform="matrix(.8 0 0 .8 16 4)">
 | 
			
		||||
         <g class="am-weather-moon-star-1"
 | 
			
		||||
            style="-moz-animation-delay:3s;-moz-animation-duration:5s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-1;-moz-animation-timing-function:linear;-ms-animation-delay:3s;-ms-animation-duration:5s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-1;-ms-animation-timing-function:linear;-webkit-animation-delay:3s;-webkit-animation-duration:5s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-1;-webkit-animation-timing-function:linear">
 | 
			
		||||
            <polygon points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3" fill="#ffa500"
 | 
			
		||||
               stroke-miterlimit="10" />
 | 
			
		||||
         </g>
 | 
			
		||||
         <g class="am-weather-moon-star-2"
 | 
			
		||||
            style="-moz-animation-delay:5s;-moz-animation-duration:4s;-moz-animation-iteration-count:1;-moz-animation-name:am-weather-moon-star-2;-moz-animation-timing-function:linear;-ms-animation-delay:5s;-ms-animation-duration:4s;-ms-animation-iteration-count:1;-ms-animation-name:am-weather-moon-star-2;-ms-animation-timing-function:linear;-webkit-animation-delay:5s;-webkit-animation-duration:4s;-webkit-animation-iteration-count:1;-webkit-animation-name:am-weather-moon-star-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
            <polygon transform="translate(20,10)" points="4 4 3.3 5.2 2.7 4 1.5 3.3 2.7 2.7 3.3 1.5 4 2.7 5.2 3.3"
 | 
			
		||||
               fill="#ffa500" stroke-miterlimit="10" />
 | 
			
		||||
         </g>
 | 
			
		||||
         <g class="am-weather-moon"
 | 
			
		||||
            style="-moz-animation-duration:6s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-moon;-moz-animation-timing-function:linear;-moz-transform-origin:12.5px 15.15px 0;-ms-animation-duration:6s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-moon;-ms-animation-timing-function:linear;-ms-transform-origin:12.5px 15.15px 0;-webkit-animation-duration:6s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-moon;-webkit-animation-timing-function:linear;-webkit-transform-origin:12.5px 15.15px 0">
 | 
			
		||||
            <path
 | 
			
		||||
               d="m14.5 13.2c0-3.7 2-6.9 5-8.7-1.5-0.9-3.2-1.3-5-1.3-5.5 0-10 4.5-10 10s4.5 10 10 10c1.8 0 3.5-0.5 5-1.3-3-1.7-5-5-5-8.7z"
 | 
			
		||||
               fill="#ffa500" stroke="#ffa500" stroke-linejoin="round" stroke-width="2" />
 | 
			
		||||
         </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-cloud-2"
 | 
			
		||||
         style="-moz-animation-duration:3s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-cloud-2;-moz-animation-timing-function:linear;-webkit-animation-duration:3s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-cloud-2;-webkit-animation-timing-function:linear">
 | 
			
		||||
         <path transform="translate(-20,-11)"
 | 
			
		||||
            d="m47.7 35.4c0-4.6-3.7-8.2-8.2-8.2-1 0-1.9 0.2-2.8 0.5-0.3-3.4-3.1-6.2-6.6-6.2-3.7 0-6.7 3-6.7 6.7 0 0.8 0.2 1.6 0.4 2.3-0.3-0.1-0.7-0.1-1-0.1-3.7 0-6.7 3-6.7 6.7 0 3.6 2.9 6.6 6.5 6.7h17.2c4.4-0.5 7.9-4 7.9-8.4z"
 | 
			
		||||
            fill="#57a0ee" stroke="#fff" stroke-linejoin="round" stroke-width="1.2" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-snow-1"
 | 
			
		||||
         style="-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow;-moz-animation-timing-function:linear;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow;-ms-animation-timing-function:linear;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow;-webkit-animation-timing-function:linear">
 | 
			
		||||
         <g transform="translate(3,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
            <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
            <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
         </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-snow-2"
 | 
			
		||||
         style="-moz-animation-delay:1.2s;-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow;-moz-animation-timing-function:linear;-ms-animation-delay:1.2s;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow;-ms-animation-timing-function:linear;-webkit-animation-delay:1.2s;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow;-webkit-animation-timing-function:linear">
 | 
			
		||||
         <g transform="translate(11,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
            <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
            <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
         </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <g class="am-weather-snow-3"
 | 
			
		||||
         style="-moz-animation-duration:2s;-moz-animation-iteration-count:infinite;-moz-animation-name:am-weather-snow-reverse;-moz-animation-timing-function:linear;-ms-animation-duration:2s;-ms-animation-iteration-count:infinite;-ms-animation-name:am-weather-snow-reverse;-ms-animation-timing-function:linear;-webkit-animation-duration:2s;-webkit-animation-iteration-count:infinite;-webkit-animation-name:am-weather-snow-reverse;-webkit-animation-timing-function:linear">
 | 
			
		||||
         <g transform="translate(20,28)" fill="none" stroke="#57a0ee" stroke-linecap="round">
 | 
			
		||||
            <line transform="translate(0,9)" y1="-2.5" y2="2.5" stroke-width="1.2" />
 | 
			
		||||
            <line transform="rotate(45,-10.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(90,-4.5,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
            <line transform="rotate(135,-1.864,4.5)" y1="-2.5" y2="2.5" />
 | 
			
		||||
         </g>
 | 
			
		||||
      </g>
 | 
			
		||||
   </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 17 KiB  | 
@@ -25,5 +25,11 @@ API_URL = "" # Ollama API URL - http://host.docker.internal:11434
 | 
			
		||||
[MODELS.DEEPSEEK]
 | 
			
		||||
API_KEY = ""
 | 
			
		||||
 | 
			
		||||
[MODELS.AIMLAPI]
 | 
			
		||||
API_KEY = "" # Required to use AI/ML API chat and embedding models
 | 
			
		||||
 | 
			
		||||
[MODELS.LM_STUDIO]
 | 
			
		||||
API_URL = "" # LM Studio API URL - http://host.docker.internal:1234
 | 
			
		||||
 | 
			
		||||
[API_ENDPOINTS]
 | 
			
		||||
SEARXNG = "" # SearxNG API URL - http://localhost:32768
 | 
			
		||||
@@ -223,7 +223,7 @@ export const POST = async (req: Request) => {
 | 
			
		||||
 | 
			
		||||
    if (body.chatModel?.provider === 'custom_openai') {
 | 
			
		||||
      llm = new ChatOpenAI({
 | 
			
		||||
        openAIApiKey: getCustomOpenaiApiKey(),
 | 
			
		||||
        apiKey: getCustomOpenaiApiKey(),
 | 
			
		||||
        modelName: getCustomOpenaiModelName(),
 | 
			
		||||
        temperature: 0.7,
 | 
			
		||||
        configuration: {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,8 @@ import {
 | 
			
		||||
  getOllamaApiEndpoint,
 | 
			
		||||
  getOpenaiApiKey,
 | 
			
		||||
  getDeepseekApiKey,
 | 
			
		||||
  getAimlApiKey,
 | 
			
		||||
  getLMStudioApiEndpoint,
 | 
			
		||||
  updateConfig,
 | 
			
		||||
} from '@/lib/config';
 | 
			
		||||
import {
 | 
			
		||||
@@ -51,10 +53,12 @@ export const GET = async (req: Request) => {
 | 
			
		||||
 | 
			
		||||
    config['openaiApiKey'] = getOpenaiApiKey();
 | 
			
		||||
    config['ollamaApiUrl'] = getOllamaApiEndpoint();
 | 
			
		||||
    config['lmStudioApiUrl'] = getLMStudioApiEndpoint();
 | 
			
		||||
    config['anthropicApiKey'] = getAnthropicApiKey();
 | 
			
		||||
    config['groqApiKey'] = getGroqApiKey();
 | 
			
		||||
    config['geminiApiKey'] = getGeminiApiKey();
 | 
			
		||||
    config['deepseekApiKey'] = getDeepseekApiKey();
 | 
			
		||||
    config['aimlApiKey'] = getAimlApiKey();
 | 
			
		||||
    config['customOpenaiApiUrl'] = getCustomOpenaiApiUrl();
 | 
			
		||||
    config['customOpenaiApiKey'] = getCustomOpenaiApiKey();
 | 
			
		||||
    config['customOpenaiModelName'] = getCustomOpenaiModelName();
 | 
			
		||||
@@ -93,6 +97,12 @@ export const POST = async (req: Request) => {
 | 
			
		||||
        DEEPSEEK: {
 | 
			
		||||
          API_KEY: config.deepseekApiKey,
 | 
			
		||||
        },
 | 
			
		||||
        AIMLAPI: {
 | 
			
		||||
          API_KEY: config.aimlApiKey,
 | 
			
		||||
        },
 | 
			
		||||
        LM_STUDIO: {
 | 
			
		||||
          API_URL: config.lmStudioApiUrl,
 | 
			
		||||
        },
 | 
			
		||||
        CUSTOM_OPENAI: {
 | 
			
		||||
          API_URL: config.customOpenaiApiUrl,
 | 
			
		||||
          API_KEY: config.customOpenaiApiKey,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,43 +1,80 @@
 | 
			
		||||
import { searchSearxng } from '@/lib/searxng';
 | 
			
		||||
 | 
			
		||||
const articleWebsites = [
 | 
			
		||||
  'yahoo.com',
 | 
			
		||||
  'www.exchangewire.com',
 | 
			
		||||
  'businessinsider.com',
 | 
			
		||||
  /* 'wired.com',
 | 
			
		||||
  'mashable.com',
 | 
			
		||||
  'theverge.com',
 | 
			
		||||
  'gizmodo.com',
 | 
			
		||||
  'cnet.com',
 | 
			
		||||
  'venturebeat.com', */
 | 
			
		||||
];
 | 
			
		||||
const websitesForTopic = {
 | 
			
		||||
  tech: {
 | 
			
		||||
    query: ['technology news', 'latest tech', 'AI', 'science and innovation'],
 | 
			
		||||
    links: ['techcrunch.com', 'wired.com', 'theverge.com'],
 | 
			
		||||
  },
 | 
			
		||||
  finance: {
 | 
			
		||||
    query: ['finance news', 'economy', 'stock market', 'investing'],
 | 
			
		||||
    links: ['bloomberg.com', 'cnbc.com', 'marketwatch.com'],
 | 
			
		||||
  },
 | 
			
		||||
  art: {
 | 
			
		||||
    query: ['art news', 'culture', 'modern art', 'cultural events'],
 | 
			
		||||
    links: ['artnews.com', 'hyperallergic.com', 'theartnewspaper.com'],
 | 
			
		||||
  },
 | 
			
		||||
  sports: {
 | 
			
		||||
    query: ['sports news', 'latest sports', 'cricket football tennis'],
 | 
			
		||||
    links: ['espn.com', 'bbc.com/sport', 'skysports.com'],
 | 
			
		||||
  },
 | 
			
		||||
  entertainment: {
 | 
			
		||||
    query: ['entertainment news', 'movies', 'TV shows', 'celebrities'],
 | 
			
		||||
    links: ['hollywoodreporter.com', 'variety.com', 'deadline.com'],
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const topics = ['AI', 'tech']; /* TODO: Add UI to customize this */
 | 
			
		||||
type Topic = keyof typeof websitesForTopic;
 | 
			
		||||
 | 
			
		||||
export const GET = async (req: Request) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const data = (
 | 
			
		||||
      await Promise.all([
 | 
			
		||||
        ...new Array(articleWebsites.length * topics.length)
 | 
			
		||||
          .fill(0)
 | 
			
		||||
          .map(async (_, i) => {
 | 
			
		||||
    const params = new URL(req.url).searchParams;
 | 
			
		||||
 | 
			
		||||
    const mode: 'normal' | 'preview' =
 | 
			
		||||
      (params.get('mode') as 'normal' | 'preview') || 'normal';
 | 
			
		||||
    const topic: Topic = (params.get('topic') as Topic) || 'tech';
 | 
			
		||||
 | 
			
		||||
    const selectedTopic = websitesForTopic[topic];
 | 
			
		||||
 | 
			
		||||
    let data = [];
 | 
			
		||||
 | 
			
		||||
    if (mode === 'normal') {
 | 
			
		||||
      const seenUrls = new Set();
 | 
			
		||||
 | 
			
		||||
      data = (
 | 
			
		||||
        await Promise.all(
 | 
			
		||||
          selectedTopic.links.flatMap((link) =>
 | 
			
		||||
            selectedTopic.query.map(async (query) => {
 | 
			
		||||
              return (
 | 
			
		||||
                await searchSearxng(`site:${link} ${query}`, {
 | 
			
		||||
                  engines: ['bing news'],
 | 
			
		||||
                  pageno: 1,
 | 
			
		||||
                  language: 'en',
 | 
			
		||||
                })
 | 
			
		||||
              ).results;
 | 
			
		||||
            }),
 | 
			
		||||
          ),
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
        .flat()
 | 
			
		||||
        .filter((item) => {
 | 
			
		||||
          const url = item.url?.toLowerCase().trim();
 | 
			
		||||
          if (seenUrls.has(url)) return false;
 | 
			
		||||
          seenUrls.add(url);
 | 
			
		||||
          return true;
 | 
			
		||||
        })
 | 
			
		||||
        .sort(() => Math.random() - 0.5);
 | 
			
		||||
    } else {
 | 
			
		||||
      data = (
 | 
			
		||||
        await searchSearxng(
 | 
			
		||||
                `site:${articleWebsites[i % articleWebsites.length]} ${
 | 
			
		||||
                  topics[i % topics.length]
 | 
			
		||||
                }`,
 | 
			
		||||
          `site:${selectedTopic.links[Math.floor(Math.random() * selectedTopic.links.length)]} ${selectedTopic.query[Math.floor(Math.random() * selectedTopic.query.length)]}`,
 | 
			
		||||
          {
 | 
			
		||||
            engines: ['bing news'],
 | 
			
		||||
            pageno: 1,
 | 
			
		||||
            language: 'en',
 | 
			
		||||
          },
 | 
			
		||||
        )
 | 
			
		||||
      ).results;
 | 
			
		||||
          }),
 | 
			
		||||
      ])
 | 
			
		||||
    )
 | 
			
		||||
      .map((result) => result)
 | 
			
		||||
      .flat()
 | 
			
		||||
      .sort(() => Math.random() - 0.5);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Response.json(
 | 
			
		||||
      {
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ export const POST = async (req: Request) => {
 | 
			
		||||
 | 
			
		||||
    if (body.chatModel?.provider === 'custom_openai') {
 | 
			
		||||
      llm = new ChatOpenAI({
 | 
			
		||||
        openAIApiKey: getCustomOpenaiApiKey(),
 | 
			
		||||
        apiKey: getCustomOpenaiApiKey(),
 | 
			
		||||
        modelName: getCustomOpenaiModelName(),
 | 
			
		||||
        temperature: 0.7,
 | 
			
		||||
        configuration: {
 | 
			
		||||
 
 | 
			
		||||
@@ -81,8 +81,7 @@ export const POST = async (req: Request) => {
 | 
			
		||||
    if (body.chatModel?.provider === 'custom_openai') {
 | 
			
		||||
      llm = new ChatOpenAI({
 | 
			
		||||
        modelName: body.chatModel?.name || getCustomOpenaiModelName(),
 | 
			
		||||
        openAIApiKey:
 | 
			
		||||
          body.chatModel?.customOpenAIKey || getCustomOpenaiApiKey(),
 | 
			
		||||
        apiKey: body.chatModel?.customOpenAIKey || getCustomOpenaiApiKey(),
 | 
			
		||||
        temperature: 0.7,
 | 
			
		||||
        configuration: {
 | 
			
		||||
          baseURL:
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@ export const POST = async (req: Request) => {
 | 
			
		||||
 | 
			
		||||
    if (body.chatModel?.provider === 'custom_openai') {
 | 
			
		||||
      llm = new ChatOpenAI({
 | 
			
		||||
        openAIApiKey: getCustomOpenaiApiKey(),
 | 
			
		||||
        apiKey: getCustomOpenaiApiKey(),
 | 
			
		||||
        modelName: getCustomOpenaiModelName(),
 | 
			
		||||
        temperature: 0.7,
 | 
			
		||||
        configuration: {
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ export const POST = async (req: Request) => {
 | 
			
		||||
 | 
			
		||||
    if (body.chatModel?.provider === 'custom_openai') {
 | 
			
		||||
      llm = new ChatOpenAI({
 | 
			
		||||
        openAIApiKey: getCustomOpenaiApiKey(),
 | 
			
		||||
        apiKey: getCustomOpenaiApiKey(),
 | 
			
		||||
        modelName: getCustomOpenaiModelName(),
 | 
			
		||||
        temperature: 0.7,
 | 
			
		||||
        configuration: {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										174
									
								
								src/app/api/weather/route.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,174 @@
 | 
			
		||||
export const POST = async (req: Request) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const body: {
 | 
			
		||||
      lat: number;
 | 
			
		||||
      lng: number;
 | 
			
		||||
      measureUnit: 'Imperial' | 'Metric';
 | 
			
		||||
    } = await req.json();
 | 
			
		||||
 | 
			
		||||
    if (!body.lat || !body.lng) {
 | 
			
		||||
      return Response.json(
 | 
			
		||||
        {
 | 
			
		||||
          message: 'Invalid request.',
 | 
			
		||||
        },
 | 
			
		||||
        { status: 400 },
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const res = await fetch(
 | 
			
		||||
      `https://api.open-meteo.com/v1/forecast?latitude=${body.lat}&longitude=${body.lng}¤t=weather_code,temperature_2m,is_day,relative_humidity_2m,wind_speed_10m&timezone=auto${
 | 
			
		||||
        body.measureUnit === 'Metric' ? '' : '&temperature_unit=fahrenheit'
 | 
			
		||||
      }${body.measureUnit === 'Metric' ? '' : '&wind_speed_unit=mph'}`,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const data = await res.json();
 | 
			
		||||
 | 
			
		||||
    if (data.error) {
 | 
			
		||||
      console.error(`Error fetching weather data: ${data.reason}`);
 | 
			
		||||
      return Response.json(
 | 
			
		||||
        {
 | 
			
		||||
          message: 'An error has occurred.',
 | 
			
		||||
        },
 | 
			
		||||
        { status: 500 },
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const weather: {
 | 
			
		||||
      temperature: number;
 | 
			
		||||
      condition: string;
 | 
			
		||||
      humidity: number;
 | 
			
		||||
      windSpeed: number;
 | 
			
		||||
      icon: string;
 | 
			
		||||
      temperatureUnit: 'C' | 'F';
 | 
			
		||||
      windSpeedUnit: 'm/s' | 'mph';
 | 
			
		||||
    } = {
 | 
			
		||||
      temperature: data.current.temperature_2m,
 | 
			
		||||
      condition: '',
 | 
			
		||||
      humidity: data.current.relative_humidity_2m,
 | 
			
		||||
      windSpeed: data.current.wind_speed_10m,
 | 
			
		||||
      icon: '',
 | 
			
		||||
      temperatureUnit: body.measureUnit === 'Metric' ? 'C' : 'F',
 | 
			
		||||
      windSpeedUnit: body.measureUnit === 'Metric' ? 'm/s' : 'mph',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const code = data.current.weather_code;
 | 
			
		||||
    const isDay = data.current.is_day === 1;
 | 
			
		||||
    const dayOrNight = isDay ? 'day' : 'night';
 | 
			
		||||
 | 
			
		||||
    switch (code) {
 | 
			
		||||
      case 0:
 | 
			
		||||
        weather.icon = `clear-${dayOrNight}`;
 | 
			
		||||
        weather.condition = 'Clear';
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 1:
 | 
			
		||||
        weather.condition = 'Mainly Clear';
 | 
			
		||||
      case 2:
 | 
			
		||||
        weather.condition = 'Partly Cloudy';
 | 
			
		||||
      case 3:
 | 
			
		||||
        weather.icon = `cloudy-1-${dayOrNight}`;
 | 
			
		||||
        weather.condition = 'Cloudy';
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 45:
 | 
			
		||||
        weather.condition = 'Fog';
 | 
			
		||||
      case 48:
 | 
			
		||||
        weather.icon = `fog-${dayOrNight}`;
 | 
			
		||||
        weather.condition = 'Fog';
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 51:
 | 
			
		||||
        weather.condition = 'Light Drizzle';
 | 
			
		||||
      case 53:
 | 
			
		||||
        weather.condition = 'Moderate Drizzle';
 | 
			
		||||
      case 55:
 | 
			
		||||
        weather.icon = `rainy-1-${dayOrNight}`;
 | 
			
		||||
        weather.condition = 'Dense Drizzle';
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 56:
 | 
			
		||||
        weather.condition = 'Light Freezing Drizzle';
 | 
			
		||||
      case 57:
 | 
			
		||||
        weather.icon = `frost-${dayOrNight}`;
 | 
			
		||||
        weather.condition = 'Dense Freezing Drizzle';
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 61:
 | 
			
		||||
        weather.condition = 'Slight Rain';
 | 
			
		||||
      case 63:
 | 
			
		||||
        weather.condition = 'Moderate Rain';
 | 
			
		||||
      case 65:
 | 
			
		||||
        weather.condition = 'Heavy Rain';
 | 
			
		||||
        weather.icon = `rainy-2-${dayOrNight}`;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 66:
 | 
			
		||||
        weather.condition = 'Light Freezing Rain';
 | 
			
		||||
      case 67:
 | 
			
		||||
        weather.condition = 'Heavy Freezing Rain';
 | 
			
		||||
        weather.icon = 'rain-and-sleet-mix';
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 71:
 | 
			
		||||
        weather.condition = 'Slight Snow Fall';
 | 
			
		||||
      case 73:
 | 
			
		||||
        weather.condition = 'Moderate Snow Fall';
 | 
			
		||||
      case 75:
 | 
			
		||||
        weather.condition = 'Heavy Snow Fall';
 | 
			
		||||
        weather.icon = `snowy-2-${dayOrNight}`;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 77:
 | 
			
		||||
        weather.condition = 'Snow';
 | 
			
		||||
        weather.icon = `snowy-1-${dayOrNight}`;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 80:
 | 
			
		||||
        weather.condition = 'Slight Rain Showers';
 | 
			
		||||
      case 81:
 | 
			
		||||
        weather.condition = 'Moderate Rain Showers';
 | 
			
		||||
      case 82:
 | 
			
		||||
        weather.condition = 'Heavy Rain Showers';
 | 
			
		||||
        weather.icon = `rainy-3-${dayOrNight}`;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 85:
 | 
			
		||||
        weather.condition = 'Slight Snow Showers';
 | 
			
		||||
      case 86:
 | 
			
		||||
        weather.condition = 'Moderate Snow Showers';
 | 
			
		||||
      case 87:
 | 
			
		||||
        weather.condition = 'Heavy Snow Showers';
 | 
			
		||||
        weather.icon = `snowy-3-${dayOrNight}`;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 95:
 | 
			
		||||
        weather.condition = 'Thunderstorm';
 | 
			
		||||
        weather.icon = `scattered-thunderstorms-${dayOrNight}`;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 96:
 | 
			
		||||
        weather.condition = 'Thunderstorm with Slight Hail';
 | 
			
		||||
      case 99:
 | 
			
		||||
        weather.condition = 'Thunderstorm with Heavy Hail';
 | 
			
		||||
        weather.icon = 'severe-thunderstorm';
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      default:
 | 
			
		||||
        weather.icon = `clear-${dayOrNight}`;
 | 
			
		||||
        weather.condition = 'Clear';
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Response.json(weather);
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    console.error('An error occurred while getting home widgets', err);
 | 
			
		||||
    return Response.json(
 | 
			
		||||
      {
 | 
			
		||||
        message: 'An error has occurred.',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        status: 500,
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -4,6 +4,7 @@ import { Search } from 'lucide-react';
 | 
			
		||||
import { useEffect, useState } from 'react';
 | 
			
		||||
import Link from 'next/link';
 | 
			
		||||
import { toast } from 'sonner';
 | 
			
		||||
import { cn } from '@/lib/utils';
 | 
			
		||||
 | 
			
		||||
interface Discover {
 | 
			
		||||
  title: string;
 | 
			
		||||
@@ -12,14 +13,38 @@ interface Discover {
 | 
			
		||||
  thumbnail: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const topics: { key: string; display: string }[] = [
 | 
			
		||||
  {
 | 
			
		||||
    display: 'Tech & Science',
 | 
			
		||||
    key: 'tech',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    display: 'Finance',
 | 
			
		||||
    key: 'finance',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    display: 'Art & Culture',
 | 
			
		||||
    key: 'art',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    display: 'Sports',
 | 
			
		||||
    key: 'sports',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    display: 'Entertainment',
 | 
			
		||||
    key: 'entertainment',
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const Page = () => {
 | 
			
		||||
  const [discover, setDiscover] = useState<Discover[] | null>(null);
 | 
			
		||||
  const [loading, setLoading] = useState(true);
 | 
			
		||||
  const [activeTopic, setActiveTopic] = useState<string>(topics[0].key);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const fetchData = async () => {
 | 
			
		||||
  const fetchArticles = async (topic: string) => {
 | 
			
		||||
    setLoading(true);
 | 
			
		||||
    try {
 | 
			
		||||
        const res = await fetch(`/api/discover`, {
 | 
			
		||||
      const res = await fetch(`/api/discover?topic=${topic}`, {
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        headers: {
 | 
			
		||||
          'Content-Type': 'application/json',
 | 
			
		||||
@@ -43,10 +68,39 @@ const Page = () => {
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
    fetchData();
 | 
			
		||||
  }, []);
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    fetchArticles(activeTopic);
 | 
			
		||||
  }, [activeTopic]);
 | 
			
		||||
 | 
			
		||||
  return loading ? (
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <div>
 | 
			
		||||
        <div className="flex flex-col pt-4">
 | 
			
		||||
          <div className="flex items-center">
 | 
			
		||||
            <Search />
 | 
			
		||||
            <h1 className="text-3xl font-medium p-2">Discover</h1>
 | 
			
		||||
          </div>
 | 
			
		||||
          <hr className="border-t border-[#2B2C2C] my-4 w-full" />
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div className="flex flex-row items-center space-x-2 overflow-x-auto">
 | 
			
		||||
          {topics.map((t, i) => (
 | 
			
		||||
            <div
 | 
			
		||||
              key={i}
 | 
			
		||||
              className={cn(
 | 
			
		||||
                'border-[0.1px] rounded-full text-sm px-3 py-1 text-nowrap transition duration-200 cursor-pointer',
 | 
			
		||||
                activeTopic === t.key
 | 
			
		||||
                  ? 'text-cyan-300 bg-cyan-300/30 border-cyan-300/60'
 | 
			
		||||
                  : 'border-white/30 text-white/70 hover:text-white hover:border-white/40 hover:bg-white/5',
 | 
			
		||||
              )}
 | 
			
		||||
              onClick={() => setActiveTopic(t.key)}
 | 
			
		||||
            >
 | 
			
		||||
              <span>{t.display}</span>
 | 
			
		||||
            </div>
 | 
			
		||||
          ))}
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        {loading ? (
 | 
			
		||||
          <div className="flex flex-row items-center justify-center min-h-screen">
 | 
			
		||||
            <svg
 | 
			
		||||
              aria-hidden="true"
 | 
			
		||||
@@ -66,17 +120,7 @@ const Page = () => {
 | 
			
		||||
            </svg>
 | 
			
		||||
          </div>
 | 
			
		||||
        ) : (
 | 
			
		||||
    <>
 | 
			
		||||
      <div>
 | 
			
		||||
        <div className="flex flex-col pt-4">
 | 
			
		||||
          <div className="flex items-center">
 | 
			
		||||
            <Search />
 | 
			
		||||
            <h1 className="text-3xl font-medium p-2">Discover</h1>
 | 
			
		||||
          </div>
 | 
			
		||||
          <hr className="border-t border-[#2B2C2C] my-4 w-full" />
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-4 pb-28 lg:pb-8 w-full justify-items-center lg:justify-items-start">
 | 
			
		||||
          <div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-4 pb-28 pt-5 lg:pb-8 w-full justify-items-center lg:justify-items-start">
 | 
			
		||||
            {discover &&
 | 
			
		||||
              discover?.map((item, i) => (
 | 
			
		||||
                <Link
 | 
			
		||||
@@ -105,6 +149,7 @@ const Page = () => {
 | 
			
		||||
                </Link>
 | 
			
		||||
              ))}
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
      </div>
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
 
 | 
			
		||||
@@ -11,3 +11,11 @@
 | 
			
		||||
    display: none;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media screen and (-webkit-min-device-pixel-ratio: 0) {
 | 
			
		||||
  select,
 | 
			
		||||
  textarea,
 | 
			
		||||
  input {
 | 
			
		||||
    font-size: 16px !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								src/app/manifest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,54 @@
 | 
			
		||||
import type { MetadataRoute } from 'next';
 | 
			
		||||
 | 
			
		||||
export default function manifest(): MetadataRoute.Manifest {
 | 
			
		||||
  return {
 | 
			
		||||
    name: 'Perplexica - Chat with the internet',
 | 
			
		||||
    short_name: 'Perplexica',
 | 
			
		||||
    description:
 | 
			
		||||
      'Perplexica is an AI powered chatbot that is connected to the internet.',
 | 
			
		||||
    start_url: '/',
 | 
			
		||||
    display: 'standalone',
 | 
			
		||||
    background_color: '#0a0a0a',
 | 
			
		||||
    theme_color: '#0a0a0a',
 | 
			
		||||
    screenshots: [
 | 
			
		||||
      {
 | 
			
		||||
        src: '/screenshots/p1.png',
 | 
			
		||||
        form_factor: 'wide',
 | 
			
		||||
        sizes: '2560x1600',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        src: '/screenshots/p2.png',
 | 
			
		||||
        form_factor: 'wide',
 | 
			
		||||
        sizes: '2560x1600',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        src: '/screenshots/p1_small.png',
 | 
			
		||||
        form_factor: 'narrow',
 | 
			
		||||
        sizes: '828x1792',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        src: '/screenshots/p2_small.png',
 | 
			
		||||
        form_factor: 'narrow',
 | 
			
		||||
        sizes: '828x1792',
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
    icons: [
 | 
			
		||||
      {
 | 
			
		||||
        src: '/icon-50.png',
 | 
			
		||||
        sizes: '50x50',
 | 
			
		||||
        type: 'image/png' as const,
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        src: '/icon-100.png',
 | 
			
		||||
        sizes: '100x100',
 | 
			
		||||
        type: 'image/png',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        src: '/icon.png',
 | 
			
		||||
        sizes: '440x440',
 | 
			
		||||
        type: 'image/png',
 | 
			
		||||
        purpose: 'any',
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@@ -7,6 +7,7 @@ import { Switch } from '@headlessui/react';
 | 
			
		||||
import ThemeSwitcher from '@/components/theme/Switcher';
 | 
			
		||||
import { ImagesIcon, VideoIcon } from 'lucide-react';
 | 
			
		||||
import Link from 'next/link';
 | 
			
		||||
import { PROVIDER_METADATA } from '@/lib/providers';
 | 
			
		||||
 | 
			
		||||
interface SettingsType {
 | 
			
		||||
  chatModelProviders: {
 | 
			
		||||
@@ -20,7 +21,9 @@ interface SettingsType {
 | 
			
		||||
  anthropicApiKey: string;
 | 
			
		||||
  geminiApiKey: string;
 | 
			
		||||
  ollamaApiUrl: string;
 | 
			
		||||
  lmStudioApiUrl: string;
 | 
			
		||||
  deepseekApiKey: string;
 | 
			
		||||
  aimlApiKey: string;
 | 
			
		||||
  customOpenaiApiKey: string;
 | 
			
		||||
  customOpenaiApiUrl: string;
 | 
			
		||||
  customOpenaiModelName: string;
 | 
			
		||||
@@ -141,15 +144,17 @@ const Page = () => {
 | 
			
		||||
  const [selectedEmbeddingModel, setSelectedEmbeddingModel] = useState<
 | 
			
		||||
    string | null
 | 
			
		||||
  >(null);
 | 
			
		||||
  const [isLoading, setIsLoading] = useState(false);
 | 
			
		||||
  const [isLoading, setIsLoading] = useState(true);
 | 
			
		||||
  const [automaticImageSearch, setAutomaticImageSearch] = useState(false);
 | 
			
		||||
  const [automaticVideoSearch, setAutomaticVideoSearch] = useState(false);
 | 
			
		||||
  const [systemInstructions, setSystemInstructions] = useState<string>('');
 | 
			
		||||
  const [measureUnit, setMeasureUnit] = useState<'Imperial' | 'Metric'>(
 | 
			
		||||
    'Metric',
 | 
			
		||||
  );
 | 
			
		||||
  const [savingStates, setSavingStates] = useState<Record<string, boolean>>({});
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const fetchConfig = async () => {
 | 
			
		||||
      setIsLoading(true);
 | 
			
		||||
      const res = await fetch(`/api/config`, {
 | 
			
		||||
        headers: {
 | 
			
		||||
          'Content-Type': 'application/json',
 | 
			
		||||
@@ -208,6 +213,10 @@ const Page = () => {
 | 
			
		||||
 | 
			
		||||
      setSystemInstructions(localStorage.getItem('systemInstructions')!);
 | 
			
		||||
 | 
			
		||||
      setMeasureUnit(
 | 
			
		||||
        localStorage.getItem('measureUnit')! as 'Imperial' | 'Metric',
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      setIsLoading(false);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -366,6 +375,8 @@ const Page = () => {
 | 
			
		||||
        localStorage.setItem('embeddingModel', value);
 | 
			
		||||
      } else if (key === 'systemInstructions') {
 | 
			
		||||
        localStorage.setItem('systemInstructions', value);
 | 
			
		||||
      } else if (key === 'measureUnit') {
 | 
			
		||||
        localStorage.setItem('measureUnit', value.toString());
 | 
			
		||||
      }
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      console.error('Failed to save:', err);
 | 
			
		||||
@@ -414,13 +425,35 @@ const Page = () => {
 | 
			
		||||
      ) : (
 | 
			
		||||
        config && (
 | 
			
		||||
          <div className="flex flex-col space-y-6 pb-28 lg:pb-8">
 | 
			
		||||
            <SettingsSection title="Appearance">
 | 
			
		||||
            <SettingsSection title="Preferences">
 | 
			
		||||
              <div className="flex flex-col space-y-1">
 | 
			
		||||
                <p className="text-black/70 dark:text-white/70 text-sm">
 | 
			
		||||
                  Theme
 | 
			
		||||
                </p>
 | 
			
		||||
                <ThemeSwitcher />
 | 
			
		||||
              </div>
 | 
			
		||||
              <div className="flex flex-col space-y-1">
 | 
			
		||||
                <p className="text-black/70 dark:text-white/70 text-sm">
 | 
			
		||||
                  Measurement Units
 | 
			
		||||
                </p>
 | 
			
		||||
                <Select
 | 
			
		||||
                  value={measureUnit ?? undefined}
 | 
			
		||||
                  onChange={(e) => {
 | 
			
		||||
                    setMeasureUnit(e.target.value as 'Imperial' | 'Metric');
 | 
			
		||||
                    saveConfig('measureUnit', e.target.value);
 | 
			
		||||
                  }}
 | 
			
		||||
                  options={[
 | 
			
		||||
                    {
 | 
			
		||||
                      label: 'Metric',
 | 
			
		||||
                      value: 'Metric',
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                      label: 'Imperial',
 | 
			
		||||
                      value: 'Imperial',
 | 
			
		||||
                    },
 | 
			
		||||
                  ]}
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
            </SettingsSection>
 | 
			
		||||
 | 
			
		||||
            <SettingsSection title="Automatic Search">
 | 
			
		||||
@@ -514,7 +547,7 @@ const Page = () => {
 | 
			
		||||
            <SettingsSection title="System Instructions">
 | 
			
		||||
              <div className="flex flex-col space-y-4">
 | 
			
		||||
                <Textarea
 | 
			
		||||
                  value={systemInstructions}
 | 
			
		||||
                  value={systemInstructions ?? undefined}
 | 
			
		||||
                  isSaving={savingStates['systemInstructions']}
 | 
			
		||||
                  onChange={(e) => {
 | 
			
		||||
                    setSystemInstructions(e.target.value);
 | 
			
		||||
@@ -548,6 +581,7 @@ const Page = () => {
 | 
			
		||||
                        (provider) => ({
 | 
			
		||||
                          value: provider,
 | 
			
		||||
                          label:
 | 
			
		||||
                            (PROVIDER_METADATA as any)[provider]?.displayName ||
 | 
			
		||||
                            provider.charAt(0).toUpperCase() +
 | 
			
		||||
                              provider.slice(1),
 | 
			
		||||
                        }),
 | 
			
		||||
@@ -690,6 +724,7 @@ const Page = () => {
 | 
			
		||||
                        (provider) => ({
 | 
			
		||||
                          value: provider,
 | 
			
		||||
                          label:
 | 
			
		||||
                            (PROVIDER_METADATA as any)[provider]?.displayName ||
 | 
			
		||||
                            provider.charAt(0).toUpperCase() +
 | 
			
		||||
                              provider.slice(1),
 | 
			
		||||
                        }),
 | 
			
		||||
@@ -858,6 +893,44 @@ const Page = () => {
 | 
			
		||||
                    onSave={(value) => saveConfig('deepseekApiKey', value)}
 | 
			
		||||
                  />
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div className="flex flex-col space-y-1">
 | 
			
		||||
                  <p className="text-black/70 dark:text-white/70 text-sm">
 | 
			
		||||
                    AI/ML API Key
 | 
			
		||||
                  </p>
 | 
			
		||||
                  <Input
 | 
			
		||||
                    type="text"
 | 
			
		||||
                    placeholder="AI/ML API Key"
 | 
			
		||||
                    value={config.aimlApiKey}
 | 
			
		||||
                    isSaving={savingStates['aimlApiKey']}
 | 
			
		||||
                    onChange={(e) => {
 | 
			
		||||
                      setConfig((prev) => ({
 | 
			
		||||
                        ...prev!,
 | 
			
		||||
                        aimlApiKey: e.target.value,
 | 
			
		||||
                      }));
 | 
			
		||||
                    }}
 | 
			
		||||
                    onSave={(value) => saveConfig('aimlApiKey', value)}
 | 
			
		||||
                  />
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div className="flex flex-col space-y-1">
 | 
			
		||||
                  <p className="text-black/70 dark:text-white/70 text-sm">
 | 
			
		||||
                    LM Studio API URL
 | 
			
		||||
                  </p>
 | 
			
		||||
                  <Input
 | 
			
		||||
                    type="text"
 | 
			
		||||
                    placeholder="LM Studio API URL"
 | 
			
		||||
                    value={config.lmStudioApiUrl}
 | 
			
		||||
                    isSaving={savingStates['lmStudioApiUrl']}
 | 
			
		||||
                    onChange={(e) => {
 | 
			
		||||
                      setConfig((prev) => ({
 | 
			
		||||
                        ...prev!,
 | 
			
		||||
                        lmStudioApiUrl: e.target.value,
 | 
			
		||||
                      }));
 | 
			
		||||
                    }}
 | 
			
		||||
                    onSave={(value) => saveConfig('lmStudioApiUrl', value)}
 | 
			
		||||
                  />
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </SettingsSection>
 | 
			
		||||
          </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -82,14 +82,29 @@ const checkConfig = async (
 | 
			
		||||
    ) {
 | 
			
		||||
      if (!chatModel || !chatModelProvider) {
 | 
			
		||||
        const chatModelProviders = providers.chatModelProviders;
 | 
			
		||||
        const chatModelProvidersKeys = Object.keys(chatModelProviders);
 | 
			
		||||
 | 
			
		||||
        if (!chatModelProviders || chatModelProvidersKeys.length === 0) {
 | 
			
		||||
          return toast.error('No chat models available');
 | 
			
		||||
        } else {
 | 
			
		||||
          chatModelProvider =
 | 
			
		||||
          chatModelProvider || Object.keys(chatModelProviders)[0];
 | 
			
		||||
            chatModelProvidersKeys.find(
 | 
			
		||||
              (provider) =>
 | 
			
		||||
                Object.keys(chatModelProviders[provider]).length > 0,
 | 
			
		||||
            ) || chatModelProvidersKeys[0];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (
 | 
			
		||||
          chatModelProvider === 'custom_openai' &&
 | 
			
		||||
          Object.keys(chatModelProviders[chatModelProvider]).length === 0
 | 
			
		||||
        ) {
 | 
			
		||||
          toast.error(
 | 
			
		||||
            "Looks like you haven't configured any chat model providers. Please configure them from the settings page or the config file.",
 | 
			
		||||
          );
 | 
			
		||||
          return setHasError(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        chatModel = Object.keys(chatModelProviders[chatModelProvider])[0];
 | 
			
		||||
 | 
			
		||||
        if (!chatModelProviders || Object.keys(chatModelProviders).length === 0)
 | 
			
		||||
          return toast.error('No chat models available');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!embeddingModel || !embeddingModelProvider) {
 | 
			
		||||
@@ -117,7 +132,8 @@ const checkConfig = async (
 | 
			
		||||
 | 
			
		||||
      if (
 | 
			
		||||
        Object.keys(chatModelProviders).length > 0 &&
 | 
			
		||||
        !chatModelProviders[chatModelProvider]
 | 
			
		||||
        (!chatModelProviders[chatModelProvider] ||
 | 
			
		||||
          Object.keys(chatModelProviders[chatModelProvider]).length === 0)
 | 
			
		||||
      ) {
 | 
			
		||||
        const chatModelProvidersKeys = Object.keys(chatModelProviders);
 | 
			
		||||
        chatModelProvider =
 | 
			
		||||
@@ -132,6 +148,16 @@ const checkConfig = async (
 | 
			
		||||
        chatModelProvider &&
 | 
			
		||||
        !chatModelProviders[chatModelProvider][chatModel]
 | 
			
		||||
      ) {
 | 
			
		||||
        if (
 | 
			
		||||
          chatModelProvider === 'custom_openai' &&
 | 
			
		||||
          Object.keys(chatModelProviders[chatModelProvider]).length === 0
 | 
			
		||||
        ) {
 | 
			
		||||
          toast.error(
 | 
			
		||||
            "Looks like you haven't configured any chat model providers. Please configure them from the settings page or the config file.",
 | 
			
		||||
          );
 | 
			
		||||
          return setHasError(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        chatModel = Object.keys(
 | 
			
		||||
          chatModelProviders[
 | 
			
		||||
            Object.keys(chatModelProviders[chatModelProvider]).length > 0
 | 
			
		||||
@@ -139,6 +165,7 @@ const checkConfig = async (
 | 
			
		||||
              : Object.keys(chatModelProviders)[0]
 | 
			
		||||
          ],
 | 
			
		||||
        )[0];
 | 
			
		||||
 | 
			
		||||
        localStorage.setItem('chatModel', chatModel);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@@ -327,7 +354,11 @@ const ChatWindow = ({ id }: { id?: string }) => {
 | 
			
		||||
    }
 | 
			
		||||
  }, [isMessagesLoaded, isConfigReady]);
 | 
			
		||||
 | 
			
		||||
  const sendMessage = async (message: string, messageId?: string) => {
 | 
			
		||||
  const sendMessage = async (
 | 
			
		||||
    message: string,
 | 
			
		||||
    messageId?: string,
 | 
			
		||||
    rewrite = false,
 | 
			
		||||
  ) => {
 | 
			
		||||
    if (loading) return;
 | 
			
		||||
    if (!isConfigReady) {
 | 
			
		||||
      toast.error('Cannot send message before the configuration is ready');
 | 
			
		||||
@@ -376,8 +407,18 @@ const ChatWindow = ({ id }: { id?: string }) => {
 | 
			
		||||
            },
 | 
			
		||||
          ]);
 | 
			
		||||
          added = true;
 | 
			
		||||
        }
 | 
			
		||||
          setMessageAppeared(true);
 | 
			
		||||
        } else {
 | 
			
		||||
          setMessages((prev) =>
 | 
			
		||||
            prev.map((message) => {
 | 
			
		||||
              if (message.messageId === data.messageId) {
 | 
			
		||||
                return { ...message, sources: sources };
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              return message;
 | 
			
		||||
            }),
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (data.type === 'message') {
 | 
			
		||||
@@ -394,8 +435,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
 | 
			
		||||
            },
 | 
			
		||||
          ]);
 | 
			
		||||
          added = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
          setMessages((prev) =>
 | 
			
		||||
            prev.map((message) => {
 | 
			
		||||
              if (message.messageId === data.messageId) {
 | 
			
		||||
@@ -409,6 +449,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
 | 
			
		||||
          recievedMessage += data.data;
 | 
			
		||||
          setMessageAppeared(true);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (data.type === 'messageEnd') {
 | 
			
		||||
        setChatHistory((prevHistory) => [
 | 
			
		||||
@@ -455,6 +496,8 @@ const ChatWindow = ({ id }: { id?: string }) => {
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const messageIndex = messages.findIndex((m) => m.messageId === messageId);
 | 
			
		||||
 | 
			
		||||
    const res = await fetch('/api/chat', {
 | 
			
		||||
      method: 'POST',
 | 
			
		||||
      headers: {
 | 
			
		||||
@@ -471,7 +514,9 @@ const ChatWindow = ({ id }: { id?: string }) => {
 | 
			
		||||
        files: fileIds,
 | 
			
		||||
        focusMode: focusMode,
 | 
			
		||||
        optimizationMode: optimizationMode,
 | 
			
		||||
        history: chatHistory,
 | 
			
		||||
        history: rewrite
 | 
			
		||||
          ? chatHistory.slice(0, messageIndex === -1 ? undefined : messageIndex)
 | 
			
		||||
          : chatHistory,
 | 
			
		||||
        chatModel: {
 | 
			
		||||
          name: chatModelProvider.name,
 | 
			
		||||
          provider: chatModelProvider.provider,
 | 
			
		||||
@@ -525,7 +570,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
 | 
			
		||||
      return [...prev.slice(0, messages.length > 2 ? index - 1 : 0)];
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    sendMessage(message.content, message.messageId);
 | 
			
		||||
    sendMessage(message.content, message.messageId, true);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
import { Settings } from 'lucide-react';
 | 
			
		||||
import EmptyChatMessageInput from './EmptyChatMessageInput';
 | 
			
		||||
import { useState } from 'react';
 | 
			
		||||
import { File } from './ChatWindow';
 | 
			
		||||
import Link from 'next/link';
 | 
			
		||||
import WeatherWidget from './WeatherWidget';
 | 
			
		||||
import NewsArticleWidget from './NewsArticleWidget';
 | 
			
		||||
 | 
			
		||||
const EmptyChat = ({
 | 
			
		||||
  sendMessage,
 | 
			
		||||
@@ -25,8 +26,6 @@ const EmptyChat = ({
 | 
			
		||||
  files: File[];
 | 
			
		||||
  setFiles: (files: File[]) => void;
 | 
			
		||||
}) => {
 | 
			
		||||
  const [isSettingsOpen, setIsSettingsOpen] = useState(false);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="relative">
 | 
			
		||||
      <div className="absolute w-full flex flex-row items-center justify-end mr-5 mt-5">
 | 
			
		||||
@@ -34,7 +33,8 @@ const EmptyChat = ({
 | 
			
		||||
          <Settings className="cursor-pointer lg:hidden" />
 | 
			
		||||
        </Link>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div className="flex flex-col items-center justify-center min-h-screen max-w-screen-sm mx-auto p-2 space-y-8">
 | 
			
		||||
      <div className="flex flex-col items-center justify-center min-h-screen max-w-screen-sm mx-auto p-2 space-y-4">
 | 
			
		||||
        <div className="flex flex-col items-center justify-center w-full space-y-8">
 | 
			
		||||
          <h2 className="text-black/70 dark:text-white/70 text-3xl font-medium -mt-8">
 | 
			
		||||
            Research begins here.
 | 
			
		||||
          </h2>
 | 
			
		||||
@@ -50,6 +50,15 @@ const EmptyChat = ({
 | 
			
		||||
            setFiles={setFiles}
 | 
			
		||||
          />
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="flex flex-col w-full gap-4 mt-2 sm:flex-row sm:justify-center">
 | 
			
		||||
          <div className="flex-1 w-full">
 | 
			
		||||
            <WeatherWidget />
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className="flex-1 w-full">
 | 
			
		||||
            <NewsArticleWidget />
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -20,9 +20,19 @@ import SearchImages from './SearchImages';
 | 
			
		||||
import SearchVideos from './SearchVideos';
 | 
			
		||||
import { useSpeech } from 'react-text-to-speech';
 | 
			
		||||
import ThinkBox from './ThinkBox';
 | 
			
		||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
 | 
			
		||||
import { SyntaxHighlightedCode } from './SyntaxHighlightedCode';
 | 
			
		||||
 | 
			
		||||
const ThinkTagProcessor = ({ children }: { children: React.ReactNode }) => {
 | 
			
		||||
  return <ThinkBox content={children as string} />;
 | 
			
		||||
const ThinkTagProcessor = ({
 | 
			
		||||
  children,
 | 
			
		||||
  thinkingEnded,
 | 
			
		||||
}: {
 | 
			
		||||
  children: React.ReactNode;
 | 
			
		||||
  thinkingEnded: boolean;
 | 
			
		||||
}) => {
 | 
			
		||||
  return (
 | 
			
		||||
    <ThinkBox content={children as string} thinkingEnded={thinkingEnded} />
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const MessageBox = ({
 | 
			
		||||
@@ -46,6 +56,7 @@ const MessageBox = ({
 | 
			
		||||
}) => {
 | 
			
		||||
  const [parsedMessage, setParsedMessage] = useState(message.content);
 | 
			
		||||
  const [speechMessage, setSpeechMessage] = useState(message.content);
 | 
			
		||||
  const [thinkingEnded, setThinkingEnded] = useState(false);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const citationRegex = /\[([^\]]+)\]/g;
 | 
			
		||||
@@ -61,6 +72,10 @@ const MessageBox = ({
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (message.role === 'assistant' && message.content.includes('</think>')) {
 | 
			
		||||
      setThinkingEnded(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
      message.role === 'assistant' &&
 | 
			
		||||
      message?.sources &&
 | 
			
		||||
@@ -88,7 +103,7 @@ const MessageBox = ({
 | 
			
		||||
                if (url) {
 | 
			
		||||
                  return `<a href="${url}" target="_blank" className="bg-light-secondary dark:bg-dark-secondary px-1 rounded ml-1 no-underline text-xs text-black/70 dark:text-white/70 relative">${numStr}</a>`;
 | 
			
		||||
                } else {
 | 
			
		||||
                  return `[${numStr}]`;
 | 
			
		||||
                  return ``;
 | 
			
		||||
                }
 | 
			
		||||
              })
 | 
			
		||||
              .join('');
 | 
			
		||||
@@ -97,6 +112,15 @@ const MessageBox = ({
 | 
			
		||||
          },
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
      setSpeechMessage(message.content.replace(regex, ''));
 | 
			
		||||
      return;
 | 
			
		||||
    } else if (
 | 
			
		||||
      message.role === 'assistant' &&
 | 
			
		||||
      message?.sources &&
 | 
			
		||||
      message.sources.length === 0
 | 
			
		||||
    ) {
 | 
			
		||||
      setParsedMessage(processedMessage.replace(regex, ''));
 | 
			
		||||
      setSpeechMessage(message.content.replace(regex, ''));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -110,6 +134,12 @@ const MessageBox = ({
 | 
			
		||||
    overrides: {
 | 
			
		||||
      think: {
 | 
			
		||||
        component: ThinkTagProcessor,
 | 
			
		||||
        props: {
 | 
			
		||||
          thinkingEnded: thinkingEnded,
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      code: {
 | 
			
		||||
        component: SyntaxHighlightedCode,
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,122 @@
 | 
			
		||||
import { Clock, Edit, Share, Trash } from 'lucide-react';
 | 
			
		||||
import { Clock, Edit, Share, Trash, FileText, FileDown } from 'lucide-react';
 | 
			
		||||
import { Message } from './ChatWindow';
 | 
			
		||||
import { useEffect, useState } from 'react';
 | 
			
		||||
import { useEffect, useState, Fragment } from 'react';
 | 
			
		||||
import { formatTimeDifference } from '@/lib/utils';
 | 
			
		||||
import DeleteChat from './DeleteChat';
 | 
			
		||||
import {
 | 
			
		||||
  Popover,
 | 
			
		||||
  PopoverButton,
 | 
			
		||||
  PopoverPanel,
 | 
			
		||||
  Transition,
 | 
			
		||||
} from '@headlessui/react';
 | 
			
		||||
import jsPDF from 'jspdf';
 | 
			
		||||
 | 
			
		||||
const downloadFile = (filename: string, content: string, type: string) => {
 | 
			
		||||
  const blob = new Blob([content], { type });
 | 
			
		||||
  const url = URL.createObjectURL(blob);
 | 
			
		||||
  const a = document.createElement('a');
 | 
			
		||||
  a.href = url;
 | 
			
		||||
  a.download = filename;
 | 
			
		||||
  document.body.appendChild(a);
 | 
			
		||||
  a.click();
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    document.body.removeChild(a);
 | 
			
		||||
    URL.revokeObjectURL(url);
 | 
			
		||||
  }, 0);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const exportAsMarkdown = (messages: Message[], title: string) => {
 | 
			
		||||
  const date = new Date(messages[0]?.createdAt || Date.now()).toLocaleString();
 | 
			
		||||
  let md = `# 💬 Chat Export: ${title}\n\n`;
 | 
			
		||||
  md += `*Exported on: ${date}*\n\n---\n`;
 | 
			
		||||
  messages.forEach((msg, idx) => {
 | 
			
		||||
    md += `\n---\n`;
 | 
			
		||||
    md += `**${msg.role === 'user' ? '🧑 User' : '🤖 Assistant'}**  
 | 
			
		||||
`;
 | 
			
		||||
    md += `*${new Date(msg.createdAt).toLocaleString()}*\n\n`;
 | 
			
		||||
    md += `> ${msg.content.replace(/\n/g, '\n> ')}\n`;
 | 
			
		||||
    if (msg.sources && msg.sources.length > 0) {
 | 
			
		||||
      md += `\n**Citations:**\n`;
 | 
			
		||||
      msg.sources.forEach((src: any, i: number) => {
 | 
			
		||||
        const url = src.metadata?.url || '';
 | 
			
		||||
        md += `- [${i + 1}] [${url}](${url})\n`;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  md += '\n---\n';
 | 
			
		||||
  downloadFile(`${title || 'chat'}.md`, md, 'text/markdown');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const exportAsPDF = (messages: Message[], title: string) => {
 | 
			
		||||
  const doc = new jsPDF();
 | 
			
		||||
  const date = new Date(messages[0]?.createdAt || Date.now()).toLocaleString();
 | 
			
		||||
  let y = 15;
 | 
			
		||||
  const pageHeight = doc.internal.pageSize.height;
 | 
			
		||||
  doc.setFontSize(18);
 | 
			
		||||
  doc.text(`Chat Export: ${title}`, 10, y);
 | 
			
		||||
  y += 8;
 | 
			
		||||
  doc.setFontSize(11);
 | 
			
		||||
  doc.setTextColor(100);
 | 
			
		||||
  doc.text(`Exported on: ${date}`, 10, y);
 | 
			
		||||
  y += 8;
 | 
			
		||||
  doc.setDrawColor(200);
 | 
			
		||||
  doc.line(10, y, 200, y);
 | 
			
		||||
  y += 6;
 | 
			
		||||
  doc.setTextColor(30);
 | 
			
		||||
  messages.forEach((msg, idx) => {
 | 
			
		||||
    if (y > pageHeight - 30) {
 | 
			
		||||
      doc.addPage();
 | 
			
		||||
      y = 15;
 | 
			
		||||
    }
 | 
			
		||||
    doc.setFont('helvetica', 'bold');
 | 
			
		||||
    doc.text(`${msg.role === 'user' ? 'User' : 'Assistant'}`, 10, y);
 | 
			
		||||
    doc.setFont('helvetica', 'normal');
 | 
			
		||||
    doc.setFontSize(10);
 | 
			
		||||
    doc.setTextColor(120);
 | 
			
		||||
    doc.text(`${new Date(msg.createdAt).toLocaleString()}`, 40, y);
 | 
			
		||||
    y += 6;
 | 
			
		||||
    doc.setTextColor(30);
 | 
			
		||||
    doc.setFontSize(12);
 | 
			
		||||
    const lines = doc.splitTextToSize(msg.content, 180);
 | 
			
		||||
    for (let i = 0; i < lines.length; i++) {
 | 
			
		||||
      if (y > pageHeight - 20) {
 | 
			
		||||
        doc.addPage();
 | 
			
		||||
        y = 15;
 | 
			
		||||
      }
 | 
			
		||||
      doc.text(lines[i], 12, y);
 | 
			
		||||
      y += 6;
 | 
			
		||||
    }
 | 
			
		||||
    if (msg.sources && msg.sources.length > 0) {
 | 
			
		||||
      doc.setFontSize(11);
 | 
			
		||||
      doc.setTextColor(80);
 | 
			
		||||
      if (y > pageHeight - 20) {
 | 
			
		||||
        doc.addPage();
 | 
			
		||||
        y = 15;
 | 
			
		||||
      }
 | 
			
		||||
      doc.text('Citations:', 12, y);
 | 
			
		||||
      y += 5;
 | 
			
		||||
      msg.sources.forEach((src: any, i: number) => {
 | 
			
		||||
        const url = src.metadata?.url || '';
 | 
			
		||||
        if (y > pageHeight - 15) {
 | 
			
		||||
          doc.addPage();
 | 
			
		||||
          y = 15;
 | 
			
		||||
        }
 | 
			
		||||
        doc.text(`- [${i + 1}] ${url}`, 15, y);
 | 
			
		||||
        y += 5;
 | 
			
		||||
      });
 | 
			
		||||
      doc.setTextColor(30);
 | 
			
		||||
    }
 | 
			
		||||
    y += 6;
 | 
			
		||||
    doc.setDrawColor(230);
 | 
			
		||||
    if (y > pageHeight - 10) {
 | 
			
		||||
      doc.addPage();
 | 
			
		||||
      y = 15;
 | 
			
		||||
    }
 | 
			
		||||
    doc.line(10, y, 200, y);
 | 
			
		||||
    y += 4;
 | 
			
		||||
  });
 | 
			
		||||
  doc.save(`${title || 'chat'}.pdf`);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const Navbar = ({
 | 
			
		||||
  chatId,
 | 
			
		||||
@@ -59,10 +173,39 @@ const Navbar = ({
 | 
			
		||||
      <p className="hidden lg:flex">{title}</p>
 | 
			
		||||
 | 
			
		||||
      <div className="flex flex-row items-center space-x-4">
 | 
			
		||||
        <Share
 | 
			
		||||
          size={17}
 | 
			
		||||
          className="active:scale-95 transition duration-100 cursor-pointer"
 | 
			
		||||
        />
 | 
			
		||||
        <Popover className="relative">
 | 
			
		||||
          <PopoverButton className="active:scale-95 transition duration-100 cursor-pointer p-2 rounded-full hover:bg-light-secondary dark:hover:bg-dark-secondary">
 | 
			
		||||
            <Share size={17} />
 | 
			
		||||
          </PopoverButton>
 | 
			
		||||
          <Transition
 | 
			
		||||
            as={Fragment}
 | 
			
		||||
            enter="transition ease-out duration-100"
 | 
			
		||||
            enterFrom="opacity-0 translate-y-1"
 | 
			
		||||
            enterTo="opacity-100 translate-y-0"
 | 
			
		||||
            leave="transition ease-in duration-75"
 | 
			
		||||
            leaveFrom="opacity-100 translate-y-0"
 | 
			
		||||
            leaveTo="opacity-0 translate-y-1"
 | 
			
		||||
          >
 | 
			
		||||
            <PopoverPanel className="absolute right-0 mt-2 w-64 rounded-xl shadow-xl bg-light-primary dark:bg-dark-primary border border-light-200 dark:border-dark-200 z-50">
 | 
			
		||||
              <div className="flex flex-col py-3 px-3 gap-2">
 | 
			
		||||
                <button
 | 
			
		||||
                  className="flex items-center gap-2 px-4 py-2 text-left hover:bg-light-secondary dark:hover:bg-dark-secondary transition-colors text-black dark:text-white rounded-lg font-medium"
 | 
			
		||||
                  onClick={() => exportAsMarkdown(messages, title || '')}
 | 
			
		||||
                >
 | 
			
		||||
                  <FileText size={17} className="text-[#24A0ED]" />
 | 
			
		||||
                  Export as Markdown
 | 
			
		||||
                </button>
 | 
			
		||||
                <button
 | 
			
		||||
                  className="flex items-center gap-2 px-4 py-2 text-left hover:bg-light-secondary dark:hover:bg-dark-secondary transition-colors text-black dark:text-white rounded-lg font-medium"
 | 
			
		||||
                  onClick={() => exportAsPDF(messages, title || '')}
 | 
			
		||||
                >
 | 
			
		||||
                  <FileDown size={17} className="text-[#24A0ED]" />
 | 
			
		||||
                  Export as PDF
 | 
			
		||||
                </button>
 | 
			
		||||
              </div>
 | 
			
		||||
            </PopoverPanel>
 | 
			
		||||
          </Transition>
 | 
			
		||||
        </Popover>
 | 
			
		||||
        <DeleteChat redirect chatId={chatId} chats={[]} setChats={() => {}} />
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										71
									
								
								src/components/NewsArticleWidget.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,71 @@
 | 
			
		||||
import { useEffect, useState } from 'react';
 | 
			
		||||
 | 
			
		||||
interface Article {
 | 
			
		||||
  title: string;
 | 
			
		||||
  content: string;
 | 
			
		||||
  url: string;
 | 
			
		||||
  thumbnail: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const NewsArticleWidget = () => {
 | 
			
		||||
  const [article, setArticle] = useState<Article | null>(null);
 | 
			
		||||
  const [loading, setLoading] = useState(true);
 | 
			
		||||
  const [error, setError] = useState(false);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    fetch('/api/discover?mode=preview')
 | 
			
		||||
      .then((res) => res.json())
 | 
			
		||||
      .then((data) => {
 | 
			
		||||
        const articles = (data.blogs || []).filter((a: Article) => a.thumbnail);
 | 
			
		||||
        setArticle(articles[Math.floor(Math.random() * articles.length)]);
 | 
			
		||||
        setLoading(false);
 | 
			
		||||
      })
 | 
			
		||||
      .catch(() => {
 | 
			
		||||
        setError(true);
 | 
			
		||||
        setLoading(false);
 | 
			
		||||
      });
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="bg-light-secondary dark:bg-dark-secondary rounded-xl border border-light-200 dark:border-dark-200 shadow-sm flex flex-row items-center w-full h-24 min-h-[96px] max-h-[96px] px-3 py-2 gap-3 overflow-hidden">
 | 
			
		||||
      {loading ? (
 | 
			
		||||
        <>
 | 
			
		||||
          <div className="animate-pulse flex flex-row items-center w-full h-full">
 | 
			
		||||
            <div className="rounded-lg w-16 min-w-16 max-w-16 h-16 min-h-16 max-h-16 bg-light-200 dark:bg-dark-200 mr-3" />
 | 
			
		||||
            <div className="flex flex-col justify-center flex-1 h-full w-0 gap-2">
 | 
			
		||||
              <div className="h-4 w-3/4 rounded bg-light-200 dark:bg-dark-200" />
 | 
			
		||||
              <div className="h-3 w-1/2 rounded bg-light-200 dark:bg-dark-200" />
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </>
 | 
			
		||||
      ) : error ? (
 | 
			
		||||
        <div className="w-full text-xs text-red-400">Could not load news.</div>
 | 
			
		||||
      ) : article ? (
 | 
			
		||||
        <a
 | 
			
		||||
          href={`/?q=Summary: ${article.url}`}
 | 
			
		||||
          className="flex flex-row items-center w-full h-full group"
 | 
			
		||||
        >
 | 
			
		||||
          <img
 | 
			
		||||
            className="object-cover rounded-lg w-16 min-w-16 max-w-16 h-16 min-h-16 max-h-16 border border-light-200 dark:border-dark-200 bg-light-200 dark:bg-dark-200 group-hover:opacity-90 transition"
 | 
			
		||||
            src={
 | 
			
		||||
              new URL(article.thumbnail).origin +
 | 
			
		||||
              new URL(article.thumbnail).pathname +
 | 
			
		||||
              `?id=${new URL(article.thumbnail).searchParams.get('id')}`
 | 
			
		||||
            }
 | 
			
		||||
            alt={article.title}
 | 
			
		||||
          />
 | 
			
		||||
          <div className="flex flex-col justify-center flex-1 h-full pl-3 w-0">
 | 
			
		||||
            <div className="font-bold text-xs text-black dark:text-white leading-tight truncate overflow-hidden whitespace-nowrap">
 | 
			
		||||
              {article.title}
 | 
			
		||||
            </div>
 | 
			
		||||
            <p className="text-black/70 dark:text-white/70 text-xs leading-snug truncate overflow-hidden whitespace-nowrap">
 | 
			
		||||
              {article.content}
 | 
			
		||||
            </p>
 | 
			
		||||
          </div>
 | 
			
		||||
        </a>
 | 
			
		||||
      ) : null}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default NewsArticleWidget;
 | 
			
		||||
							
								
								
									
										30
									
								
								src/components/SyntaxHighlightedCode.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,30 @@
 | 
			
		||||
import React, { HTMLProps } from 'react';
 | 
			
		||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
 | 
			
		||||
import {
 | 
			
		||||
  coldarkDark,
 | 
			
		||||
  coldarkCold,
 | 
			
		||||
} from 'react-syntax-highlighter/dist/esm/styles/prism';
 | 
			
		||||
 | 
			
		||||
export const SyntaxHighlightedCode = (props: HTMLProps<HTMLDivElement>) => {
 | 
			
		||||
  const isDarkTheme = document.documentElement.classList.contains('dark');
 | 
			
		||||
  const language = props.className?.match(/lang-([a-zA-Z0-9_-]+)/)![1];
 | 
			
		||||
 | 
			
		||||
  return language ? (
 | 
			
		||||
    <div className="not-prose">
 | 
			
		||||
      <SyntaxHighlighter
 | 
			
		||||
        customStyle={{
 | 
			
		||||
          margin: 0,
 | 
			
		||||
          backgroundColor: isDarkTheme ? '#111111' : '#f3f3ee',
 | 
			
		||||
        }}
 | 
			
		||||
        language={language}
 | 
			
		||||
        style={isDarkTheme ? coldarkDark : coldarkCold}
 | 
			
		||||
      >
 | 
			
		||||
        {props.children as string}
 | 
			
		||||
      </SyntaxHighlighter>
 | 
			
		||||
    </div>
 | 
			
		||||
  ) : (
 | 
			
		||||
    <code className="inline bg-light-100 dark:bg-dark-100 px-2 py-1 rounded-lg text-sm not-prose">
 | 
			
		||||
      {props.children}
 | 
			
		||||
    </code>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
@@ -1,15 +1,23 @@
 | 
			
		||||
'use client';
 | 
			
		||||
 | 
			
		||||
import { useState } from 'react';
 | 
			
		||||
import { cn } from '@/lib/utils';
 | 
			
		||||
import { useEffect, useState } from 'react';
 | 
			
		||||
import { ChevronDown, ChevronUp, BrainCircuit } from 'lucide-react';
 | 
			
		||||
 | 
			
		||||
interface ThinkBoxProps {
 | 
			
		||||
  content: string;
 | 
			
		||||
  thinkingEnded: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ThinkBox = ({ content }: ThinkBoxProps) => {
 | 
			
		||||
  const [isExpanded, setIsExpanded] = useState(false);
 | 
			
		||||
const ThinkBox = ({ content, thinkingEnded }: ThinkBoxProps) => {
 | 
			
		||||
  const [isExpanded, setIsExpanded] = useState(true);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (thinkingEnded) {
 | 
			
		||||
      setIsExpanded(false);
 | 
			
		||||
    } else {
 | 
			
		||||
      setIsExpanded(true);
 | 
			
		||||
    }
 | 
			
		||||
  }, [thinkingEnded]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="my-4 bg-light-secondary/50 dark:bg-dark-secondary/50 rounded-xl border border-light-200 dark:border-dark-200 overflow-hidden">
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										161
									
								
								src/components/WeatherWidget.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,161 @@
 | 
			
		||||
import { Cloud, Sun, CloudRain, CloudSnow, Wind } from 'lucide-react';
 | 
			
		||||
import { useEffect, useState } from 'react';
 | 
			
		||||
 | 
			
		||||
const WeatherWidget = () => {
 | 
			
		||||
  const [data, setData] = useState({
 | 
			
		||||
    temperature: 0,
 | 
			
		||||
    condition: '',
 | 
			
		||||
    location: '',
 | 
			
		||||
    humidity: 0,
 | 
			
		||||
    windSpeed: 0,
 | 
			
		||||
    icon: '',
 | 
			
		||||
    temperatureUnit: 'C',
 | 
			
		||||
    windSpeedUnit: 'm/s',
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const [loading, setLoading] = useState(true);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const getApproxLocation = async () => {
 | 
			
		||||
      const res = await fetch('https://ipwhois.app/json/');
 | 
			
		||||
      const data = await res.json();
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        latitude: data.latitude,
 | 
			
		||||
        longitude: data.longitude,
 | 
			
		||||
        city: data.city,
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const getLocation = async (
 | 
			
		||||
      callback: (location: {
 | 
			
		||||
        latitude: number;
 | 
			
		||||
        longitude: number;
 | 
			
		||||
        city: string;
 | 
			
		||||
      }) => void,
 | 
			
		||||
    ) => {
 | 
			
		||||
      if (navigator.geolocation) {
 | 
			
		||||
        const result = await navigator.permissions.query({
 | 
			
		||||
          name: 'geolocation',
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (result.state === 'granted') {
 | 
			
		||||
          navigator.geolocation.getCurrentPosition(async (position) => {
 | 
			
		||||
            const res = await fetch(
 | 
			
		||||
              `https://api-bdc.io/data/reverse-geocode-client?latitude=${position.coords.latitude}&longitude=${position.coords.longitude}&localityLanguage=en`,
 | 
			
		||||
              {
 | 
			
		||||
                method: 'GET',
 | 
			
		||||
                headers: {
 | 
			
		||||
                  'Content-Type': 'application/json',
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const data = await res.json();
 | 
			
		||||
 | 
			
		||||
            callback({
 | 
			
		||||
              latitude: position.coords.latitude,
 | 
			
		||||
              longitude: position.coords.longitude,
 | 
			
		||||
              city: data.locality,
 | 
			
		||||
            });
 | 
			
		||||
          });
 | 
			
		||||
        } else if (result.state === 'prompt') {
 | 
			
		||||
          callback(await getApproxLocation());
 | 
			
		||||
          navigator.geolocation.getCurrentPosition((position) => {});
 | 
			
		||||
        } else if (result.state === 'denied') {
 | 
			
		||||
          callback(await getApproxLocation());
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        callback(await getApproxLocation());
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    getLocation(async (location) => {
 | 
			
		||||
      const res = await fetch(`/api/weather`, {
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        body: JSON.stringify({
 | 
			
		||||
          lat: location.latitude,
 | 
			
		||||
          lng: location.longitude,
 | 
			
		||||
          measureUnit: localStorage.getItem('measureUnit') ?? 'Metric',
 | 
			
		||||
        }),
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      const data = await res.json();
 | 
			
		||||
 | 
			
		||||
      if (res.status !== 200) {
 | 
			
		||||
        console.error('Error fetching weather data');
 | 
			
		||||
        setLoading(false);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      setData({
 | 
			
		||||
        temperature: data.temperature,
 | 
			
		||||
        condition: data.condition,
 | 
			
		||||
        location: location.city,
 | 
			
		||||
        humidity: data.humidity,
 | 
			
		||||
        windSpeed: data.windSpeed,
 | 
			
		||||
        icon: data.icon,
 | 
			
		||||
        temperatureUnit: data.temperatureUnit,
 | 
			
		||||
        windSpeedUnit: data.windSpeedUnit,
 | 
			
		||||
      });
 | 
			
		||||
      setLoading(false);
 | 
			
		||||
    });
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="bg-light-secondary dark:bg-dark-secondary rounded-xl border border-light-200 dark:border-dark-200 shadow-sm flex flex-row items-center w-full h-24 min-h-[96px] max-h-[96px] px-3 py-2 gap-3">
 | 
			
		||||
      {loading ? (
 | 
			
		||||
        <>
 | 
			
		||||
          <div className="flex flex-col items-center justify-center w-16 min-w-16 max-w-16 h-full animate-pulse">
 | 
			
		||||
            <div className="h-10 w-10 rounded-full bg-light-200 dark:bg-dark-200 mb-2" />
 | 
			
		||||
            <div className="h-4 w-10 rounded bg-light-200 dark:bg-dark-200" />
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className="flex flex-col justify-between flex-1 h-full py-1 animate-pulse">
 | 
			
		||||
            <div className="flex flex-row items-center justify-between">
 | 
			
		||||
              <div className="h-3 w-20 rounded bg-light-200 dark:bg-dark-200" />
 | 
			
		||||
              <div className="h-3 w-12 rounded bg-light-200 dark:bg-dark-200" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className="h-3 w-16 rounded bg-light-200 dark:bg-dark-200 mt-1" />
 | 
			
		||||
            <div className="flex flex-row justify-between w-full mt-auto pt-1 border-t border-light-200 dark:border-dark-200">
 | 
			
		||||
              <div className="h-3 w-16 rounded bg-light-200 dark:bg-dark-200" />
 | 
			
		||||
              <div className="h-3 w-8 rounded bg-light-200 dark:bg-dark-200" />
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </>
 | 
			
		||||
      ) : (
 | 
			
		||||
        <>
 | 
			
		||||
          <div className="flex flex-col items-center justify-center w-16 min-w-16 max-w-16 h-full">
 | 
			
		||||
            <img
 | 
			
		||||
              src={`/weather-ico/${data.icon}.svg`}
 | 
			
		||||
              alt={data.condition}
 | 
			
		||||
              className="h-10 w-auto"
 | 
			
		||||
            />
 | 
			
		||||
            <span className="text-base font-semibold text-black dark:text-white">
 | 
			
		||||
              {data.temperature}°{data.temperatureUnit}
 | 
			
		||||
            </span>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className="flex flex-col justify-between flex-1 h-full py-1">
 | 
			
		||||
            <div className="flex flex-row items-center justify-between">
 | 
			
		||||
              <span className="text-xs font-medium text-black dark:text-white">
 | 
			
		||||
                {data.location}
 | 
			
		||||
              </span>
 | 
			
		||||
              <span className="flex items-center text-xs text-black/60 dark:text-white/60">
 | 
			
		||||
                <Wind className="w-3 h-3 mr-1" />
 | 
			
		||||
                {data.windSpeed} {data.windSpeedUnit}
 | 
			
		||||
              </span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <span className="text-xs text-black/60 dark:text-white/60 mt-1">
 | 
			
		||||
              {data.condition}
 | 
			
		||||
            </span>
 | 
			
		||||
            <div className="flex flex-row justify-between w-full mt-auto pt-1 border-t border-light-200 dark:border-dark-200 text-xs text-black/60 dark:text-white/60">
 | 
			
		||||
              <span>Humidity: {data.humidity}%</span>
 | 
			
		||||
              <span>Now</span>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </>
 | 
			
		||||
      )}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default WeatherWidget;
 | 
			
		||||
@@ -3,32 +3,18 @@ import {
 | 
			
		||||
  RunnableMap,
 | 
			
		||||
  RunnableLambda,
 | 
			
		||||
} from '@langchain/core/runnables';
 | 
			
		||||
import { PromptTemplate } from '@langchain/core/prompts';
 | 
			
		||||
import { ChatPromptTemplate } from '@langchain/core/prompts';
 | 
			
		||||
import formatChatHistoryAsString from '../utils/formatHistory';
 | 
			
		||||
import { BaseMessage } from '@langchain/core/messages';
 | 
			
		||||
import { StringOutputParser } from '@langchain/core/output_parsers';
 | 
			
		||||
import { searchSearxng } from '../searxng';
 | 
			
		||||
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
import LineOutputParser from '../outputParsers/lineOutputParser';
 | 
			
		||||
 | 
			
		||||
const imageSearchChainPrompt = `
 | 
			
		||||
You will be given a conversation below and a follow up question. You need to rephrase the follow-up question so it is a standalone question that can be used by the LLM to search the web for images.
 | 
			
		||||
You need to make sure the rephrased question agrees with the conversation and is relevant to the conversation.
 | 
			
		||||
 | 
			
		||||
Example:
 | 
			
		||||
1. Follow up question: What is a cat?
 | 
			
		||||
Rephrased: A cat
 | 
			
		||||
 | 
			
		||||
2. Follow up question: What is a car? How does it works?
 | 
			
		||||
Rephrased: Car working
 | 
			
		||||
 | 
			
		||||
3. Follow up question: How does an AC work?
 | 
			
		||||
Rephrased: AC working
 | 
			
		||||
 | 
			
		||||
Conversation:
 | 
			
		||||
{chat_history}
 | 
			
		||||
 | 
			
		||||
Follow up question: {query}
 | 
			
		||||
Rephrased question:
 | 
			
		||||
Output only the rephrased query wrapped in an XML <query> element. Do not include any explanation or additional text.
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
type ImageSearchChainInput = {
 | 
			
		||||
@@ -54,12 +40,39 @@ const createImageSearchChain = (llm: BaseChatModel) => {
 | 
			
		||||
        return input.query;
 | 
			
		||||
      },
 | 
			
		||||
    }),
 | 
			
		||||
    PromptTemplate.fromTemplate(imageSearchChainPrompt),
 | 
			
		||||
    ChatPromptTemplate.fromMessages([
 | 
			
		||||
      ['system', imageSearchChainPrompt],
 | 
			
		||||
      [
 | 
			
		||||
        'user',
 | 
			
		||||
        '<conversation>\n</conversation>\n<follow_up>\nWhat is a cat?\n</follow_up>',
 | 
			
		||||
      ],
 | 
			
		||||
      ['assistant', '<query>A cat</query>'],
 | 
			
		||||
 | 
			
		||||
      [
 | 
			
		||||
        'user',
 | 
			
		||||
        '<conversation>\n</conversation>\n<follow_up>\nWhat is a car? How does it work?\n</follow_up>',
 | 
			
		||||
      ],
 | 
			
		||||
      ['assistant', '<query>Car working</query>'],
 | 
			
		||||
      [
 | 
			
		||||
        'user',
 | 
			
		||||
        '<conversation>\n</conversation>\n<follow_up>\nHow does an AC work?\n</follow_up>',
 | 
			
		||||
      ],
 | 
			
		||||
      ['assistant', '<query>AC working</query>'],
 | 
			
		||||
      [
 | 
			
		||||
        'user',
 | 
			
		||||
        '<conversation>{chat_history}</conversation>\n<follow_up>\n{query}\n</follow_up>',
 | 
			
		||||
      ],
 | 
			
		||||
    ]),
 | 
			
		||||
    llm,
 | 
			
		||||
    strParser,
 | 
			
		||||
    RunnableLambda.from(async (input: string) => {
 | 
			
		||||
      input = input.replace(/<think>.*?<\/think>/g, '');
 | 
			
		||||
      const queryParser = new LineOutputParser({
 | 
			
		||||
        key: 'query',
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      return await queryParser.parse(input);
 | 
			
		||||
    }),
 | 
			
		||||
    RunnableLambda.from(async (input: string) => {
 | 
			
		||||
      const res = await searchSearxng(input, {
 | 
			
		||||
        engines: ['bing images', 'google images'],
 | 
			
		||||
      });
 | 
			
		||||
 
 | 
			
		||||
@@ -3,32 +3,18 @@ import {
 | 
			
		||||
  RunnableMap,
 | 
			
		||||
  RunnableLambda,
 | 
			
		||||
} from '@langchain/core/runnables';
 | 
			
		||||
import { PromptTemplate } from '@langchain/core/prompts';
 | 
			
		||||
import { ChatPromptTemplate } from '@langchain/core/prompts';
 | 
			
		||||
import formatChatHistoryAsString from '../utils/formatHistory';
 | 
			
		||||
import { BaseMessage } from '@langchain/core/messages';
 | 
			
		||||
import { StringOutputParser } from '@langchain/core/output_parsers';
 | 
			
		||||
import { searchSearxng } from '../searxng';
 | 
			
		||||
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
import LineOutputParser from '../outputParsers/lineOutputParser';
 | 
			
		||||
 | 
			
		||||
const VideoSearchChainPrompt = `
 | 
			
		||||
const videoSearchChainPrompt = `
 | 
			
		||||
You will be given a conversation below and a follow up question. You need to rephrase the follow-up question so it is a standalone question that can be used by the LLM to search Youtube for videos.
 | 
			
		||||
You need to make sure the rephrased question agrees with the conversation and is relevant to the conversation.
 | 
			
		||||
  
 | 
			
		||||
  Example:
 | 
			
		||||
  1. Follow up question: How does a car work?
 | 
			
		||||
  Rephrased: How does a car work?
 | 
			
		||||
  
 | 
			
		||||
  2. Follow up question: What is the theory of relativity?
 | 
			
		||||
  Rephrased: What is theory of relativity
 | 
			
		||||
  
 | 
			
		||||
  3. Follow up question: How does an AC work?
 | 
			
		||||
  Rephrased: How does an AC work
 | 
			
		||||
  
 | 
			
		||||
  Conversation:
 | 
			
		||||
  {chat_history}
 | 
			
		||||
  
 | 
			
		||||
  Follow up question: {query}
 | 
			
		||||
  Rephrased question:
 | 
			
		||||
Output only the rephrased query wrapped in an XML <query> element. Do not include any explanation or additional text.
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
type VideoSearchChainInput = {
 | 
			
		||||
@@ -55,12 +41,37 @@ const createVideoSearchChain = (llm: BaseChatModel) => {
 | 
			
		||||
        return input.query;
 | 
			
		||||
      },
 | 
			
		||||
    }),
 | 
			
		||||
    PromptTemplate.fromTemplate(VideoSearchChainPrompt),
 | 
			
		||||
    ChatPromptTemplate.fromMessages([
 | 
			
		||||
      ['system', videoSearchChainPrompt],
 | 
			
		||||
      [
 | 
			
		||||
        'user',
 | 
			
		||||
        '<conversation>\n</conversation>\n<follow_up>\nHow does a car work?\n</follow_up>',
 | 
			
		||||
      ],
 | 
			
		||||
      ['assistant', '<query>How does a car work?</query>'],
 | 
			
		||||
      [
 | 
			
		||||
        'user',
 | 
			
		||||
        '<conversation>\n</conversation>\n<follow_up>\nWhat is the theory of relativity?\n</follow_up>',
 | 
			
		||||
      ],
 | 
			
		||||
      ['assistant', '<query>Theory of relativity</query>'],
 | 
			
		||||
      [
 | 
			
		||||
        'user',
 | 
			
		||||
        '<conversation>\n</conversation>\n<follow_up>\nHow does an AC work?\n</follow_up>',
 | 
			
		||||
      ],
 | 
			
		||||
      ['assistant', '<query>AC working</query>'],
 | 
			
		||||
      [
 | 
			
		||||
        'user',
 | 
			
		||||
        '<conversation>{chat_history}</conversation>\n<follow_up>\n{query}\n</follow_up>',
 | 
			
		||||
      ],
 | 
			
		||||
    ]),
 | 
			
		||||
    llm,
 | 
			
		||||
    strParser,
 | 
			
		||||
    RunnableLambda.from(async (input: string) => {
 | 
			
		||||
      input = input.replace(/<think>.*?<\/think>/g, '');
 | 
			
		||||
 | 
			
		||||
      const queryParser = new LineOutputParser({
 | 
			
		||||
        key: 'query',
 | 
			
		||||
      });
 | 
			
		||||
      return await queryParser.parse(input);
 | 
			
		||||
    }),
 | 
			
		||||
    RunnableLambda.from(async (input: string) => {
 | 
			
		||||
      const res = await searchSearxng(input, {
 | 
			
		||||
        engines: ['youtube'],
 | 
			
		||||
      });
 | 
			
		||||
@@ -92,8 +103,8 @@ const handleVideoSearch = (
 | 
			
		||||
  input: VideoSearchChainInput,
 | 
			
		||||
  llm: BaseChatModel,
 | 
			
		||||
) => {
 | 
			
		||||
  const VideoSearchChain = createVideoSearchChain(llm);
 | 
			
		||||
  return VideoSearchChain.invoke(input);
 | 
			
		||||
  const videoSearchChain = createVideoSearchChain(llm);
 | 
			
		||||
  return videoSearchChain.invoke(input);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default handleVideoSearch;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,14 @@
 | 
			
		||||
import fs from 'fs';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
import toml from '@iarna/toml';
 | 
			
		||||
 | 
			
		||||
// Use dynamic imports for Node.js modules to prevent client-side errors
 | 
			
		||||
let fs: any;
 | 
			
		||||
let path: any;
 | 
			
		||||
if (typeof window === 'undefined') {
 | 
			
		||||
  // We're on the server
 | 
			
		||||
  fs = require('fs');
 | 
			
		||||
  path = require('path');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const configFileName = 'config.toml';
 | 
			
		||||
 | 
			
		||||
interface Config {
 | 
			
		||||
@@ -28,6 +35,12 @@ interface Config {
 | 
			
		||||
    DEEPSEEK: {
 | 
			
		||||
      API_KEY: string;
 | 
			
		||||
    };
 | 
			
		||||
    AIMLAPI: {
 | 
			
		||||
      API_KEY: string;
 | 
			
		||||
    };
 | 
			
		||||
    LM_STUDIO: {
 | 
			
		||||
      API_URL: string;
 | 
			
		||||
    };
 | 
			
		||||
    CUSTOM_OPENAI: {
 | 
			
		||||
      API_URL: string;
 | 
			
		||||
      API_KEY: string;
 | 
			
		||||
@@ -43,10 +56,17 @@ type RecursivePartial<T> = {
 | 
			
		||||
  [P in keyof T]?: RecursivePartial<T[P]>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const loadConfig = () =>
 | 
			
		||||
  toml.parse(
 | 
			
		||||
const loadConfig = () => {
 | 
			
		||||
  // Server-side only
 | 
			
		||||
  if (typeof window === 'undefined') {
 | 
			
		||||
    return toml.parse(
 | 
			
		||||
      fs.readFileSync(path.join(process.cwd(), `${configFileName}`), 'utf-8'),
 | 
			
		||||
    ) as any as Config;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Client-side fallback - settings will be loaded via API
 | 
			
		||||
  return {} as Config;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getSimilarityMeasure = () =>
 | 
			
		||||
  loadConfig().GENERAL.SIMILARITY_MEASURE;
 | 
			
		||||
@@ -68,6 +88,8 @@ export const getOllamaApiEndpoint = () => loadConfig().MODELS.OLLAMA.API_URL;
 | 
			
		||||
 | 
			
		||||
export const getDeepseekApiKey = () => loadConfig().MODELS.DEEPSEEK.API_KEY;
 | 
			
		||||
 | 
			
		||||
export const getAimlApiKey = () => loadConfig().MODELS.AIMLAPI.API_KEY;
 | 
			
		||||
 | 
			
		||||
export const getCustomOpenaiApiKey = () =>
 | 
			
		||||
  loadConfig().MODELS.CUSTOM_OPENAI.API_KEY;
 | 
			
		||||
 | 
			
		||||
@@ -77,6 +99,9 @@ export const getCustomOpenaiApiUrl = () =>
 | 
			
		||||
export const getCustomOpenaiModelName = () =>
 | 
			
		||||
  loadConfig().MODELS.CUSTOM_OPENAI.MODEL_NAME;
 | 
			
		||||
 | 
			
		||||
export const getLMStudioApiEndpoint = () =>
 | 
			
		||||
  loadConfig().MODELS.LM_STUDIO.API_URL;
 | 
			
		||||
 | 
			
		||||
const mergeConfigs = (current: any, update: any): any => {
 | 
			
		||||
  if (update === null || update === undefined) {
 | 
			
		||||
    return current;
 | 
			
		||||
@@ -109,10 +134,13 @@ const mergeConfigs = (current: any, update: any): any => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const updateConfig = (config: RecursivePartial<Config>) => {
 | 
			
		||||
  // Server-side only
 | 
			
		||||
  if (typeof window === 'undefined') {
 | 
			
		||||
    const currentConfig = loadConfig();
 | 
			
		||||
    const mergedConfig = mergeConfigs(currentConfig, config);
 | 
			
		||||
    fs.writeFileSync(
 | 
			
		||||
      path.join(path.join(process.cwd(), `${configFileName}`)),
 | 
			
		||||
      toml.stringify(mergedConfig),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,8 @@ import Database from 'better-sqlite3';
 | 
			
		||||
import * as schema from './schema';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
 | 
			
		||||
const sqlite = new Database(path.join(process.cwd(), 'data/db.sqlite'));
 | 
			
		||||
const DATA_DIR = process.env.DATA_DIR || process.cwd();
 | 
			
		||||
const sqlite = new Database(path.join(DATA_DIR, './data/db.sqlite'));
 | 
			
		||||
const db = drizzle(sqlite, {
 | 
			
		||||
  schema: schema,
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								src/lib/db/migrate.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,5 @@
 | 
			
		||||
import db from './';
 | 
			
		||||
import { migrate } from 'drizzle-orm/better-sqlite3/migrator';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
 | 
			
		||||
migrate(db, { migrationsFolder: path.join(process.cwd(), 'drizzle') });
 | 
			
		||||
@@ -65,12 +65,16 @@ export const webSearchResponsePrompt = `
 | 
			
		||||
    You are Perplexica, an AI model skilled in web search and crafting detailed, engaging, and well-structured answers. You excel at summarizing web pages and extracting relevant information to create professional, blog-style responses.
 | 
			
		||||
 | 
			
		||||
    Your task is to provide answers that are:
 | 
			
		||||
    - **Informative and relevant**: Thoroughly address the user's query using the given context.
 | 
			
		||||
    - **Informative and relevant**: Thoroughly address the user's query using the given  search results.
 | 
			
		||||
    - **Well-structured**: Include clear headings and subheadings, and use a professional tone to present information concisely and logically.
 | 
			
		||||
    - **Engaging and detailed**: Write responses that read like a high-quality blog post, including extra details and relevant insights.
 | 
			
		||||
    - **Cited and credible**: Use inline citations with [number] notation to refer to the context source(s) for each fact or detail included.
 | 
			
		||||
    - **Cited and credible**: Use inline citations with [number] notation to refer to the  search results source(s) for each fact or detail included.
 | 
			
		||||
    - **Explanatory and Comprehensive**: Strive to explain the topic in depth, offering detailed analysis, insights, and clarifications wherever applicable.
 | 
			
		||||
 | 
			
		||||
    You have access to the following tools which you have to use to answer the user:
 | 
			
		||||
    1. **search_web**: Use this tool to search the web for information to answer the user's question.
 | 
			
		||||
    2. **summarize**: Use this tool to summarize a link.
 | 
			
		||||
    
 | 
			
		||||
    ### Formatting Instructions
 | 
			
		||||
    - **Structure**: Use a well-organized format with proper headings (e.g., "## Example heading 1" or "## Example heading 2"). Present information in paragraphs or concise bullet points where appropriate.
 | 
			
		||||
    - **Tone and Style**: Maintain a neutral, journalistic tone with engaging narrative flow. Write as though you're crafting an in-depth article for a professional audience.
 | 
			
		||||
@@ -80,12 +84,13 @@ export const webSearchResponsePrompt = `
 | 
			
		||||
    - **Conclusion or Summary**: Include a concluding paragraph that synthesizes the provided information or suggests potential next steps, where appropriate.
 | 
			
		||||
 | 
			
		||||
    ### Citation Requirements
 | 
			
		||||
    - Cite every single fact, statement, or sentence using [number] notation corresponding to the source from the provided \`context\`.
 | 
			
		||||
    - Cite every single fact, statement, or sentence using [number] notation corresponding to the source from the search results
 | 
			
		||||
    - Integrate citations naturally at the end of sentences or clauses as appropriate. For example, "The Eiffel Tower is one of the most visited landmarks in the world[1]."
 | 
			
		||||
    - Ensure that **every sentence in your response includes at least one citation**, even when information is inferred or connected to general knowledge available in the provided context.
 | 
			
		||||
    - Ensure that **every sentence in your response includes at least one citation**, even when information is inferred or connected to general knowledge available in the provided  search results.
 | 
			
		||||
    - Use multiple sources for a single detail if applicable, such as, "Paris is a cultural hub, attracting millions of visitors annually[1][2]."
 | 
			
		||||
    - Always prioritize credibility and accuracy by linking all statements back to their respective context sources.
 | 
			
		||||
    - Always prioritize credibility and accuracy by linking all statements back to their respective  search results sources.
 | 
			
		||||
    - Avoid citing unsupported assumptions or personal interpretations; if no source supports a statement, clearly indicate the limitation.
 | 
			
		||||
    - Never return references to the citation or sources yourself, they're returned to the user internally.
 | 
			
		||||
    
 | 
			
		||||
    ### Special Instructions
 | 
			
		||||
    - If the query involves technical, historical, or complex topics, provide detailed background and explanatory sections to ensure clarity.
 | 
			
		||||
@@ -99,12 +104,8 @@ export const webSearchResponsePrompt = `
 | 
			
		||||
    ### Example Output
 | 
			
		||||
    - Begin with a brief introduction summarizing the event or query topic.
 | 
			
		||||
    - Follow with detailed sections under clear headings, covering all aspects of the query if possible.
 | 
			
		||||
    - Provide explanations or historical context as needed to enhance understanding.
 | 
			
		||||
    - Provide explanations or historical  search results as needed to enhance understanding.
 | 
			
		||||
    - End with a conclusion or overall perspective if relevant.
 | 
			
		||||
 | 
			
		||||
    <context>
 | 
			
		||||
    {context}
 | 
			
		||||
    </context>
 | 
			
		||||
 | 
			
		||||
    Current date & time in ISO format (UTC timezone) is: {date}.
 | 
			
		||||
`;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,8 +10,4 @@ However you do not need to cite it using the same number. You can use different
 | 
			
		||||
### User instructions
 | 
			
		||||
These instructions are shared to you by the user and not by the system. You will have to follow them but give them less priority than the above instructions. If the user has provided specific instructions or preferences, incorporate them into your response while adhering to the overall guidelines.
 | 
			
		||||
{systemInstructions}
 | 
			
		||||
 | 
			
		||||
<context>
 | 
			
		||||
{context}
 | 
			
		||||
</context>
 | 
			
		||||
`;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										94
									
								
								src/lib/providers/aimlapi.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,94 @@
 | 
			
		||||
import { ChatOpenAI, OpenAIEmbeddings } from '@langchain/openai';
 | 
			
		||||
import { getAimlApiKey } from '../config';
 | 
			
		||||
import { ChatModel, EmbeddingModel } from '.';
 | 
			
		||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
import { Embeddings } from '@langchain/core/embeddings';
 | 
			
		||||
import axios from 'axios';
 | 
			
		||||
 | 
			
		||||
export const PROVIDER_INFO = {
 | 
			
		||||
  key: 'aimlapi',
 | 
			
		||||
  displayName: 'AI/ML API',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
interface AimlApiModel {
 | 
			
		||||
  id: string;
 | 
			
		||||
  name?: string;
 | 
			
		||||
  type?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const API_URL = 'https://api.aimlapi.com';
 | 
			
		||||
 | 
			
		||||
export const loadAimlApiChatModels = async () => {
 | 
			
		||||
  const apiKey = getAimlApiKey();
 | 
			
		||||
 | 
			
		||||
  if (!apiKey) return {};
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    const response = await axios.get(`${API_URL}/models`, {
 | 
			
		||||
      headers: {
 | 
			
		||||
        'Content-Type': 'application/json',
 | 
			
		||||
        Authorization: `Bearer ${apiKey}`,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const chatModels: Record<string, ChatModel> = {};
 | 
			
		||||
 | 
			
		||||
    response.data.data.forEach((model: AimlApiModel) => {
 | 
			
		||||
      if (model.type === 'chat-completion') {
 | 
			
		||||
        chatModels[model.id] = {
 | 
			
		||||
          displayName: model.name || model.id,
 | 
			
		||||
          model: new ChatOpenAI({
 | 
			
		||||
            apiKey: apiKey,
 | 
			
		||||
            modelName: model.id,
 | 
			
		||||
            temperature: 0.7,
 | 
			
		||||
            configuration: {
 | 
			
		||||
              baseURL: API_URL,
 | 
			
		||||
            },
 | 
			
		||||
          }) as unknown as BaseChatModel,
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return chatModels;
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    console.error(`Error loading AI/ML API models: ${err}`);
 | 
			
		||||
    return {};
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const loadAimlApiEmbeddingModels = async () => {
 | 
			
		||||
  const apiKey = getAimlApiKey();
 | 
			
		||||
 | 
			
		||||
  if (!apiKey) return {};
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    const response = await axios.get(`${API_URL}/models`, {
 | 
			
		||||
      headers: {
 | 
			
		||||
        'Content-Type': 'application/json',
 | 
			
		||||
        Authorization: `Bearer ${apiKey}`,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const embeddingModels: Record<string, EmbeddingModel> = {};
 | 
			
		||||
 | 
			
		||||
    response.data.data.forEach((model: AimlApiModel) => {
 | 
			
		||||
      if (model.type === 'embedding') {
 | 
			
		||||
        embeddingModels[model.id] = {
 | 
			
		||||
          displayName: model.name || model.id,
 | 
			
		||||
          model: new OpenAIEmbeddings({
 | 
			
		||||
            apiKey: apiKey,
 | 
			
		||||
            modelName: model.id,
 | 
			
		||||
            configuration: {
 | 
			
		||||
              baseURL: API_URL,
 | 
			
		||||
            },
 | 
			
		||||
          }) as unknown as Embeddings,
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return embeddingModels;
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    console.error(`Error loading AI/ML API embeddings models: ${err}`);
 | 
			
		||||
    return {};
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -1,6 +1,11 @@
 | 
			
		||||
import { ChatAnthropic } from '@langchain/anthropic';
 | 
			
		||||
import { ChatModel } from '.';
 | 
			
		||||
import { getAnthropicApiKey } from '../config';
 | 
			
		||||
 | 
			
		||||
export const PROVIDER_INFO = {
 | 
			
		||||
  key: 'anthropic',
 | 
			
		||||
  displayName: 'Anthropic',
 | 
			
		||||
};
 | 
			
		||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
 | 
			
		||||
const anthropicChatModels: Record<string, string>[] = [
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,11 @@ import { getDeepseekApiKey } from '../config';
 | 
			
		||||
import { ChatModel } from '.';
 | 
			
		||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
 | 
			
		||||
export const PROVIDER_INFO = {
 | 
			
		||||
  key: 'deepseek',
 | 
			
		||||
  displayName: 'Deepseek AI',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const deepseekChatModels: Record<string, string>[] = [
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Deepseek Chat (Deepseek V3)',
 | 
			
		||||
@@ -26,7 +31,7 @@ export const loadDeepseekChatModels = async () => {
 | 
			
		||||
      chatModels[model.key] = {
 | 
			
		||||
        displayName: model.displayName,
 | 
			
		||||
        model: new ChatOpenAI({
 | 
			
		||||
          openAIApiKey: deepseekApiKey,
 | 
			
		||||
          apiKey: deepseekApiKey,
 | 
			
		||||
          modelName: model.key,
 | 
			
		||||
          temperature: 0.7,
 | 
			
		||||
          configuration: {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,13 +4,22 @@ import {
 | 
			
		||||
} from '@langchain/google-genai';
 | 
			
		||||
import { getGeminiApiKey } from '../config';
 | 
			
		||||
import { ChatModel, EmbeddingModel } from '.';
 | 
			
		||||
 | 
			
		||||
export const PROVIDER_INFO = {
 | 
			
		||||
  key: 'gemini',
 | 
			
		||||
  displayName: 'Google Gemini',
 | 
			
		||||
};
 | 
			
		||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
import { Embeddings } from '@langchain/core/embeddings';
 | 
			
		||||
 | 
			
		||||
const geminiChatModels: Record<string, string>[] = [
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Gemini 2.5 Pro Experimental',
 | 
			
		||||
    key: 'gemini-2.5-pro-exp-03-25',
 | 
			
		||||
    displayName: 'Gemini 2.5 Flash',
 | 
			
		||||
    key: 'gemini-2.5-flash',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Gemini 2.5 Pro',
 | 
			
		||||
    key: 'gemini-2.5-pro',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Gemini 2.0 Flash',
 | 
			
		||||
@@ -62,7 +71,7 @@ export const loadGeminiChatModels = async () => {
 | 
			
		||||
        displayName: model.displayName,
 | 
			
		||||
        model: new ChatGoogleGenerativeAI({
 | 
			
		||||
          apiKey: geminiApiKey,
 | 
			
		||||
          modelName: model.key,
 | 
			
		||||
          model: model.key,
 | 
			
		||||
          temperature: 0.7,
 | 
			
		||||
        }) as unknown as BaseChatModel,
 | 
			
		||||
      };
 | 
			
		||||
@@ -95,7 +104,7 @@ export const loadGeminiEmbeddingModels = async () => {
 | 
			
		||||
 | 
			
		||||
    return embeddingModels;
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    console.error(`Error loading OpenAI embeddings models: ${err}`);
 | 
			
		||||
    console.error(`Error loading Gemini embeddings models: ${err}`);
 | 
			
		||||
    return {};
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,105 +1,37 @@
 | 
			
		||||
import { ChatOpenAI } from '@langchain/openai';
 | 
			
		||||
import { ChatGroq } from '@langchain/groq';
 | 
			
		||||
import { getGroqApiKey } from '../config';
 | 
			
		||||
import { ChatModel } from '.';
 | 
			
		||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
 | 
			
		||||
const groqChatModels: Record<string, string>[] = [
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Gemma2 9B IT',
 | 
			
		||||
    key: 'gemma2-9b-it',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Llama 3.3 70B Versatile',
 | 
			
		||||
    key: 'llama-3.3-70b-versatile',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Llama 3.1 8B Instant',
 | 
			
		||||
    key: 'llama-3.1-8b-instant',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Llama3 70B 8192',
 | 
			
		||||
    key: 'llama3-70b-8192',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Llama3 8B 8192',
 | 
			
		||||
    key: 'llama3-8b-8192',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Mixtral 8x7B 32768',
 | 
			
		||||
    key: 'mixtral-8x7b-32768',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Qwen QWQ 32B (Preview)',
 | 
			
		||||
    key: 'qwen-qwq-32b',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Mistral Saba 24B (Preview)',
 | 
			
		||||
    key: 'mistral-saba-24b',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Qwen 2.5 Coder 32B (Preview)',
 | 
			
		||||
    key: 'qwen-2.5-coder-32b',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Qwen 2.5 32B (Preview)',
 | 
			
		||||
    key: 'qwen-2.5-32b',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'DeepSeek R1 Distill Qwen 32B (Preview)',
 | 
			
		||||
    key: 'deepseek-r1-distill-qwen-32b',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'DeepSeek R1 Distill Llama 70B (Preview)',
 | 
			
		||||
    key: 'deepseek-r1-distill-llama-70b',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Llama 3.3 70B SpecDec (Preview)',
 | 
			
		||||
    key: 'llama-3.3-70b-specdec',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Llama 3.2 1B Preview (Preview)',
 | 
			
		||||
    key: 'llama-3.2-1b-preview',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Llama 3.2 3B Preview (Preview)',
 | 
			
		||||
    key: 'llama-3.2-3b-preview',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Llama 3.2 11B Vision Preview (Preview)',
 | 
			
		||||
    key: 'llama-3.2-11b-vision-preview',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Llama 3.2 90B Vision Preview (Preview)',
 | 
			
		||||
    key: 'llama-3.2-90b-vision-preview',
 | 
			
		||||
  },
 | 
			
		||||
  /* {
 | 
			
		||||
    displayName: 'Llama 4 Maverick 17B 128E Instruct (Preview)',
 | 
			
		||||
    key: 'meta-llama/llama-4-maverick-17b-128e-instruct',
 | 
			
		||||
  }, */
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'Llama 4 Scout 17B 16E Instruct (Preview)',
 | 
			
		||||
    key: 'meta-llama/llama-4-scout-17b-16e-instruct',
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
export const PROVIDER_INFO = {
 | 
			
		||||
  key: 'groq',
 | 
			
		||||
  displayName: 'Groq',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
 | 
			
		||||
export const loadGroqChatModels = async () => {
 | 
			
		||||
  const groqApiKey = getGroqApiKey();
 | 
			
		||||
 | 
			
		||||
  if (!groqApiKey) return {};
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    const res = await fetch('https://api.groq.com/openai/v1/models', {
 | 
			
		||||
      method: 'GET',
 | 
			
		||||
      headers: {
 | 
			
		||||
        Authorization: `bearer ${groqApiKey}`,
 | 
			
		||||
        'Content-Type': 'application/json',
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const groqChatModels = (await res.json()).data;
 | 
			
		||||
    const chatModels: Record<string, ChatModel> = {};
 | 
			
		||||
 | 
			
		||||
    groqChatModels.forEach((model) => {
 | 
			
		||||
      chatModels[model.key] = {
 | 
			
		||||
        displayName: model.displayName,
 | 
			
		||||
        model: new ChatOpenAI({
 | 
			
		||||
          openAIApiKey: groqApiKey,
 | 
			
		||||
          modelName: model.key,
 | 
			
		||||
    groqChatModels.forEach((model: any) => {
 | 
			
		||||
      chatModels[model.id] = {
 | 
			
		||||
        displayName: model.id,
 | 
			
		||||
        model: new ChatGroq({
 | 
			
		||||
          apiKey: groqApiKey,
 | 
			
		||||
          model: model.id,
 | 
			
		||||
          temperature: 0.7,
 | 
			
		||||
          configuration: {
 | 
			
		||||
            baseURL: 'https://api.groq.com/openai/v1',
 | 
			
		||||
          },
 | 
			
		||||
        }) as unknown as BaseChatModel,
 | 
			
		||||
      };
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,66 @@
 | 
			
		||||
import { Embeddings } from '@langchain/core/embeddings';
 | 
			
		||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
import { loadOpenAIChatModels, loadOpenAIEmbeddingModels } from './openai';
 | 
			
		||||
import {
 | 
			
		||||
  loadOpenAIChatModels,
 | 
			
		||||
  loadOpenAIEmbeddingModels,
 | 
			
		||||
  PROVIDER_INFO as OpenAIInfo,
 | 
			
		||||
  PROVIDER_INFO,
 | 
			
		||||
} from './openai';
 | 
			
		||||
import {
 | 
			
		||||
  getCustomOpenaiApiKey,
 | 
			
		||||
  getCustomOpenaiApiUrl,
 | 
			
		||||
  getCustomOpenaiModelName,
 | 
			
		||||
} from '../config';
 | 
			
		||||
import { ChatOpenAI } from '@langchain/openai';
 | 
			
		||||
import { loadOllamaChatModels, loadOllamaEmbeddingModels } from './ollama';
 | 
			
		||||
import { loadGroqChatModels } from './groq';
 | 
			
		||||
import { loadAnthropicChatModels } from './anthropic';
 | 
			
		||||
import { loadGeminiChatModels, loadGeminiEmbeddingModels } from './gemini';
 | 
			
		||||
import { loadTransformersEmbeddingsModels } from './transformers';
 | 
			
		||||
import { loadDeepseekChatModels } from './deepseek';
 | 
			
		||||
import {
 | 
			
		||||
  loadOllamaChatModels,
 | 
			
		||||
  loadOllamaEmbeddingModels,
 | 
			
		||||
  PROVIDER_INFO as OllamaInfo,
 | 
			
		||||
} from './ollama';
 | 
			
		||||
import { loadGroqChatModels, PROVIDER_INFO as GroqInfo } from './groq';
 | 
			
		||||
import {
 | 
			
		||||
  loadAnthropicChatModels,
 | 
			
		||||
  PROVIDER_INFO as AnthropicInfo,
 | 
			
		||||
} from './anthropic';
 | 
			
		||||
import {
 | 
			
		||||
  loadGeminiChatModels,
 | 
			
		||||
  loadGeminiEmbeddingModels,
 | 
			
		||||
  PROVIDER_INFO as GeminiInfo,
 | 
			
		||||
} from './gemini';
 | 
			
		||||
import {
 | 
			
		||||
  loadTransformersEmbeddingsModels,
 | 
			
		||||
  PROVIDER_INFO as TransformersInfo,
 | 
			
		||||
} from './transformers';
 | 
			
		||||
import {
 | 
			
		||||
  loadDeepseekChatModels,
 | 
			
		||||
  PROVIDER_INFO as DeepseekInfo,
 | 
			
		||||
} from './deepseek';
 | 
			
		||||
import {
 | 
			
		||||
  loadAimlApiChatModels,
 | 
			
		||||
  loadAimlApiEmbeddingModels,
 | 
			
		||||
  PROVIDER_INFO as AimlApiInfo,
 | 
			
		||||
} from './aimlapi';
 | 
			
		||||
import {
 | 
			
		||||
  loadLMStudioChatModels,
 | 
			
		||||
  loadLMStudioEmbeddingsModels,
 | 
			
		||||
  PROVIDER_INFO as LMStudioInfo,
 | 
			
		||||
} from './lmstudio';
 | 
			
		||||
 | 
			
		||||
export const PROVIDER_METADATA = {
 | 
			
		||||
  openai: OpenAIInfo,
 | 
			
		||||
  ollama: OllamaInfo,
 | 
			
		||||
  groq: GroqInfo,
 | 
			
		||||
  anthropic: AnthropicInfo,
 | 
			
		||||
  gemini: GeminiInfo,
 | 
			
		||||
  transformers: TransformersInfo,
 | 
			
		||||
  deepseek: DeepseekInfo,
 | 
			
		||||
  aimlapi: AimlApiInfo,
 | 
			
		||||
  lmstudio: LMStudioInfo,
 | 
			
		||||
  custom_openai: {
 | 
			
		||||
    key: 'custom_openai',
 | 
			
		||||
    displayName: 'Custom OpenAI',
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export interface ChatModel {
 | 
			
		||||
  displayName: string;
 | 
			
		||||
@@ -34,6 +82,8 @@ export const chatModelProviders: Record<
 | 
			
		||||
  anthropic: loadAnthropicChatModels,
 | 
			
		||||
  gemini: loadGeminiChatModels,
 | 
			
		||||
  deepseek: loadDeepseekChatModels,
 | 
			
		||||
  aimlapi: loadAimlApiChatModels,
 | 
			
		||||
  lmstudio: loadLMStudioChatModels,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const embeddingModelProviders: Record<
 | 
			
		||||
@@ -44,6 +94,8 @@ export const embeddingModelProviders: Record<
 | 
			
		||||
  ollama: loadOllamaEmbeddingModels,
 | 
			
		||||
  gemini: loadGeminiEmbeddingModels,
 | 
			
		||||
  transformers: loadTransformersEmbeddingsModels,
 | 
			
		||||
  aimlapi: loadAimlApiEmbeddingModels,
 | 
			
		||||
  lmstudio: loadLMStudioEmbeddingsModels,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getAvailableChatModelProviders = async () => {
 | 
			
		||||
@@ -66,7 +118,7 @@ export const getAvailableChatModelProviders = async () => {
 | 
			
		||||
          [customOpenAiModelName]: {
 | 
			
		||||
            displayName: customOpenAiModelName,
 | 
			
		||||
            model: new ChatOpenAI({
 | 
			
		||||
              openAIApiKey: customOpenAiApiKey,
 | 
			
		||||
              apiKey: customOpenAiApiKey,
 | 
			
		||||
              modelName: customOpenAiModelName,
 | 
			
		||||
              temperature: 0.7,
 | 
			
		||||
              configuration: {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										100
									
								
								src/lib/providers/lmstudio.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,100 @@
 | 
			
		||||
import { getKeepAlive, getLMStudioApiEndpoint } from '../config';
 | 
			
		||||
import axios from 'axios';
 | 
			
		||||
import { ChatModel, EmbeddingModel } from '.';
 | 
			
		||||
 | 
			
		||||
export const PROVIDER_INFO = {
 | 
			
		||||
  key: 'lmstudio',
 | 
			
		||||
  displayName: 'LM Studio',
 | 
			
		||||
};
 | 
			
		||||
import { ChatOpenAI } from '@langchain/openai';
 | 
			
		||||
import { OpenAIEmbeddings } from '@langchain/openai';
 | 
			
		||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
import { Embeddings } from '@langchain/core/embeddings';
 | 
			
		||||
 | 
			
		||||
interface LMStudioModel {
 | 
			
		||||
  id: string;
 | 
			
		||||
  name?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ensureV1Endpoint = (endpoint: string): string =>
 | 
			
		||||
  endpoint.endsWith('/v1') ? endpoint : `${endpoint}/v1`;
 | 
			
		||||
 | 
			
		||||
const checkServerAvailability = async (endpoint: string): Promise<boolean> => {
 | 
			
		||||
  try {
 | 
			
		||||
    await axios.get(`${ensureV1Endpoint(endpoint)}/models`, {
 | 
			
		||||
      headers: { 'Content-Type': 'application/json' },
 | 
			
		||||
    });
 | 
			
		||||
    return true;
 | 
			
		||||
  } catch {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const loadLMStudioChatModels = async () => {
 | 
			
		||||
  const endpoint = getLMStudioApiEndpoint();
 | 
			
		||||
 | 
			
		||||
  if (!endpoint) return {};
 | 
			
		||||
  if (!(await checkServerAvailability(endpoint))) return {};
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    const response = await axios.get(`${ensureV1Endpoint(endpoint)}/models`, {
 | 
			
		||||
      headers: { 'Content-Type': 'application/json' },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const chatModels: Record<string, ChatModel> = {};
 | 
			
		||||
 | 
			
		||||
    response.data.data.forEach((model: LMStudioModel) => {
 | 
			
		||||
      chatModels[model.id] = {
 | 
			
		||||
        displayName: model.name || model.id,
 | 
			
		||||
        model: new ChatOpenAI({
 | 
			
		||||
          apiKey: 'lm-studio',
 | 
			
		||||
          configuration: {
 | 
			
		||||
            baseURL: ensureV1Endpoint(endpoint),
 | 
			
		||||
          },
 | 
			
		||||
          modelName: model.id,
 | 
			
		||||
          temperature: 0.7,
 | 
			
		||||
          streaming: true,
 | 
			
		||||
          maxRetries: 3,
 | 
			
		||||
        }) as unknown as BaseChatModel,
 | 
			
		||||
      };
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return chatModels;
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    console.error(`Error loading LM Studio models: ${err}`);
 | 
			
		||||
    return {};
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const loadLMStudioEmbeddingsModels = async () => {
 | 
			
		||||
  const endpoint = getLMStudioApiEndpoint();
 | 
			
		||||
 | 
			
		||||
  if (!endpoint) return {};
 | 
			
		||||
  if (!(await checkServerAvailability(endpoint))) return {};
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    const response = await axios.get(`${ensureV1Endpoint(endpoint)}/models`, {
 | 
			
		||||
      headers: { 'Content-Type': 'application/json' },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const embeddingsModels: Record<string, EmbeddingModel> = {};
 | 
			
		||||
 | 
			
		||||
    response.data.data.forEach((model: LMStudioModel) => {
 | 
			
		||||
      embeddingsModels[model.id] = {
 | 
			
		||||
        displayName: model.name || model.id,
 | 
			
		||||
        model: new OpenAIEmbeddings({
 | 
			
		||||
          apiKey: 'lm-studio',
 | 
			
		||||
          configuration: {
 | 
			
		||||
            baseURL: ensureV1Endpoint(endpoint),
 | 
			
		||||
          },
 | 
			
		||||
          modelName: model.id,
 | 
			
		||||
        }) as unknown as Embeddings,
 | 
			
		||||
      };
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return embeddingsModels;
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    console.error(`Error loading LM Studio embeddings model: ${err}`);
 | 
			
		||||
    return {};
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -1,8 +1,13 @@
 | 
			
		||||
import axios from 'axios';
 | 
			
		||||
import { getKeepAlive, getOllamaApiEndpoint } from '../config';
 | 
			
		||||
import { ChatModel, EmbeddingModel } from '.';
 | 
			
		||||
import { ChatOllama } from '@langchain/community/chat_models/ollama';
 | 
			
		||||
import { OllamaEmbeddings } from '@langchain/community/embeddings/ollama';
 | 
			
		||||
 | 
			
		||||
export const PROVIDER_INFO = {
 | 
			
		||||
  key: 'ollama',
 | 
			
		||||
  displayName: 'Ollama',
 | 
			
		||||
};
 | 
			
		||||
import { ChatOllama } from '@langchain/ollama';
 | 
			
		||||
import { OllamaEmbeddings } from '@langchain/ollama';
 | 
			
		||||
 | 
			
		||||
export const loadOllamaChatModels = async () => {
 | 
			
		||||
  const ollamaApiEndpoint = getOllamaApiEndpoint();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,11 @@
 | 
			
		||||
import { ChatOpenAI, OpenAIEmbeddings } from '@langchain/openai';
 | 
			
		||||
import { getOpenaiApiKey } from '../config';
 | 
			
		||||
import { ChatModel, EmbeddingModel } from '.';
 | 
			
		||||
 | 
			
		||||
export const PROVIDER_INFO = {
 | 
			
		||||
  key: 'openai',
 | 
			
		||||
  displayName: 'OpenAI',
 | 
			
		||||
};
 | 
			
		||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
 | 
			
		||||
import { Embeddings } from '@langchain/core/embeddings';
 | 
			
		||||
 | 
			
		||||
@@ -25,6 +30,18 @@ const openaiChatModels: Record<string, string>[] = [
 | 
			
		||||
    displayName: 'GPT-4 omni mini',
 | 
			
		||||
    key: 'gpt-4o-mini',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'GPT 4.1 nano',
 | 
			
		||||
    key: 'gpt-4.1-nano',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'GPT 4.1 mini',
 | 
			
		||||
    key: 'gpt-4.1-mini',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    displayName: 'GPT 4.1',
 | 
			
		||||
    key: 'gpt-4.1',
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const openaiEmbeddingModels: Record<string, string>[] = [
 | 
			
		||||
@@ -50,7 +67,7 @@ export const loadOpenAIChatModels = async () => {
 | 
			
		||||
      chatModels[model.key] = {
 | 
			
		||||
        displayName: model.displayName,
 | 
			
		||||
        model: new ChatOpenAI({
 | 
			
		||||
          openAIApiKey: openaiApiKey,
 | 
			
		||||
          apiKey: openaiApiKey,
 | 
			
		||||
          modelName: model.key,
 | 
			
		||||
          temperature: 0.7,
 | 
			
		||||
        }) as unknown as BaseChatModel,
 | 
			
		||||
@@ -76,7 +93,7 @@ export const loadOpenAIEmbeddingModels = async () => {
 | 
			
		||||
      embeddingModels[model.key] = {
 | 
			
		||||
        displayName: model.displayName,
 | 
			
		||||
        model: new OpenAIEmbeddings({
 | 
			
		||||
          openAIApiKey: openaiApiKey,
 | 
			
		||||
          apiKey: openaiApiKey,
 | 
			
		||||
          modelName: model.key,
 | 
			
		||||
        }) as unknown as Embeddings,
 | 
			
		||||
      };
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,10 @@
 | 
			
		||||
import { HuggingFaceTransformersEmbeddings } from '../huggingfaceTransformer';
 | 
			
		||||
 | 
			
		||||
export const PROVIDER_INFO = {
 | 
			
		||||
  key: 'transformers',
 | 
			
		||||
  displayName: 'Hugging Face',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const loadTransformersEmbeddingsModels = async () => {
 | 
			
		||||
  try {
 | 
			
		||||
    const embeddingModels = {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,12 @@ import {
 | 
			
		||||
  RunnableMap,
 | 
			
		||||
  RunnableSequence,
 | 
			
		||||
} from '@langchain/core/runnables';
 | 
			
		||||
import { BaseMessage } from '@langchain/core/messages';
 | 
			
		||||
import {
 | 
			
		||||
  AIMessage,
 | 
			
		||||
  BaseMessage,
 | 
			
		||||
  isAIMessage,
 | 
			
		||||
  ToolMessage,
 | 
			
		||||
} from '@langchain/core/messages';
 | 
			
		||||
import { StringOutputParser } from '@langchain/core/output_parsers';
 | 
			
		||||
import LineListOutputParser from '../outputParsers/listLineOutputParser';
 | 
			
		||||
import LineOutputParser from '../outputParsers/lineOutputParser';
 | 
			
		||||
@@ -24,6 +29,15 @@ import computeSimilarity from '../utils/computeSimilarity';
 | 
			
		||||
import formatChatHistoryAsString from '../utils/formatHistory';
 | 
			
		||||
import eventEmitter from 'events';
 | 
			
		||||
import { StreamEvent } from '@langchain/core/tracers/log_stream';
 | 
			
		||||
import { DynamicStructuredTool, tool } from '@langchain/core/tools';
 | 
			
		||||
import { MessagesAnnotation, StateGraph } from '@langchain/langgraph';
 | 
			
		||||
import { z } from 'zod';
 | 
			
		||||
import {
 | 
			
		||||
  IterableReadableStream,
 | 
			
		||||
  IterableReadableStreamInterface,
 | 
			
		||||
} from '@langchain/core/utils/stream';
 | 
			
		||||
import EventEmitter from 'node:events';
 | 
			
		||||
import { BaseLanguageModel } from '@langchain/core/language_models/base';
 | 
			
		||||
 | 
			
		||||
export interface MetaSearchAgentType {
 | 
			
		||||
  searchAndAnswer: (
 | 
			
		||||
@@ -47,11 +61,6 @@ interface Config {
 | 
			
		||||
  activeEngines: string[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BasicChainInput = {
 | 
			
		||||
  chat_history: BaseMessage[];
 | 
			
		||||
  query: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class MetaSearchAgent implements MetaSearchAgentType {
 | 
			
		||||
  private config: Config;
 | 
			
		||||
  private strParser = new StringOutputParser();
 | 
			
		||||
@@ -60,239 +69,6 @@ class MetaSearchAgent implements MetaSearchAgentType {
 | 
			
		||||
    this.config = config;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async createSearchRetrieverChain(llm: BaseChatModel) {
 | 
			
		||||
    (llm as unknown as ChatOpenAI).temperature = 0;
 | 
			
		||||
 | 
			
		||||
    return RunnableSequence.from([
 | 
			
		||||
      PromptTemplate.fromTemplate(this.config.queryGeneratorPrompt),
 | 
			
		||||
      llm,
 | 
			
		||||
      this.strParser,
 | 
			
		||||
      RunnableLambda.from(async (input: string) => {
 | 
			
		||||
        const linksOutputParser = new LineListOutputParser({
 | 
			
		||||
          key: 'links',
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        const questionOutputParser = new LineOutputParser({
 | 
			
		||||
          key: 'question',
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        const links = await linksOutputParser.parse(input);
 | 
			
		||||
        let question = this.config.summarizer
 | 
			
		||||
          ? await questionOutputParser.parse(input)
 | 
			
		||||
          : input;
 | 
			
		||||
 | 
			
		||||
        if (question === 'not_needed') {
 | 
			
		||||
          return { query: '', docs: [] };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (links.length > 0) {
 | 
			
		||||
          if (question.length === 0) {
 | 
			
		||||
            question = 'summarize';
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          let docs: Document[] = [];
 | 
			
		||||
 | 
			
		||||
          const linkDocs = await getDocumentsFromLinks({ links });
 | 
			
		||||
 | 
			
		||||
          const docGroups: Document[] = [];
 | 
			
		||||
 | 
			
		||||
          linkDocs.map((doc) => {
 | 
			
		||||
            const URLDocExists = docGroups.find(
 | 
			
		||||
              (d) =>
 | 
			
		||||
                d.metadata.url === doc.metadata.url &&
 | 
			
		||||
                d.metadata.totalDocs < 10,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (!URLDocExists) {
 | 
			
		||||
              docGroups.push({
 | 
			
		||||
                ...doc,
 | 
			
		||||
                metadata: {
 | 
			
		||||
                  ...doc.metadata,
 | 
			
		||||
                  totalDocs: 1,
 | 
			
		||||
                },
 | 
			
		||||
              });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const docIndex = docGroups.findIndex(
 | 
			
		||||
              (d) =>
 | 
			
		||||
                d.metadata.url === doc.metadata.url &&
 | 
			
		||||
                d.metadata.totalDocs < 10,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (docIndex !== -1) {
 | 
			
		||||
              docGroups[docIndex].pageContent =
 | 
			
		||||
                docGroups[docIndex].pageContent + `\n\n` + doc.pageContent;
 | 
			
		||||
              docGroups[docIndex].metadata.totalDocs += 1;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          await Promise.all(
 | 
			
		||||
            docGroups.map(async (doc) => {
 | 
			
		||||
              const res = await llm.invoke(`
 | 
			
		||||
            You are a web search summarizer, tasked with summarizing a piece of text retrieved from a web search. Your job is to summarize the 
 | 
			
		||||
            text into a detailed, 2-4 paragraph explanation that captures the main ideas and provides a comprehensive answer to the query.
 | 
			
		||||
            If the query is \"summarize\", you should provide a detailed summary of the text. If the query is a specific question, you should answer it in the summary.
 | 
			
		||||
            
 | 
			
		||||
            - **Journalistic tone**: The summary should sound professional and journalistic, not too casual or vague.
 | 
			
		||||
            - **Thorough and detailed**: Ensure that every key point from the text is captured and that the summary directly answers the query.
 | 
			
		||||
            - **Not too lengthy, but detailed**: The summary should be informative but not excessively long. Focus on providing detailed information in a concise format.
 | 
			
		||||
 | 
			
		||||
            The text will be shared inside the \`text\` XML tag, and the query inside the \`query\` XML tag.
 | 
			
		||||
 | 
			
		||||
            <example>
 | 
			
		||||
            1. \`<text>
 | 
			
		||||
            Docker is a set of platform-as-a-service products that use OS-level virtualization to deliver software in packages called containers. 
 | 
			
		||||
            It was first released in 2013 and is developed by Docker, Inc. Docker is designed to make it easier to create, deploy, and run applications 
 | 
			
		||||
            by using containers.
 | 
			
		||||
            </text>
 | 
			
		||||
 | 
			
		||||
            <query>
 | 
			
		||||
            What is Docker and how does it work?
 | 
			
		||||
            </query>
 | 
			
		||||
 | 
			
		||||
            Response:
 | 
			
		||||
            Docker is a revolutionary platform-as-a-service product developed by Docker, Inc., that uses container technology to make application 
 | 
			
		||||
            deployment more efficient. It allows developers to package their software with all necessary dependencies, making it easier to run in 
 | 
			
		||||
            any environment. Released in 2013, Docker has transformed the way applications are built, deployed, and managed.
 | 
			
		||||
            \`
 | 
			
		||||
            2. \`<text>
 | 
			
		||||
            The theory of relativity, or simply relativity, encompasses two interrelated theories of Albert Einstein: special relativity and general
 | 
			
		||||
            relativity. However, the word "relativity" is sometimes used in reference to Galilean invariance. The term "theory of relativity" was based
 | 
			
		||||
            on the expression "relative theory" used by Max Planck in 1906. The theory of relativity usually encompasses two interrelated theories by
 | 
			
		||||
            Albert Einstein: special relativity and general relativity. Special relativity applies to all physical phenomena in the absence of gravity.
 | 
			
		||||
            General relativity explains the law of gravitation and its relation to other forces of nature. It applies to the cosmological and astrophysical
 | 
			
		||||
            realm, including astronomy.
 | 
			
		||||
            </text>
 | 
			
		||||
 | 
			
		||||
            <query>
 | 
			
		||||
            summarize
 | 
			
		||||
            </query>
 | 
			
		||||
 | 
			
		||||
            Response:
 | 
			
		||||
            The theory of relativity, developed by Albert Einstein, encompasses two main theories: special relativity and general relativity. Special
 | 
			
		||||
            relativity applies to all physical phenomena in the absence of gravity, while general relativity explains the law of gravitation and its
 | 
			
		||||
            relation to other forces of nature. The theory of relativity is based on the concept of "relative theory," as introduced by Max Planck in
 | 
			
		||||
            1906. It is a fundamental theory in physics that has revolutionized our understanding of the universe.
 | 
			
		||||
            \`
 | 
			
		||||
            </example>
 | 
			
		||||
 | 
			
		||||
            Everything below is the actual data you will be working with. Good luck!
 | 
			
		||||
 | 
			
		||||
            <query>
 | 
			
		||||
            ${question}
 | 
			
		||||
            </query>
 | 
			
		||||
 | 
			
		||||
            <text>
 | 
			
		||||
            ${doc.pageContent}
 | 
			
		||||
            </text>
 | 
			
		||||
 | 
			
		||||
            Make sure to answer the query in the summary.
 | 
			
		||||
          `);
 | 
			
		||||
 | 
			
		||||
              const document = new Document({
 | 
			
		||||
                pageContent: res.content as string,
 | 
			
		||||
                metadata: {
 | 
			
		||||
                  title: doc.metadata.title,
 | 
			
		||||
                  url: doc.metadata.url,
 | 
			
		||||
                },
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              docs.push(document);
 | 
			
		||||
            }),
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
          return { query: question, docs: docs };
 | 
			
		||||
        } else {
 | 
			
		||||
          question = question.replace(/<think>.*?<\/think>/g, '');
 | 
			
		||||
 | 
			
		||||
          const res = await searchSearxng(question, {
 | 
			
		||||
            language: 'en',
 | 
			
		||||
            engines: this.config.activeEngines,
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          const documents = res.results.map(
 | 
			
		||||
            (result) =>
 | 
			
		||||
              new Document({
 | 
			
		||||
                pageContent:
 | 
			
		||||
                  result.content ||
 | 
			
		||||
                  (this.config.activeEngines.includes('youtube')
 | 
			
		||||
                    ? result.title
 | 
			
		||||
                    : '') /* Todo: Implement transcript grabbing using Youtubei (source: https://www.npmjs.com/package/youtubei) */,
 | 
			
		||||
                metadata: {
 | 
			
		||||
                  title: result.title,
 | 
			
		||||
                  url: result.url,
 | 
			
		||||
                  ...(result.img_src && { img_src: result.img_src }),
 | 
			
		||||
                },
 | 
			
		||||
              }),
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
          return { query: question, docs: documents };
 | 
			
		||||
        }
 | 
			
		||||
      }),
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async createAnsweringChain(
 | 
			
		||||
    llm: BaseChatModel,
 | 
			
		||||
    fileIds: string[],
 | 
			
		||||
    embeddings: Embeddings,
 | 
			
		||||
    optimizationMode: 'speed' | 'balanced' | 'quality',
 | 
			
		||||
    systemInstructions: string,
 | 
			
		||||
  ) {
 | 
			
		||||
    return RunnableSequence.from([
 | 
			
		||||
      RunnableMap.from({
 | 
			
		||||
        systemInstructions: () => systemInstructions,
 | 
			
		||||
        query: (input: BasicChainInput) => input.query,
 | 
			
		||||
        chat_history: (input: BasicChainInput) => input.chat_history,
 | 
			
		||||
        date: () => new Date().toISOString(),
 | 
			
		||||
        context: RunnableLambda.from(async (input: BasicChainInput) => {
 | 
			
		||||
          const processedHistory = formatChatHistoryAsString(
 | 
			
		||||
            input.chat_history,
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
          let docs: Document[] | null = null;
 | 
			
		||||
          let query = input.query;
 | 
			
		||||
 | 
			
		||||
          if (this.config.searchWeb) {
 | 
			
		||||
            const searchRetrieverChain =
 | 
			
		||||
              await this.createSearchRetrieverChain(llm);
 | 
			
		||||
 | 
			
		||||
            const searchRetrieverResult = await searchRetrieverChain.invoke({
 | 
			
		||||
              chat_history: processedHistory,
 | 
			
		||||
              query,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            query = searchRetrieverResult.query;
 | 
			
		||||
            docs = searchRetrieverResult.docs;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          const sortedDocs = await this.rerankDocs(
 | 
			
		||||
            query,
 | 
			
		||||
            docs ?? [],
 | 
			
		||||
            fileIds,
 | 
			
		||||
            embeddings,
 | 
			
		||||
            optimizationMode,
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
          return sortedDocs;
 | 
			
		||||
        })
 | 
			
		||||
          .withConfig({
 | 
			
		||||
            runName: 'FinalSourceRetriever',
 | 
			
		||||
          })
 | 
			
		||||
          .pipe(this.processDocs),
 | 
			
		||||
      }),
 | 
			
		||||
      ChatPromptTemplate.fromMessages([
 | 
			
		||||
        ['system', this.config.responsePrompt],
 | 
			
		||||
        new MessagesPlaceholder('chat_history'),
 | 
			
		||||
        ['user', '{query}'],
 | 
			
		||||
      ]),
 | 
			
		||||
      llm,
 | 
			
		||||
      this.strParser,
 | 
			
		||||
    ]).withConfig({
 | 
			
		||||
      runName: 'FinalResponseGenerator',
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async rerankDocs(
 | 
			
		||||
    query: string,
 | 
			
		||||
    docs: Document[],
 | 
			
		||||
@@ -432,36 +208,363 @@ class MetaSearchAgent implements MetaSearchAgentType {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async handleStream(
 | 
			
		||||
    stream: AsyncGenerator<StreamEvent, any, any>,
 | 
			
		||||
    stream: AsyncIterable<[BaseMessage, Record<string, any>]>,
 | 
			
		||||
    emitter: eventEmitter,
 | 
			
		||||
  ) {
 | 
			
		||||
    for await (const event of stream) {
 | 
			
		||||
      if (
 | 
			
		||||
        event.event === 'on_chain_end' &&
 | 
			
		||||
        event.name === 'FinalSourceRetriever'
 | 
			
		||||
      ) {
 | 
			
		||||
        ``;
 | 
			
		||||
    for await (const [message, _metadata] of stream) {
 | 
			
		||||
      if (isAIMessage(message) && message.tool_calls?.length) {
 | 
			
		||||
      } else if (isAIMessage(message) && message.content) {
 | 
			
		||||
        emitter.emit(
 | 
			
		||||
          'data',
 | 
			
		||||
          JSON.stringify({ type: 'sources', data: event.data.output }),
 | 
			
		||||
          JSON.stringify({ type: 'response', data: message.content }),
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      if (
 | 
			
		||||
        event.event === 'on_chain_stream' &&
 | 
			
		||||
        event.name === 'FinalResponseGenerator'
 | 
			
		||||
      ) {
 | 
			
		||||
        emitter.emit(
 | 
			
		||||
          'data',
 | 
			
		||||
          JSON.stringify({ type: 'response', data: event.data.chunk }),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
      if (
 | 
			
		||||
        event.event === 'on_chain_end' &&
 | 
			
		||||
        event.name === 'FinalResponseGenerator'
 | 
			
		||||
      ) {
 | 
			
		||||
 | 
			
		||||
    emitter.emit('end');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getTools({
 | 
			
		||||
    llm,
 | 
			
		||||
    emitter,
 | 
			
		||||
  }: {
 | 
			
		||||
    llm: BaseLanguageModel;
 | 
			
		||||
    emitter: EventEmitter;
 | 
			
		||||
  }): DynamicStructuredTool[] {
 | 
			
		||||
    const searchToolInputSchema = z.object({
 | 
			
		||||
      searchMode: z
 | 
			
		||||
        .enum(['normal', 'news'])
 | 
			
		||||
        .describe(
 | 
			
		||||
          'The search mode. If you want latest, live or articles on a topic use the news mode (you also need to use news mode for queries where you think there might be a newswall), otherwise for normal searches use normal mode.',
 | 
			
		||||
        ),
 | 
			
		||||
      query: z.string().describe('The query to search the web for.'),
 | 
			
		||||
      links: z
 | 
			
		||||
        .array(z.string().describe('The link to get data from'))
 | 
			
		||||
        .describe(
 | 
			
		||||
          'A list of links (if shared by user) to generate an answer from.',
 | 
			
		||||
        ),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const searchTool = tool(
 | 
			
		||||
      async (input: any) => {
 | 
			
		||||
        if (input.links.length > 0) {
 | 
			
		||||
          let docs: Document[] = [];
 | 
			
		||||
 | 
			
		||||
          const linkDocs = await getDocumentsFromLinks({ links: input.links });
 | 
			
		||||
 | 
			
		||||
          const docGroups: Document[] = [];
 | 
			
		||||
 | 
			
		||||
          linkDocs.map((doc) => {
 | 
			
		||||
            const URLDocExists = docGroups.find(
 | 
			
		||||
              (d) =>
 | 
			
		||||
                d.metadata.url === doc.metadata.url &&
 | 
			
		||||
                d.metadata.totalDocs < 10,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (!URLDocExists) {
 | 
			
		||||
              docGroups.push({
 | 
			
		||||
                ...doc,
 | 
			
		||||
                metadata: {
 | 
			
		||||
                  ...doc.metadata,
 | 
			
		||||
                  totalDocs: 1,
 | 
			
		||||
                },
 | 
			
		||||
              });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const docIndex = docGroups.findIndex(
 | 
			
		||||
              (d) =>
 | 
			
		||||
                d.metadata.url === doc.metadata.url &&
 | 
			
		||||
                d.metadata.totalDocs < 10,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (docIndex !== -1) {
 | 
			
		||||
              docGroups[docIndex].pageContent =
 | 
			
		||||
                docGroups[docIndex].pageContent + `\n\n` + doc.pageContent;
 | 
			
		||||
              docGroups[docIndex].metadata.totalDocs += 1;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          const URLSourcePrompt = `
 | 
			
		||||
              You are a web search question answerer, tasked with finding relevant information from web documents to answer questions. Your job is to extract and summarize the most relevant parts of a document that can help answer the user's query.
 | 
			
		||||
 | 
			
		||||
              - **Find relevant sections**: Identify parts of the document that directly relate to the question
 | 
			
		||||
              - **Extract key information**: Pull out specific facts, data, or explanations that answer the query
 | 
			
		||||
              - **Summarize concisely**: Provide a focused summary of the relevant information found
 | 
			
		||||
              - **Stay on topic**: Only include information that helps answer the specific question asked
 | 
			
		||||
 | 
			
		||||
              The document text will be shared inside the \`text\` XML tag, and the query inside the \`query\` XML tag.
 | 
			
		||||
 | 
			
		||||
              Extract and summarize the relevant information from the document that answers the query.
 | 
			
		||||
              `;
 | 
			
		||||
 | 
			
		||||
          const URLSourceChatPrompt = ChatPromptTemplate.fromMessages([
 | 
			
		||||
            ['system', URLSourcePrompt],
 | 
			
		||||
            [
 | 
			
		||||
              'human',
 | 
			
		||||
              `
 | 
			
		||||
              <text>
 | 
			
		||||
             Docker is a set of platform-as-a-service products that use OS-level virtualization to deliver software in packages called containers. 
 | 
			
		||||
             It was first released in 2013 and is developed by Docker, Inc. Docker is designed to make it easier to create, deploy, and run applications 
 | 
			
		||||
             by using containers.
 | 
			
		||||
             </text>
 | 
			
		||||
 
 | 
			
		||||
             <query>
 | 
			
		||||
             What is Docker and how does it work?
 | 
			
		||||
             </query>
 | 
			
		||||
              `,
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
              'assistant',
 | 
			
		||||
              `
 | 
			
		||||
                 Docker is a revolutionary platform-as-a-service product developed by Docker, Inc., that uses container technology to make application 
 | 
			
		||||
             deployment more efficient. It allows developers to package their software with all necessary dependencies, making it easier to run in 
 | 
			
		||||
             any environment. Released in 2013, Docker has transformed the way applications are built, deployed, and managed.
 | 
			
		||||
                `,
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
              'human',
 | 
			
		||||
              `
 | 
			
		||||
     <text>
 | 
			
		||||
     Rising global temperatures are causing significant changes to Earth's climate system. Ice sheets in Greenland and Antarctica are melting at accelerated rates, contributing to sea level rise. Ocean temperatures are increasing, leading to coral bleaching events. Weather patterns are becoming more extreme, with increased frequency of hurricanes, droughts, and flooding. The Arctic is warming twice as fast as the global average, a phenomenon known as Arctic amplification.
 | 
			
		||||
     </text>
 | 
			
		||||
 | 
			
		||||
     <query>
 | 
			
		||||
     What are the main effects of climate change on the environment?
 | 
			
		||||
     </query>
 | 
			
		||||
   `,
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
              'assistant',
 | 
			
		||||
              `
 | 
			
		||||
     Climate change is causing accelerated melting of ice sheets in Greenland and Antarctica, leading to sea level rise. Rising ocean temperatures are causing coral bleaching, while weather patterns are becoming more extreme with increased hurricanes, droughts, and flooding. The Arctic is experiencing particularly rapid warming at twice the global average rate.
 | 
			
		||||
   `,
 | 
			
		||||
            ],
 | 
			
		||||
 | 
			
		||||
            [
 | 
			
		||||
              'human',
 | 
			
		||||
              `
 | 
			
		||||
     <text>
 | 
			
		||||
     Pasta is a staple food of Italian cuisine made from wheat flour and water. Common shapes include spaghetti, penne, and fusilli. It can be served with various sauces like marinara, alfredo, or pesto. Pasta cooking involves boiling water with salt and cooking until al dente. Different regions of Italy have their own traditional pasta dishes and preparation methods.
 | 
			
		||||
     </text>
 | 
			
		||||
 | 
			
		||||
     <query>
 | 
			
		||||
     How do solar panels generate electricity?
 | 
			
		||||
     </query>
 | 
			
		||||
   `,
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
              'assistant',
 | 
			
		||||
              `
 | 
			
		||||
     The provided document about pasta and Italian cuisine does not contain information about how solar panels generate electricity. No relevant information found to answer the query.
 | 
			
		||||
   `,
 | 
			
		||||
            ],
 | 
			
		||||
 | 
			
		||||
            [
 | 
			
		||||
              'human',
 | 
			
		||||
              `
 | 
			
		||||
     <text>
 | 
			
		||||
     {content}
 | 
			
		||||
     </text>
 | 
			
		||||
 | 
			
		||||
     <query>
 | 
			
		||||
     {query}
 | 
			
		||||
     </query>
 | 
			
		||||
   `,
 | 
			
		||||
            ],
 | 
			
		||||
          ]);
 | 
			
		||||
 | 
			
		||||
          await Promise.all(
 | 
			
		||||
            docGroups.map(async (doc) => {
 | 
			
		||||
              const formattedPrompt = await URLSourceChatPrompt.formatMessages({
 | 
			
		||||
                query: input.query,
 | 
			
		||||
                content: doc.pageContent,
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              const llmResponse = await llm.invoke(formattedPrompt);
 | 
			
		||||
 | 
			
		||||
              const document = new Document({
 | 
			
		||||
                pageContent: llmResponse.content as string,
 | 
			
		||||
                metadata: {
 | 
			
		||||
                  title: doc.metadata.title,
 | 
			
		||||
                  url: doc.metadata.url,
 | 
			
		||||
                },
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              docs.push(document);
 | 
			
		||||
            }),
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
          emitter.emit('data', JSON.stringify({ type: 'sources', data: docs }));
 | 
			
		||||
 | 
			
		||||
          return this.processDocs(docs);
 | 
			
		||||
        } else {
 | 
			
		||||
          const res = await searchSearxng(input.query, {
 | 
			
		||||
            language: 'en',
 | 
			
		||||
            engines:
 | 
			
		||||
              input.searchMode === 'news'
 | 
			
		||||
                ? ['bing_news']
 | 
			
		||||
                : this.config.activeEngines,
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          const documents = res.results.map(
 | 
			
		||||
            (result) =>
 | 
			
		||||
              new Document({
 | 
			
		||||
                pageContent:
 | 
			
		||||
                  result.content ||
 | 
			
		||||
                  (this.config.activeEngines.includes('youtube')
 | 
			
		||||
                    ? result.title
 | 
			
		||||
                    : '') /* Todo: Implement transcript grabbing using Youtubei (source: https://www.npmjs.com/package/youtubei) */,
 | 
			
		||||
                metadata: {
 | 
			
		||||
                  title: result.title,
 | 
			
		||||
                  url: result.url,
 | 
			
		||||
                  ...(result.img_src && { img_src: result.img_src }),
 | 
			
		||||
                },
 | 
			
		||||
              }),
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
          emitter.emit(
 | 
			
		||||
            'data',
 | 
			
		||||
            JSON.stringify({ type: 'sources', data: documents }),
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
          return this.processDocs(documents);
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        name: 'search_web',
 | 
			
		||||
        schema: searchToolInputSchema,
 | 
			
		||||
        description: 'This tool allows you to search the web for information.',
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const summarizeToolInputSchema = z.object({
 | 
			
		||||
      links: z
 | 
			
		||||
        .array(z.string().describe('The URL to summarize'))
 | 
			
		||||
        .describe('The list of URLs to summarize'),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const summarizeTool = tool(
 | 
			
		||||
      async (input: any) => {
 | 
			
		||||
        if (input.links.length > 0) {
 | 
			
		||||
          let docs: Document[] = [];
 | 
			
		||||
 | 
			
		||||
          const linkDocs = await getDocumentsFromLinks({ links: input.links });
 | 
			
		||||
          const docGroups: Document[] = [];
 | 
			
		||||
 | 
			
		||||
          linkDocs.map((doc) => {
 | 
			
		||||
            const URLDocExists = docGroups.find(
 | 
			
		||||
              (d) =>
 | 
			
		||||
                d.metadata.url === doc.metadata.url &&
 | 
			
		||||
                d.metadata.totalDocs < 10,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (!URLDocExists) {
 | 
			
		||||
              docGroups.push({
 | 
			
		||||
                ...doc,
 | 
			
		||||
                metadata: {
 | 
			
		||||
                  ...doc.metadata,
 | 
			
		||||
                  totalDocs: 1,
 | 
			
		||||
                },
 | 
			
		||||
              });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const docIndex = docGroups.findIndex(
 | 
			
		||||
              (d) =>
 | 
			
		||||
                d.metadata.url === doc.metadata.url &&
 | 
			
		||||
                d.metadata.totalDocs < 10,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (docIndex !== -1) {
 | 
			
		||||
              docGroups[docIndex].pageContent =
 | 
			
		||||
                docGroups[docIndex].pageContent + `\n\n` + doc.pageContent;
 | 
			
		||||
              docGroups[docIndex].metadata.totalDocs += 1;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          const summarizerPrompt = `
 | 
			
		||||
You are a document summarizer for map-reduce processing of website content. Extract all factual information, data, and key concepts from document chunks into concise paragraph summaries.
 | 
			
		||||
 | 
			
		||||
**Requirements:**
 | 
			
		||||
- **Extract facts only**: Include concrete information, data, numbers, dates, definitions, and explanations
 | 
			
		||||
- **Ignore fluff**: Skip opinions, filler words, casual language, and non-essential content
 | 
			
		||||
- **Be concise**: Create summaries shorter than the original content
 | 
			
		||||
- **Paragraph format**: Write in plain paragraph form, no markdown, bullet points, or formatting
 | 
			
		||||
- **Preserve specifics**: Keep exact numbers, dates, names, and technical terms
 | 
			
		||||
 | 
			
		||||
The document text will be provided inside the \`text\` XML tag. Create a factual paragraph summary.
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
          const summarizerChatPrompt = ChatPromptTemplate.fromMessages([
 | 
			
		||||
            ['system', summarizerPrompt],
 | 
			
		||||
            [
 | 
			
		||||
              'human',
 | 
			
		||||
              `
 | 
			
		||||
    <text>
 | 
			
		||||
    Docker is a platform-as-a-service product developed by Docker, Inc. and released in 2013 that uses OS-level virtualization to deliver software in containers. Containers are lightweight, portable packages that include application code, runtime, system tools, libraries, and settings.
 | 
			
		||||
    </text>
 | 
			
		||||
    `,
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
              'assistant',
 | 
			
		||||
              `Docker is a platform-as-a-service product developed by Docker, Inc. in 2013 that uses OS-level virtualization to deliver software in containers. Containers are lightweight, portable packages containing application code, runtime, system tools, libraries, and settings.`,
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
              'human',
 | 
			
		||||
              `
 | 
			
		||||
    <text>
 | 
			
		||||
    Hey there! So like, I was totally thinking about pasta the other day, you know? It's super amazing how there are different shapes. Spaghetti is long and thin, penne has tube shapes, and fusilli is all twisty! Haha, I just love Italian creativity with food.
 | 
			
		||||
    </text>
 | 
			
		||||
    `,
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
              'assistant',
 | 
			
		||||
              `Pasta comes in various shapes including spaghetti which is long and thin, penne which has tube shapes, and fusilli which has a twisted form. These are Italian food products.`,
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
              'human',
 | 
			
		||||
              `
 | 
			
		||||
    <text>
 | 
			
		||||
    {content}
 | 
			
		||||
    </text>
 | 
			
		||||
    `,
 | 
			
		||||
            ],
 | 
			
		||||
          ]);
 | 
			
		||||
 | 
			
		||||
          await Promise.all(
 | 
			
		||||
            docGroups.map(async (doc) => {
 | 
			
		||||
              const formattedPrompt = await summarizerChatPrompt.formatMessages(
 | 
			
		||||
                {
 | 
			
		||||
                  content: doc.pageContent,
 | 
			
		||||
                },
 | 
			
		||||
              );
 | 
			
		||||
 | 
			
		||||
              const llmResponse = await llm.invoke(formattedPrompt);
 | 
			
		||||
 | 
			
		||||
              const document = new Document({
 | 
			
		||||
                pageContent: llmResponse.content as string,
 | 
			
		||||
                metadata: {
 | 
			
		||||
                  title: doc.metadata.title,
 | 
			
		||||
                  url: doc.metadata.url,
 | 
			
		||||
                },
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              docs.push(document);
 | 
			
		||||
            }),
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
          emitter.emit('data', JSON.stringify({ type: 'sources', data: docs }));
 | 
			
		||||
 | 
			
		||||
          return this.processDocs(docs);
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        name: 'summarize',
 | 
			
		||||
        description: 'This tool can be used to summarize URL(s)',
 | 
			
		||||
        schema: summarizeToolInputSchema,
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    return [searchTool, summarizeTool];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async searchAndAnswer(
 | 
			
		||||
@@ -475,21 +578,94 @@ class MetaSearchAgent implements MetaSearchAgentType {
 | 
			
		||||
  ) {
 | 
			
		||||
    const emitter = new eventEmitter();
 | 
			
		||||
 | 
			
		||||
    const answeringChain = await this.createAnsweringChain(
 | 
			
		||||
    const tools = this.getTools({
 | 
			
		||||
      emitter,
 | 
			
		||||
      llm,
 | 
			
		||||
      fileIds,
 | 
			
		||||
      embeddings,
 | 
			
		||||
      optimizationMode,
 | 
			
		||||
      systemInstructions,
 | 
			
		||||
    );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const stream = answeringChain.streamEvents(
 | 
			
		||||
    const shouldContinue = (state: typeof MessagesAnnotation.State) => {
 | 
			
		||||
      const lastMessage = state.messages[
 | 
			
		||||
        state.messages.length - 1
 | 
			
		||||
      ] as AIMessage;
 | 
			
		||||
 | 
			
		||||
      if (lastMessage.tool_calls && lastMessage.tool_calls.length) {
 | 
			
		||||
        return 'tools';
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return '__end__';
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const callTools = async (
 | 
			
		||||
      state: typeof MessagesAnnotation.State,
 | 
			
		||||
    ): Promise<Partial<typeof MessagesAnnotation.State>> => {
 | 
			
		||||
      const lastMessage = state.messages[
 | 
			
		||||
        state.messages.length - 1
 | 
			
		||||
      ] as AIMessage;
 | 
			
		||||
 | 
			
		||||
      const toolResults: BaseMessage[] = [];
 | 
			
		||||
 | 
			
		||||
      if (lastMessage.tool_calls && lastMessage.tool_calls.length) {
 | 
			
		||||
        await Promise.all(
 | 
			
		||||
          lastMessage.tool_calls.map(async (t) => {
 | 
			
		||||
            const toolToCall = tools.find((i) => i.name === t.name);
 | 
			
		||||
 | 
			
		||||
            const result = await toolToCall?.invoke(t.args)!;
 | 
			
		||||
 | 
			
		||||
            toolResults.push(
 | 
			
		||||
              new ToolMessage({
 | 
			
		||||
                content: result,
 | 
			
		||||
                tool_call_id: t.id!,
 | 
			
		||||
              }),
 | 
			
		||||
            );
 | 
			
		||||
          }),
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        messages: [...toolResults],
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const boundModel = llm.bindTools?.(tools)!;
 | 
			
		||||
 | 
			
		||||
    const callModel = async (
 | 
			
		||||
      state: typeof MessagesAnnotation.State,
 | 
			
		||||
    ): Promise<Partial<typeof MessagesAnnotation.State>> => {
 | 
			
		||||
      const { messages } = state;
 | 
			
		||||
      const res = await boundModel?.invoke(messages);
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        messages: [res!],
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const workflow = new StateGraph(MessagesAnnotation)
 | 
			
		||||
      .addNode('agent', callModel)
 | 
			
		||||
      .addNode(
 | 
			
		||||
        'tools',
 | 
			
		||||
        RunnableLambda.from(callTools).withConfig({
 | 
			
		||||
          tags: ['nostream'],
 | 
			
		||||
        }),
 | 
			
		||||
      )
 | 
			
		||||
      .addEdge('__start__', 'agent')
 | 
			
		||||
      .addEdge('tools', 'agent')
 | 
			
		||||
      .addConditionalEdges('agent', shouldContinue);
 | 
			
		||||
 | 
			
		||||
    const app = workflow.compile();
 | 
			
		||||
 | 
			
		||||
    const filledPrompt = await PromptTemplate.fromTemplate(
 | 
			
		||||
      this.config.responsePrompt,
 | 
			
		||||
    ).format({
 | 
			
		||||
      systemInstructions: systemInstructions,
 | 
			
		||||
      date: Date.now(),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const stream = await app.stream(
 | 
			
		||||
      {
 | 
			
		||||
        chat_history: history,
 | 
			
		||||
        query: message,
 | 
			
		||||
        messages: [['system', filledPrompt], ...history, ['human', message]],
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        version: 'v1',
 | 
			
		||||
        streamMode: 'messages',
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ export const getDocumentsFromLinks = async ({ links }: { links: string[] }) => {
 | 
			
		||||
        const splittedText = await splitter.splitText(parsedText);
 | 
			
		||||
        const title = res.data
 | 
			
		||||
          .toString('utf8')
 | 
			
		||||
          .match(/<title>(.*?)<\/title>/)?.[1];
 | 
			
		||||
          .match(/<title.*>(.*?)<\/title>/)?.[1];
 | 
			
		||||
 | 
			
		||||
        const linkDocs = splittedText.map((text) => {
 | 
			
		||||
          return new Document({
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,11 @@
 | 
			
		||||
import { BaseMessage } from '@langchain/core/messages';
 | 
			
		||||
import { BaseMessage, isAIMessage } from '@langchain/core/messages';
 | 
			
		||||
 | 
			
		||||
const formatChatHistoryAsString = (history: BaseMessage[]) => {
 | 
			
		||||
  return history
 | 
			
		||||
    .map((message) => `${message._getType()}: ${message.content}`)
 | 
			
		||||
    .map(
 | 
			
		||||
      (message) =>
 | 
			
		||||
        `${isAIMessage(message) ? 'AI' : 'User'}: ${message.content}`,
 | 
			
		||||
    )
 | 
			
		||||
    .join('\n');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||