This commit is contained in:
a-ill
2023-06-14 21:41:54 +03:00
parent 4d034eba7d
commit 9e8ee05bb6
128 changed files with 12242 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>$(vars(:title))</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta property="og:title" content="$(vars(:title))">
<meta property="og:description" content="$(vars(:description))">
<meta property="og:type" content="website">
<meta property="og:image" content="">
<meta property="og:url" content="">
<!--Load libraries-->
<!--Load fonts-->
<!--Load CSS-->
<!--Load components-->
</head>
<body>
<!--<loadscreen-component></loadscreen-component>-->
<div id="content">
<navbar-component></navbar-component>
<%@yield%>
<footer-component></footer-component>
</div>
</body>
</html>

View File

View File

@@ -0,0 +1,24 @@
module BasicController
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests
using JSON3
using SearchLight
using Server.DatabaseSupport, Server.TemplateEditor
controller = "basic"
dict_layouts = Dict(
:landing => generate_layout_html("main",controller,"landing",css=["landing"]),
)
#---General-----------------------------------------------------
function landing()
html(:basic,:landing, layout = dict_layouts[:landing], context = @__MODULE__,
title = "LibSoc",
description = ""
)
end
end

View File

@@ -0,0 +1 @@
<landing-component></landing-component>

4
Server/app/svelte/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/node_modules/
/public/build/
.DS_Store

107
Server/app/svelte/README.md Normal file
View File

@@ -0,0 +1,107 @@
# This repo is no longer maintained. Consider using `npm init vite` and selecting the `svelte` option or — if you want a full-fledged app framework and don't mind using pre-1.0 software — use [SvelteKit](https://kit.svelte.dev), the official application framework for Svelte.
---
# svelte app
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
```bash
npx degit sveltejs/template svelte-app
cd svelte-app
```
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
## Get started
Install the dependencies...
```bash
cd svelte-app
npm install
```
...then start [Rollup](https://rollupjs.org):
```bash
npm run dev
```
Navigate to [localhost:8080](http://localhost:8080). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
## Building and running in production mode
To create an optimised version of the app:
```bash
npm run build
```
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
## Single-page app mode
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
```js
"start": "sirv public --single"
```
## Using TypeScript
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
```bash
node scripts/setupTypeScript.js
```
Or remove the script via:
```bash
rm scripts/setupTypeScript.js
```
If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte).
## Deploying to the web
### With [Vercel](https://vercel.com)
Install `vercel` if you haven't already:
```bash
npm install -g vercel
```
Then, from within your project folder:
```bash
cd public
vercel deploy --name my-project
```
### With [surge](https://surge.sh/)
Install `surge` if you haven't already:
```bash
npm install -g surge
```
Then, from within your project folder:
```bash
npm run build
surge public my-project.surge.sh
```

2674
Server/app/svelte/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
{
"name": "svelte-app",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public --no-clear"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.0.0",
"rollup": "^2.3.4",
"rollup-plugin-cleaner": "^1.0.0",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0",
"rollup-plugin-watch": "^1.0.2",
"svelte": "^3.0.0",
"walk-sync": "^3.0.0"
},
"dependencies": {
"sirv-cli": "^2.0.0"
}
}

View File

@@ -0,0 +1,532 @@
:root {
--light-blue:hsl(195, 67%, 95%);
--darker-pink:hsl(344, 60%, 47%);
--pink:hsl(344, 73%, 57%);
--dark-green:hsl(176, 63%, 25%);
--green:hsl(147, 33%, 60%);
--orange:hsl(30, 97%, 72%);
--light-orange: hsl(19, 76%, 72%);
--dark-brown:hsl(23, 47%, 20%);
--brown:hsl(23, 47%, 30%);
--light-brown: hsl(23, 47%, 50%);
--dark-pink:hsl(343, 39%, 16%);
--red:hsl(359, 72%, 61%);
--dark-blue:hsl(217, 25%, 16%);
--grey-blue:hsl(223, 13%, 22%);
--cream:hsl(34, 43%, 90%);
--dark-cream:hsl(33, 26%, 84%);
--sans-serif: "Space Grotesk";
--serif: "DejaVu";
}
svg {
width: auto;
height: auto;
}
:not(svg *) {
margin: 0;
padding: 0;
box-sizing: border-box;
border: none;
font-size: 0;
}
html {
overflow-x: hidden;
font-size: 16px;
}
body {
position: relative;
min-height: 100vh;
max-width: 100vw;
overflow: hidden;
background: white;
}
#content {
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
min-height: 100vh;
flex-grow: 1;
}
/*---Fonts---------------------------------------------------------*/
@font-face {
font-family: 'Space Grotesk';
font-weight: 400;
font-style: normal;
font-display: swap;
src: /*local('Space Grotesk Light'),
local('SpaceGroteskLight-Regular'),
local('Space Grotesk Light Regular'), */
url('/fonts/SpaceGrotesk/SpaceGrotesk.woff2') format('woff2'),
url('/fonts/SpaceGrotesk/SpaceGrotesk.woff') format('woff');
}
@font-face {
font-family: 'DejaVu';
font-weight: 400;
font-style: normal;
font-display: swap;
src: /*local('DejaVuLGCSerif'),
local('DejaVu LGC Serif'), */
url('/fonts/DejaVu/DejaVuLGCSerif.woff2') format('woff2'),
url('/fonts/DejaVu/DejaVuLGCSerif.woff') format('woff');
}
.serif {
font-family: var(--serif)
}
.sans-serif {
font-family: var(--sans-serif)
}
/*---Text related------------------------------------------------------------------------------*/
b {
font-family: inherit;
font-size: inherit;
}
h1 {
font-family: var(--sans-serif, sans-serif);
}
h2 {
font-size: 2rem;
font-family: var(--sans-serif, sans-serif);
font-weight: bold;
}
h3 {
font-family: var(--sans-serif, sans-serif);
font-size: 1.6rem
}
h4 {
font-family: var(--sans-serif, sans-serif);
font-size: 1.4rem
}
span {
font-family: var(--serif, serif);
font-size: 1.3rem;
height: auto;
width: auto;
}
p {
font-family: var(--serif, serif);
font-size: 1.2rem;
line-height: 170%;
}
b,i,s {
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
label {
font-family: var(--serif, serif);
font-size: 1.2rem;
}
sup {
vertical-align: top;
position: relative;
top: -0.682rem;
}
sub {
vertical-align: top;
position: relative;
top: 0.34rem;
}
a {
font-family: var(--serif, serif);
font-size: 1.638rem;
color: black;
}
a:link { text-decoration: none; }
a:visited { text-decoration: none; }
a:hover { text-decoration: none; }
a:active { text-decoration: none; }
a:focus { text-decoration: none; }
.justify {
text-align: justify;
}
.center {
width: 100%;
margin-left: auto;
margin-right: auto;
text-align: center;
}
.left {
text-align: left;
}
.bold {
font-weight: bold;
}
.margin-end {
margin-bottom: 1rem;
}
.margin-end2 {
margin-bottom: 2rem;
}
.text p, .text li {
font-size: 1.2rem;
font-family: var(--serif);
line-height: 170%;
}
.text li {
margin-left: 1.5rem;
margin-bottom: 0.5rem;
line-height: 140%;
}
.text ul p {
margin-bottom: 0.25rem;
}
.text h2 {
width: max-content;
position: relative;
text-align: center;
margin: auto;
margin-bottom: 1rem;
}
.title-highlight {
position: relative;
}
.title-highlight::before {
position: absolute;
margin-left: -0.68rem;
margin-top: -0.14rem;
width: 2.5rem;
height: 0rem;
content: "";
border-left: 0.19rem solid var(--pink);
border-top: 0.19rem solid var(--pink);
border-radius: 1rem;
}
.title-highlight::after {
position: absolute;
left:0;
top: 0;
margin-left: -0.68rem;
margin-top: -0.14rem;
width: 0rem;
height: 1.7rem;
content: "";
border-left: 0.19rem solid var(--pink);
border-top: 0.19rem solid var(--pink);
border-radius: 1rem;
}
.text h3 {
margin-top: 1rem;
margin-bottom: 0.5rem;
}
.text h4 {
margin-bottom: 0.5rem;
}
.text p {
margin-bottom: 1rem;
}
.text ul>ul>li {
margin-left: 2.5rem;
margin-bottom: 0.5rem;
line-height: 140%;
}
/*---Button/input related--------------------------------------------------------------*/
button {
cursor: pointer;
}
button {
background: transparent;
}
button:focus {
outline:0;
}
input[type="text"],input[type="email"],input[type="password"],input[type="number"] {
font-family: var(--serif, serif);
background-color: white;
border-radius: 0.4rem;
border-color: black;
border: black solid 0.063rem;
padding-left: 0.5rem;
font: 1.3rem var(--serif, serif);
}
input[type="text"] {
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
color: #353535;
}
input[type="email"] {
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
font-weight: normal;
color: #353535;
height: 2.7rem;
padding-left: 0.34rem;
}
input[type="password"] {
padding-left: 0.34rem;
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
font-weight: normal;
color: #353535;
}
input[type="number"] {
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
color: #353535;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
}
/*---Scroll button---------------------------------------------------------------------*/
.scroll-button {
cursor: pointer;
background-color: #EBF7FB;
border-color: #EBF7FB;
height: 3.822rem;
width: 3.822rem;
border-radius: 3.822rem;
border: 0;
margin: 0;
padding-top: 0.505rem;
}
.scroll-button img {
width: 1.9rem;
padding-bottom: 0.4rem;
height: auto;
}
.next {
padding-left: 0.382rem;
}
.prev {
padding-right: 0.382rem;
}
/*---Grid related----------------------------------------------------------------------*/
.column {
display: grid;
grid-auto-flow: column
}
.center-items {
display: flex;
justify-content: center;
}
/*---Fillers-------------------------------------------------------------------------*/
.filler1 {
width: 100%;
height: 0.655rem;
display: inline-block;
}
.filler2 {
width: 100%;
height: 1.263rem;
display: inline-block;
}
.filler3 {
width: 100%;
height: 2.525rem;
display: inline-block;
}
.filler4 {
width: 100%;
height: 3.822rem;
display: inline-block;
}
.filler5 {
width: 100%;
height: 5.05rem;
display: inline-block;
}
.filler6 {
width: 100%;
height: 6.347rem;
display: inline-block;
}
/*---Margins------------------------------------------------------------------------*/
.bmargin1 {
margin-bottom: 0.5rem
}
.bmargin2 {
margin-bottom: 1rem
}
.bmargin3 {
margin-bottom: 1.5rem
}
.tmargin1 {
margin-top: 0.5rem
}
.tmargin2 {
margin-top: 1rem
}
.tmargin3 {
margin-top: 1.5rem
}
/*---Other-------------------------------------------------------------------------*/
.flex-column {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.flex-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.pane {
background: white;
border: 0;
border-radius: 0.635rem;
box-shadow: 0 0 0.314rem rgb(187, 187, 187);
}
.pane-container {
margin-top: min(3vw, 1rem);
margin-bottom: 3.1rem;
display: grid;
grid-auto-flow: column;
column-gap: 5rem;
}
.pane-centering {
display: flex;
justify-content: center;
}
.main-pane {
position: relative;
margin: auto;
height: min-content;
max-width: 66rem;
width: 66rem;
z-index: 1;
}
.clicked {
background-color: hsla(344, 73%, 57%, 0.25);
}
@media only screen and (max-width: 1117px) {
.main-pane {
width: 100%;
}
}
/*---Scaling-----------------------------------------------------------------------*/
html {
font-size: 16px;
}
@media only screen and (max-width: 660px) {
html {
font-size: 14px;
}
}
@media only screen and (max-width: 570px) {
html {
font-size: 12px;
}
}
@media only screen and (max-width: 470px) {
html {
font-size: 11px;
}
}
@media only screen and (max-width: 400px) {
html {
font-size: 10px;
}
}
@media only screen and (max-width: 360px) {
html {
font-size: 9px;
}
}

View File

@@ -0,0 +1,177 @@
/*---Footer----------------------------------------------------*/
footer {
position: relative;
bottom: 0;
width: 100%;
height: auto;
background: var(--dark-green);
}
footer p, footer a {
font-family: var(--sans-serif);
}
#footer-content-container {
position: relative;
margin: auto;
padding-top: 2rem;
max-width: 116rem;
width: 97vw;
}
#footer-grid-content-container {
display: grid;
margin-left: 2rem;
margin-right: 2rem;
margin-bottom: 1.4rem;
}
.not-logged {
grid-template-columns: auto auto auto 2rem;
}
.logged {
grid-template-columns: auto auto 2rem;
}
footer h2 {
color: #ffffff;
font-size: 1.4rem;
margin-bottom: 0.5rem;
}
#footer-copyright {
position: relative;
color: #ffffff;
margin-left: 2rem;
bottom: 0rem;
font-weight: 400;
font-size: 1.2rem;
height: 3rem;
top: 0rem;
margin-bottom: 0;
}
footer a {
font-size: 1.2rem;
color: #d8d8d8;
}
footer p, footer label {
display: block;
font-size: 1.2rem;
color: #d8d8d8;
font-family: var(--sans-serif,sans-serif);
margin-bottom: 0.5rem;
}
#newsletter-container h3 {
margin-bottom: 0.99rem;
}
#newsletter-container p {
width: 28.665rem;
margin-bottom: 0.48rem;
}
#newsletterEmailInput {
height: 2.5rem;
width: 20.5rem;
border: 0;
border-radius: 0.4rem 0 0 0.4rem;
filter: drop-shadow( 0.07rem 0.14rem 0.07rem rgb(0 0 0 / 0.4));
}
#newsletterEmailInput::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
color: var(--c,gray);
opacity: 1; /* Firefox */
}
#newsletterEmailButton {
position: absolute;
width: 6.8rem;
height: 2.5rem;
background: var(--pink);
color: #ffffff;
font-family: var(--sans-serif,sans-serif);
font-size: 1.4rem;
border-radius: 0 0.2rem 0.2rem 0;
filter: drop-shadow( 0.07rem 0.14rem 0.07rem rgb(0 0 0 / 0.4));
}
#newsletterEmailButton:active {
background: var(--darker-pink);
}
#contact-us-container {
width: 14rem;
}
#contact-us-container h3 {
margin-bottom: 0.99rem;
}
#legal-info-container {
width: 9.6rem;
}
#legal-info-container h3 {
margin-bottom: 0.99rem;
}
#legal-info-container p {
margin-bottom: 0.48rem;
}
#legal-info-container a {
display: block;
margin-bottom: 0.48rem;
}
#footer-up {
position: absolute;
width: 4.8rem;
height: 4.8rem;
border-radius: 3.4rem;
top: 4rem;
right: 2rem;
background: #ffffff;
}
#footer-up svg {
width: 40%;
height: auto;
}
.grass{
position: absolute;
top: -3.8rem;
--height: 3.82rem;
filter: drop-shadow( 0.07rem 0.14rem 0.07rem rgb(0 0 0 / 0.4));
z-index: -1;
}
@media only screen and (max-width: 1170px) {
.not-logged {
grid-template-rows: auto auto auto auto;
grid-template-columns: auto;
row-gap: 2rem;
}
.logged {
grid-template-rows: auto auto auto;
grid-template-columns: auto;
row-gap: 2rem;
}
#footer-copyright {
height: 1rem;
top: -2rem;
}
#newsletterEmailInput {
width: 18rem;
}
}

View File

View File

@@ -0,0 +1,200 @@
/* Header */
#navbar{
position: relative;
top: 0;
width: min(100%,116rem);
z-index: 1000;
height: 5.26rem;
}
#navbar * {
font-family: var(--sans-serif, sans-serif);
}
/* Logo */
#logo-container {
display: flex;
position: absolute;
margin-left: 1rem;
height: 100%;
max-height: 5.26rem;
color: black;
z-index: 1;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
}
#navbar-logo {
width: 3.16rem;
object-fit: contain;
}
#navbar-logo-text {
position: relative;
width: auto;
height: 100%;
line-height: 400%;
white-space: nowrap;
text-align: center;
font-size: 1.4rem;
color: #292222;
font-family: var(--sans-serif, sans-serif);
font-weight: 400;
padding-left: 1.2rem;
}
/* Nav menu */
#nav {
position: fixed;
width: 100%;
height: 100%;
background-color: white;
overflow: hidden;
z-index: 0;
}
#menu a{
display: block;
padding: 1.9rem;
color: black;
font-size: 1.4rem;
}
#menu a:hover {
background-color: rgb(220, 220, 220);
}
#menu a:active{
background-color: #f7aec0;
}
#nav{
max-height: 0;
/*transition: max-height .5s ease-out;*/
}
/* Menu Icon */
#hamb{
position: absolute;
cursor: pointer;
right: 0rem;
padding: 2.8rem 2rem;
z-index: 9999;
}/* Style label tag */
#hamb-line {
background: black;
display: block;
height: 2px;
position: relative;
width: 24px;
} /* Style span tag */
#hamb-line::before,
#hamb-line::after{
background: black;
content: '';
display: block;
height: 100%;
position: absolute;
transition: all .2s ease-out;
width: 100%;
}
#hamb-line::before{
top: 5px;
}
#hamb-line::after{
top: -5px;
}
#side-menu {
display: none;
} /* Hide checkbox */
/* Toggle menu icon */
#side-menu:checked ~ nav {
display: block;
max-height: 100%;
padding-top: 5.625rem;
}
#side-menu:checked ~ #logo-container {
position: fixed;
}
#side-menu:checked ~ #hamb {
position: fixed;
}
#side-menu:checked ~ #hamb #hamb-line {
background: transparent;
}
#side-menu:checked ~ #hamb #hamb-line::before {
transform: rotate(-45deg);
top:0;
}
#side-menu:checked ~ #hamb #hamb-line::after {
transform: rotate(45deg);
top:0;
}
#cart-icon {
height: 1.8rem;
pointer-events: none;
}
#menu a:hover div {
filter: saturate(50%) brightness(140%);
}
#menu a:hover svg {
stroke: rgb(127, 127, 127);;
}
#cart-counter {
position: relative;
top: -2.8rem;
left: 1.6rem;
width: 1.3rem;
height: 1.3rem;
border-radius: 3.4rem;
font-family: var(--sans-serif, sans-serif);
font-size: 1rem;
text-align: center;
color: white;
background: var(--pink);
}
/* Responsiveness */
@media only screen and (min-width: 1500px) {
#navbar{
left: 50%;
-ms-transform: translateX(-50%);
transform: translateX(-50%);
}
#nav{
max-height: none;
top: 0;
position: relative;
float: right;
width: fit-content;
background-color: transparent;
}
#menu li{
float: left;
}
#menu a:hover{
background-color: transparent;
color: rgb(127, 127, 127);
}
#hamb{
display: none;
}
}

View File

@@ -0,0 +1,35 @@
export default class CssTools {
static applyCSS(element,id,outerclass,classlisthint) {
// Return if no CSS to apply
if (classlisthint==null || (outerclass==null && id==null)) {
return
}
let outerClassNames = outerclass.split(" ").map(x => "."+x)
let outerCssSelectors = [...outerClassNames,"#"+id]
let styleSheets = document.styleSheets
let l = styleSheets.length
for (let i=0; i<l; i++) {
let sheet = styleSheets[i]
let name = sheet.href.split("/").at(-1).split(".")[0]
if (name===classlisthint) {
for (let outerCss of outerCssSelectors) {
for (let rule of sheet.cssRules) {
if (rule.selectorText==outerCss) {
let styleRule = rule.style
let vals = Object.values(styleRule)
for (let val of vals) {
element.style[val] = styleRule[val]
}
}
}
}
break
}
}
}
}

View File

@@ -0,0 +1,146 @@
// Broadcast array on array
export function bAr(fun,ar1,ar2) {
var result = new Array(ar1.length)
for (var i = 0;i<ar1.length;i++) {
result[i] = fun(ar1[i],ar2[i])
}
return(result)
}
// Broadcast array on a number
export function b(fun,ar1,val) {
var result = new Array(ar1.length)
for (var i = 0;i<ar1.length;i++) {
result[i] = fun(ar1[i],val)
}
return(result)
}
// Broadcast array on a function
export function bFun(fun,ar1) {
var result = new Array(ar1.length)
for (var i = 0;i<ar1.length;i++) {
result[i] = fun(ar1[i])
}
return(result)
}
export function multiply(num1, num2) {
let result = num1 * num2;
return result;
}
export function sum(ar) {
return ar.reduce((a, b) => a + b, 0)
}
export function prod(ar) {
return ar.reduce((a, b) => a * b, 1)
}
export function mean(ar) {
return ar.reduce((a, b) => a + b, 0)/ar.length
}
export function median(values){
if(values.length ===0) throw new Error("No inputs");
values.sort(function(a,b){
return a-b;
});
var half = Math.floor(values.length / 2);
if (values.length % 2)
return values[half];
return (values[half - 1] + values[half]) / 2.0;
}
export function range(start,end, step = start<end ? 1 : -1) {
var arr = []
if (step>0) {
for (var i = start; i <= end; i += step) {
arr.push(i)
}
}
else {
for (var i = start; i >= end; i += step) {
arr.push(i)
}
}
return arr
}
export function numericallyIntegrate(f, a, b, dx) {
// calculate the number of trapezoids
let n = (b - a) / dx
// define the variable for area
let Area = 0
//loop to calculate the area of each trapezoid and sum.
for (let i = 1; i <= n; i++) {
//the x locations of the left and right side of each trapezpoid
let x0 = a + (i-1)*dx
let x1 = a + i*dx
// the area of each trapezoid
let Ai = dx * (f(x0) + f(x1))/ 2.
// cumulatively sum the areas
Area = Area + Ai
}
return Area
}
const randomNormals = () => {
let u1 = 0, u2 = 0;
//Convert [0,1) to (0,1)
while (u1 === 0) u1 = Math.random();
while (u2 === 0) u2 = Math.random();
const R = Math.sqrt(-2.0 * Math.log(u1));
const Θ = 2.0 * Math.PI * u2;
return [R * Math.cos(Θ), R * Math.sin(Θ)];
};
export function randomSkewNormal(ξ, ω, α = 0) {
const [u0, v] = randomNormals();
if (α === 0) {
return ξ + ω * u0;
}
const 𝛿 = α / Math.sqrt(1 + α * α);
const u1 = 𝛿 * u0 + Math.sqrt(1 - 𝛿 * 𝛿) * v;
const z = u0 >= 0 ? u1 : -u1;
return ξ + ω * z;
};
export function percentile(arr, p) {
arr.sort(function(a,b){
return a-b;
});
if (arr.length === 0) return 0;
if (typeof p !== 'number') throw new TypeError('p must be a number');
if (p <= 0) return arr[0];
if (p >= 1) return arr[arr.length - 1];
var index = (arr.length - 1) * p,
lower = Math.floor(index),
upper = lower + 1,
weight = index % 1;
if (upper >= arr.length) return arr[lower];
return arr[lower] * (1 - weight) + arr[upper] * weight;
}
export function smooth(ar,window) {
let windowHalf = window/2
let windowHalf1 = Math.floor(windowHalf)
let windowHalf2 = Math.ceil(windowHalf)
for (let i=windowHalf1;i<ar.length-windowHalf2;i++) {
ar[i] = mean(ar.slice(i-windowHalf1,i+windowHalf2))
}
}

View File

@@ -0,0 +1,112 @@
export function isObject(v) {
return typeof v === 'object' && !Array.isArray(v) && v !== null
}
// Prevents excessive function calling
export function debounce(func, timeout){
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => { func.apply(this, args); }, timeout)
}
}
export function svgFromObject(object) {
var objectDoc = object.contentDocument;
var svgItem = objectDoc.querySelector("path");
return svgItem
}
export function rem2px(rem) {
let fontSizeString = window.getComputedStyle(document.getElementsByTagName("html")[0]).getPropertyValue('font-size')
let fontSize = parseFloat(fontSizeString.substring(0,fontSizeString.length-2))
return fontSize * rem
}
export function px2rem(px) {
let fontSizeString = window.getComputedStyle(document.getElementsByTagName("html")[0]).getPropertyValue('font-size')
let fontSize = parseFloat(fontSizeString.substring(0,fontSizeString.length-2))
return px / fontSize
}
/**
* Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
*
* @param {String} text The text to be rendered.
* @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
*
* @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393
*/
export function getTextWidth(text, font) {
// re-use canvas object for better performance
const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
const context = canvas.getContext("2d");
context.font = font;
const metrics = context.measureText(text);
return metrics.width;
}
function getCssStyle(element, prop) {
return window.getComputedStyle(element, null).getPropertyValue(prop);
}
export function getCanvasFont(el = document.body) {
const fontWeight = getCssStyle(el, 'font-weight') || 'normal';
const fontSize = getCssStyle(el, 'font-size') || '16px';
const fontFamily = getCssStyle(el, 'font-family') || 'Times New Roman';
return `${fontWeight} ${fontSize} ${fontFamily}`;
}
export function validateAge(event,input,callback) {
event.returnValue = false
var key
if (event.type === 'paste') {
key = event.clipboardData.getData('text/plain');
}
else {
// Handle key press
key = event.keyCode || event.which;
key = String.fromCharCode(key);
}
let keys = ["0","1","2","3","4","5","6","7","8","9"]
if (key in keys) {
var val = parseFloat(input.value)
if (val>120) {
input.value = 120
}
else {
input.value = val
}
if (callback!=undefined) {
callback(input.value)
}
}
}
export function validatePosNumber(event,input,callback,max) {
event.returnValue = false
var key
if (event.type === 'paste') {
key = event.clipboardData.getData('text/plain');
}
else {
// Handle key press
key = event.data;
}
let keys = ["0","1","2","3","4","5","6","7","8","9"]
if (key in keys) {
var val = parseFloat(input.value)
if (val>max) {
input.value = max
}
if (callback!=undefined) {
callback(input.value)
}
}
else {
callback(input.value)
}
}

View File

@@ -0,0 +1,64 @@
// Get data from server
export function getData(path,callback) {
var xhr = new XMLHttpRequest();
xhr.overrideMimeType("application/json");
xhr.open('GET', path, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == "200") {
if (callback !== undefined) {
callback(xhr.responseText);
}
}
};
xhr.send(null);
}
// Parse JSON from given path into a given variable under a given key
export function getJSON(variable,key,path) {
getData(path,function(response) {
// Parse JSON string into object
variable[key] = JSON.parse(response);
});
}
export function sendData(route,data,callback) {
var xhr = new XMLHttpRequest();
xhr.open("POST", route, true)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE) {
var status = xhr.status;
if (status === 0 || (status >= 200 && status < 400)) {
// The request has been completed successfully
if (callback !== undefined) {
callback(xhr.responseText)
}
} else {
// Oh no! There has been an error with the request!
}
}
};
xhr.send(JSON.stringify(data))
}
export function sendText(route,data,callback) {
var xhr = new XMLHttpRequest();
xhr.open("POST", route, true)
xhr.setRequestHeader('Content-Type', 'text/plain')
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE) {
var status = xhr.status;
if (status === 0 || (status >= 200 && status < 400)) {
// The request has been completed successfully
if (callback !== undefined) {
callback(xhr.responseText)
}
} else {
// Oh no! There has been an error with the request!
}
}
};
xhr.send(data)
}

View File

@@ -0,0 +1,97 @@
import svelte from 'rollup-plugin-svelte';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import css from 'rollup-plugin-css-only';
import cleaner from 'rollup-plugin-cleaner';
import copy from 'rollup-plugin-copy';
import watch from "rollup-plugin-watch";
const production = !process.env.ROLLUP_WATCH;
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
return {
writeBundle() {
if (server) return;
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
process.on('SIGTERM', toExit);
process.on('exit', toExit);
}
};
}
const walkSync = require("walk-sync");
const paths = walkSync("./src", {globs: ["**/*.svelte"]}).map(x => "src/"+x)
export default {
input: paths,
output: {
format: "esm",
dir: "../../public/js/components",
},
plugins: [
svelte({
compilerOptions: {
// enable run-time checks when not in production
dev: !production,
customElement: true,
}
}),
// we'll extract any component CSS out into
// a separate file - better for performance
css({ output: 'bundle.css' }),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
watch({ dir: 'public' }),
cleaner({
targets: [
'../../../public/js/components'
]
}),
copy({
targets: [
{ src: 'public/*', dest: '../../public/' },
]
}),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};

View File

@@ -0,0 +1,121 @@
// @ts-check
/** This script modifies the project to support TS code in .svelte files like:
<script lang="ts">
export let name: string;
</script>
As well as validating the code for CI.
*/
/** To work on this script:
rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template
*/
const fs = require("fs")
const path = require("path")
const { argv } = require("process")
const projectRoot = argv[2] || path.join(__dirname, "..")
// Add deps to pkg.json
const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8"))
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
"svelte-check": "^2.0.0",
"svelte-preprocess": "^4.0.0",
"@rollup/plugin-typescript": "^8.0.0",
"typescript": "^4.0.0",
"tslib": "^2.0.0",
"@tsconfig/svelte": "^2.0.0"
})
// Add script for checking
packageJSON.scripts = Object.assign(packageJSON.scripts, {
"check": "svelte-check --tsconfig ./tsconfig.json"
})
// Write the package JSON
fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " "))
// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too
const beforeMainJSPath = path.join(projectRoot, "src", "main.js")
const afterMainTSPath = path.join(projectRoot, "src", "main.ts")
fs.renameSync(beforeMainJSPath, afterMainTSPath)
// Switch the app.svelte file to use TS
const appSveltePath = path.join(projectRoot, "src", "App.svelte")
let appFile = fs.readFileSync(appSveltePath, "utf8")
appFile = appFile.replace("<script>", '<script lang="ts">')
appFile = appFile.replace("export let name;", 'export let name: string;')
fs.writeFileSync(appSveltePath, appFile)
// Edit rollup config
const rollupConfigPath = path.join(projectRoot, "rollup.config.js")
let rollupConfig = fs.readFileSync(rollupConfigPath, "utf8")
// Edit imports
rollupConfig = rollupConfig.replace(`'rollup-plugin-terser';`, `'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';`)
// Replace name of entry point
rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`)
// Add preprocessor
rollupConfig = rollupConfig.replace(
'compilerOptions:',
'preprocess: sveltePreprocess({ sourceMap: !production }),\n\t\t\tcompilerOptions:'
);
// Add TypeScript
rollupConfig = rollupConfig.replace(
'commonjs(),',
'commonjs(),\n\t\ttypescript({\n\t\t\tsourceMap: !production,\n\t\t\tinlineSources: !production\n\t\t}),'
);
fs.writeFileSync(rollupConfigPath, rollupConfig)
// Add TSConfig
const tsconfig = `{
"extends": "@tsconfig/svelte/tsconfig.json",
"include": ["src/**/*"],
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]
}`
const tsconfigPath = path.join(projectRoot, "tsconfig.json")
fs.writeFileSync(tsconfigPath, tsconfig)
// Add global.d.ts
const dtsPath = path.join(projectRoot, "src", "global.d.ts")
fs.writeFileSync(dtsPath, `/// <reference types="svelte" />`)
// Delete this script, but not during testing
if (!argv[2]) {
// Remove the script
fs.unlinkSync(path.join(__filename))
// Check for Mac's DS_store file, and if it's the only one left remove it
const remainingFiles = fs.readdirSync(path.join(__dirname))
if (remainingFiles.length === 1 && remainingFiles[0] === '.DS_store') {
fs.unlinkSync(path.join(__dirname, '.DS_store'))
}
// Check if the scripts folder is empty
if (fs.readdirSync(path.join(__dirname)).length === 0) {
// Remove the scripts folder
fs.rmdirSync(path.join(__dirname))
}
}
// Adds the extension recommendation
fs.mkdirSync(path.join(projectRoot, ".vscode"), { recursive: true })
fs.writeFileSync(path.join(projectRoot, ".vscode", "extensions.json"), `{
"recommendations": ["svelte.svelte-vscode"]
}
`)
console.log("Converted to TypeScript.")
if (fs.existsSync(path.join(projectRoot, "node_modules"))) {
console.log("\nYou will need to re-run your dependency manager to get started.")
}

View File

@@ -0,0 +1,40 @@
<svelte:options tag="cookies-dialog" />
<script>
// Import libraries
import { onMount } from 'svelte'
//Export
// Main code
onMount(() => {
})
</script>
<div id="wrapper">
<div>
<p>We use cookies to improve your experience, personalise your content and analyse site usage. By clicking “OK”, you agree to the use of cookies.</p>
</div>
</div>
<style>
@import '/css/common.css';
#wrapper {
display: none;
position: relative;
height: 5rem;
width: 100%;
background: white;
box-shadow: 0 0 0.314rem rgb(187, 187, 187);;
}
</style>

View File

@@ -0,0 +1,107 @@
<svelte:options tag="legend-component" />
<script>
// Import libraries
import { onMount } from 'svelte'
import { pullLegendData } from '/js/predict/charts.js'
// Import components
//Export
export let option = null
export let chart = null
export let data = {}
// Main code
let legendData = []
let buttons = []
let dataKeys
function init() {
if (option==null || option==undefined || chart==null || chart==undefined) {
setTimeout(init,100)
}
else {
legendData = pullLegendData(legendData,option)
for (let obj of legendData) {
data[obj.name] = true
}
dataKeys = Object.keys(data)
}
}
function toggleSeries(i) {
data[dataKeys[i]] = !data[dataKeys[i]]
let inds = []
let ids = option.series.map((x) => x._id)
let id = ids[i]
for (let j=0;j<ids.length;j++) {
if (ids[j]==id) {
inds.push(j)
}
}
for (let i of inds) {
let series = option.series[i]
if (!series.tooltip.show) {
series.lineStyle.opacity = 1
series.itemStyle.opacity = 1
series.tooltip.show = true
buttons[inds[0]].style.opacity = 1
}
else {
series.lineStyle.opacity = 0
series.itemStyle.opacity = 0
series.tooltip.show = false
buttons[inds[0]].style.opacity = 0.5
}
}
chart.setOption(option)
}
onMount(() => {
init()
})
</script>
<div class="legend">
{#each legendData as item, i}
<button bind:this={buttons[i]} on:click={() => toggleSeries(i)}>
<div class="marker" style="background-color: {item.color}"></div>
<span>{item.name}</span>
</button>
{/each}
</div>
<style>
@import '/css/common.css';
@import '/css/test-basic.css';
button {
cursor: pointer;
}
.legend {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
gap: 1rem;
}
.legend * {
font-family: var(--sans-serif);
}
.marker {
position: relative;
display:inline-block;
margin-right: 0.5rem;
top: 0.1rem;
width: 1rem;
height: 1rem;
border-radius: 1rem;
}
</style>

View File

@@ -0,0 +1,27 @@
<svelte:options tag="loadscreen-component" />
<script>
// Import libraries
import { onMount } from 'svelte'
// Import components
// Main code
let loadscreen
onMount(() => {
window.addEventListener('load', function() {
loadscreen.parentNode.host.style.display = "none"
})
})
</script>
<div bind:this={loadscreen} id="loadscreen" style="width:100%; height: 100%; background:white; position: absolute; z-index: 100000"></div>
<style>
</style>

View File

@@ -0,0 +1,181 @@
<svelte:options tag="pane-aligner" />
<script>
// Import libraries
import { getContext, setContext, onMount } from 'svelte'
import { debounce } from "/js/libraries/miscTools.js"
// Import components
// Export statements
// Main code
let root
let mainPane
let sidebarLeft
let sidebarLeft2
let sidebarRight
let parentProps = getContext("alignerParent")
let switchView = parentProps!=undefined ? getContext("alignerParent").switchView : undefined
let leftReplaced = false
let left2Replaced = false
let rightReplaced = false
let switchViewReplaced = false
function adjustSlotted() {
if (root.parentNode!=null) {
let slotted = root.parentNode.host.childNodes
if (slotted.length==0) {
setTimeout(adjustSlotted, 50)
}
else {
let changed = false
let html = root.parentNode.innerHTML
for (let item of slotted) {
if (item.slot=="sidebar-left" && !leftReplaced) {
html = html.replace("#sidebar-left{display:none}","")
leftReplaced = true
changed = true
}
else if (item.slot=="sidebar-left2" && !left2Replaced) {
html = html.replace("#sidebar-left2{display:none}","")
left2Replaced = true
changed = true
}
else if (item.slot=="sidebar-right" && !rightReplaced){
html = html.replace("#sidebar-right{display:none;","#sidebar-right{")
rightReplaced = true
changed = true
}
}
if (switchView!=undefined && !switchViewReplaced) {
html = html.replace("1880px",switchView)
changed = true
}
if (changed) {
root.parentNode.innerHTML = html
}
}
}
}
window.addEventListener("resize", debounce(adjustSlotted,100))
onMount(() => {
adjustSlotted()
})
</script>
<div bind:this={root} id="root" class="pane-centering">
<div class="pane-container">
<div id="sidebars-left" class="sidebar">
<div bind:this={sidebarLeft} id="sidebar-left" class="pane">
<slot name="sidebar-left"></slot>
</div>
<div bind:this={sidebarLeft2} id="sidebar-left2" class="pane">
<slot name="sidebar-left2"></slot>
</div>
</div>
<div bind:this={sidebarRight} id="sidebar-right" class="pane sidebar">
<slot name="sidebar-right"></slot>
</div>
<div bind:this={mainPane} id="main-pane" class="pane">
<slot name="main" id="main-slot"></slot>
</div>
</div>
</div>
<style>
@import '/css/common.css';
.pane-container {
display: block;
margin-left: var(--total-margin-left,0rem);
}
#root {
min-height: var(--min-height,auto);
}
#main-pane {
position: relative;
padding-left: var(--padding-left,0rem);
padding-right: var(--padding-right,0rem);
padding-top: var(--padding-top,0rem);
padding-bottom: var(--padding-bottom,0rem);
text-align: justify;
background: var(--background,white);
box-shadow: var(--box-shadow,0 0 0.314rem rgb(187, 187, 187));
margin: auto;
height: min-content;
max-width: var(--width-main,66rem);
width: var(--width-main,66rem);
z-index: 1;
overflow-x: var(--overflow-x,hidden);
}
.sidebar {
position: absolute;
}
#sidebars-left {
display: flex;
flex-direction: column;
gap: 1rem;
margin-left: calc(-1*var(--width-left,22.5rem) - 1rem - 4rem);
width: calc(var(--width-left,22.5rem) + 4rem);
}
#sidebar-left,#sidebar-left2 {
position: relative;
background-color: white;
padding: 2rem 2rem;
}
#sidebar-left {
display:none;
}
#sidebar-left2 {
display:none;
}
#sidebar-right {
display:none;
margin-left: calc(var(--width-main,66rem) + 1rem);
width: var(--width-right,auto);
background-color: white;
padding: 2rem 2rem;
}
@media only screen and (max-width: 1880px) {
#main-pane {
max-width: initial;
width: 100%;
max-width: var(--width-main,66rem);
padding-left: var(--padding-left-mobile,1.8rem);
padding-right: var(--padding-right-mobile,1.8rem);
padding-top: var(--padding-top-mobile,1.8rem);
padding-bottom: var(--padding-bottom-mobile,1.8rem);
}
#sidebars-left, #sidebar-right {
position: relative;
margin: auto;
margin-top: 1rem;
margin-bottom: 1rem;
max-width: var(--width-main,66rem);
width: 100%;
}
.pane-container {
width: 95%;
justify-items: center;
grid-auto-flow: row;
margin-left: 0;
}
}
</style>

View File

@@ -0,0 +1,256 @@
<svelte:options tag="select-component" />
<script>
// Import libraries
import { onMount } from 'svelte'
import { px2rem,getTextWidth,getCanvasFont } from "/js/libraries/miscTools.js"
//Export
export let callback = null
export let options = [""]
export let value = null
export let valueindex = null
// Main code
let root = arguments[0]
let select
let optionsHolder
let optionButtons = []
let currentOption
let currentOptionButton
let init = false
let key = 0
let obs = null
$: setKeyValue(value,options)
$: setKeyIndex(valueindex,options)
$: changeOptionsWidth(select,optionsHolder)
function setKeyValue(value,options) {
if (value!==null) {
if (options.includes(value)) {
let index = options.findIndex((element) => element==value)
currentOption.innerHTML = value
optionButtons[index].style.display = "none"
valueindex = index
}
key += 1
}
}
function setKeyIndex(valueindex,options) {
if (valueindex!=null && options!=undefined && options[valueindex]!=value) {
value = options[valueindex]
key += 1
}
}
function indexToValue(index) {
value = options[index]
}
function changeVisibility() {
if (optionsHolder.style.display=="none") {
optionsHolder.style.display = "initial"
}
else {
optionsHolder.style.display = "none"
}
}
function changeOption(index,callback) {
valueindex = index
value = options[index]
if (callback!=undefined && callback!=null) {
callback(index)
}
}
function hideSelect() {
optionsHolder.style.display = "none"
}
function changeOptionsWidth(select,optionsHolder) {
let selectWidth
if (select!=undefined && optionsHolder!=undefined) {
let selectWidthText = getComputedStyle(select).getPropertyValue('--width')
if (isNaN(selectWidthText) || selectWidthText=="") {
if (obs==null) {
obs = new ResizeObserver(() => changeOptionsWidth(select,optionsHolder))
obs.observe(currentOptionButton)
return
}
else {
selectWidthText = getComputedStyle(currentOptionButton).getPropertyValue('width')
selectWidth = px2rem(parseFloat(selectWidthText.slice(0,selectWidthText.length-2)))
}
}
else {
selectWidth = parseFloat(selectWidthText.slice(0,selectWidthText.length-2))
}
let spanWidths = []
for (let i=0;i<optionsHolder.children.length;i++) {
let span = optionsHolder.children[i].children[0]
let spanWidth = getTextWidth(span.innerHTML, getCanvasFont(span))
spanWidths.push(spanWidth)
}
let maxOptionsWidth = px2rem(Math.max(...spanWidths))
if (maxOptionsWidth>selectWidth) {
let width = 1.1*maxOptionsWidth+"rem"
optionsHolder.style.width = width
for (let i=0;i<optionsHolder.children.length;i++) {
let button = optionsHolder.children[i]
button.style.width = width
}
optionsHolder.style.marginLeft = - (1.1*maxOptionsWidth - selectWidth) /2 - 0.05 + "rem"
}
else {
let width = selectWidth + 0.1 + "rem"
for (let i=0;i<optionsHolder.children.length;i++) {
let button = optionsHolder.children[i]
button.style.width = width
}
}
}
}
onMount(() => {
init = true
root.addEventListener('focusout', hideSelect)
})
</script>
<div bind:this={select} class="select">
{#key key}
<button bind:this={currentOptionButton} id="current-option-button" on:click={changeVisibility}>
<div id="current-options-div">
<span bind:this={currentOption} id="current-options-span">{value!=null ? value : ""}</span>
</div>
<img id="arrow-down" src="../assets/arrow_down.svg" alt="arrow down">
</button>
<div bind:this={optionsHolder} id="options-holder" style="display: none">
{#each options as option, i}
<button bind:this={optionButtons[i]} value={i} on:click={() => changeOption(i,callback)}>
<span>{option}</span>
</button>
{/each}
</div>
{/key}
</div>
<style>
@import '/css/common.css';
#current-options-div {
position: relative;
overflow: hidden;
width: calc(100% - 2.5rem);
text-align: var(--text-align,left);
padding-top: 0.5rem;
}
#arrow-down {
right: 0.5rem;
width: 1.365rem;
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
.select {
position: relative;
margin-top: var(--margin-top,0);
width: var(--width);
max-width: var(--max-width);
height: var(--height,2.75rem);
border: var(--border,rgba(0,0,0,var(--opacity,1)) solid);
border-width: var(--border-width, 0.063rem);
border-radius: var(--border-radius,0.126rem);
}
.select button {
width: var(--width);
max-width: var(--max-width);
}
#current-option-button, #current-option-button * {
opacity: var(--opacity,1);
font-family: var(--font-family,var(--serif), serif);
font-size: var(--font-size, 1.3rem);
}
.select >:first-child {
margin-right: -2.75rem;
padding-right: 0.0rem;
}
.select span {
position: relative;
padding-top: 0.5rem;
white-space: nowrap;
}
#current-option-button {
display: flex;
width: 100%;
height: 100%;
padding-left: 0.341rem;
font-weight: var(--font-weight,400);
}
#options-holder {
position: absolute;
margin-top: calc(-1 * var(--border-width, 0.063rem));
background: white;
z-index: 1;
margin-left: -0.05rem;
border-radius: var(--border-radius-options,0.126rem);
}
#options-holder * {
font-size: var(--options-font-size, 1.2rem);
font-family: var(--font-family,var(--serif), serif);
}
#options-holder button {
display: flex;
position: relative;
width: var(--width);
background: white;
font-weight: 400;
text-align: var(--text-align,left);
padding-top: 0.341rem;
padding-bottom: 0.341rem;
padding-right: 3.515rem;
padding-left: 0.341rem;
}
#options-holder button:hover {
background: #cdcdcd;
}
#options-holder button {
border: black solid;
border-width: 0 var(--border-width-options,var(--border-width, 0.063rem)) 0 var(--border-width-options,var(--border-width, 0.063rem));
}
#options-holder >:first-child {
border-top: black solid var(--border-width-options,var(--border-width, 0.063rem));
border-top-left-radius: var(--border-radius-options,0.126rem);
border-top-right-radius: var(--border-radius-options,0.126rem);
}
#options-holder >:last-child {
border-bottom: black solid var(--border-width-options,var(--border-width, 0.063rem));
border-bottom-left-radius: var(--border-radius-options,0.126rem);
border-bottom-right-radius: var(--border-radius-options,0.126rem);
}
</style>

View File

@@ -0,0 +1,103 @@
<svelte:options tag="switch-component" />
<script>
// Import libraries
import { onMount } from 'svelte'
import { px2rem,getTextWidth,getCanvasFont } from "/js/libraries/miscTools.js"
//Export
export let callback = null
export let checked = false
export const toggle = () => {
let f = () => {
if (callback != null) {
checked = !checked
callback()
}
else {
toggle()
}
}
setTimeout(f,100)
}
function toggleClick() {
if (callback != null) {
checked = !checked
callback()
}
}
// Main code
onMount(() => {
})
</script>
<label class="switch">
<input type="checkbox" bind:checked={checked} on:click={toggleClick}>
<span class="switch-span"></span>
</label>
<style>
@import '/css/common.css';
.switch span {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
border-radius: calc(2* 1.2rem);
}
.switch span:before {
position: absolute;
content: "";
height: calc(var(--height) - 0.5rem);
width: calc(var(--height) - 0.5rem);
left: calc(0.3rem);
bottom: 0.25rem;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
border-radius: 50%;
}
.switch input:checked + .switch-span {
background-color: var(--pink);
}
.switch input:hover + .switch-span {
box-shadow: 0 0 0 var(--pink);
}
.switch input:checked + .switch-span:before {
-webkit-transform: translateX(calc(var(--width) - var(--height)/2 - 2*0.6rem));
-ms-transform: translateX(calc(var(--width) - var(--height)/2 - 2*0.6rem));
transform: translateX(calc(var(--width) - var(--height)/2 - 2*0.6rem));
}
.switch {
position: relative;
display: inline-block;
width: var(--width);
height: var(--height);
}
.switch input {
position: absolute;
width: var(--width);
height: var(--height);
opacity: 0;
}
</style>

View File

@@ -0,0 +1,34 @@
<svelte:options tag="footer-component" />
<script>
// Import components
</script>
<footer>
<div id="footer-content-container">
<div id="footer-grid-content-container" class="logged">
<div id="contact-us-container">
<h2>CONTACT US</h2>
<p>Email: <a href="mailto:info@chiron.com">test@test</a></p>
</div>
</div>
<button on:click={() => {location.href='#'}} id="footer-up" aria-label="go up">
<svg xmlns="http://www.w3.org/2000/svg" width="42.545" height="72.601" viewBox="0 0 42.545 72.601">
<g id="Group_268" data-name="Group 268" transform="translate(-6.177 -2.399)">
<rect id="Rectangle_146" data-name="Rectangle 146" width="11" height="51" rx="5.5" transform="translate(22 24)" fill="var(--pink)"/>
<path id="Path_1145" data-name="Path 1145" d="M23.814,4.021a5,5,0,0,1,7.372,0l16.134,17.6c2.94,3.207,1.046,10.4-3.686,8.379S28.02,14.081,28.391,13.524,16.544,27.976,11.366,30,4.741,24.828,7.68,21.621Z" fill="var(--pink)"/>
</g>
</svg>
</button>
<p id="footer-copyright">© 2023 LibSoc</p>
</div>
</footer>
<style>
@import '/css/common.css';
@import '/css/footer.css';
</style>

View File

@@ -0,0 +1,26 @@
<svelte:options tag="landing-component" />
<script>
// Import statements
i
// Import components
// Main code
onMount(() => {
})
</script>
<!--HTML GOES HERE-->
<p>I AM A TEXT FOR TESTING</p>
<style>
@import '/css/common.css';
</style>

View File

@@ -0,0 +1,57 @@
<svelte:options tag="navbar-component" />
<script>
// Import statements
import { onMount } from 'svelte'
// Main code
let hambInput
let navbar
function changeNavbar() {
if (hambInput.checked) {
navbar.style.background = "white"
navbar.style.boxShadow = "0 0 0.314rem rgb(187, 187, 187)"
}
else {
setTimeout(()=> {
navbar.style.position = "relative"
navbar.style.background = ""
navbar.style.boxShadow = ""
}
,510)
}
}
onMount(() => {
})
</script>
<!-- Navigation bar -->
<header bind:this={navbar} id="navbar">
<!-- Logo -->
<a id=logo-container href="/">
<img src="" id="navbar-logo" alt="iql logo">
<span id="navbar-logo-text">LibSoc</span>
</a>
<!-- Hamburger icon -->
<input bind:this={hambInput} type="checkbox" id="side-menu" on:click={changeNavbar}>
<label id="hamb" for="side-menu"><span id="hamb-line"></span></label>
<!-- Menu -->
<nav id="nav">
<ul id="menu">
<li><a href="/test">test</a></li>
</ul>
</nav>
</header>
<style>
@import '/css/common.css';
@import '/css/navbar.css';
</style>