feat(frontend-shared): unifying frontend components, build tools, styles, test config, and more. (#18265)
* feat(frontend-shared): Adding shared components, styles, test tooling, build tooling, and plugins * chore(launchpad): fix build for feat/fronted-shared-infra (#18267) * wip: fix build * fix tests * modify tsconfig * fix typing error * simplify imports Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>
@@ -1,79 +1,142 @@
|
||||
<p align="center">
|
||||
<img src="https://cloud.githubusercontent.com/assets/1268976/20607953/d7ae489c-b24a-11e6-9cc4-91c6c74c5e88.png"/>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://on.cypress.io">Documentation</a> |
|
||||
<a href="https://on.cypress.io/changelog">Changelog</a> |
|
||||
<a href="https://on.cypress.io/roadmap">Roadmap</a>
|
||||
</p>
|
||||
|
||||
<h3 align="center">
|
||||
The web has evolved. Finally, testing has too.
|
||||
</h3>
|
||||
|
||||
<p align="center">
|
||||
Fast, easy and reliable testing for anything that runs in a browser.
|
||||
</p>
|
||||
<p align="center">
|
||||
Join us, we're <a href="https://cypress.io/jobs">hiring</a>.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/package/cypress">
|
||||
<img src="https://img.shields.io/npm/dm/cypress.svg" alt="npm"/>
|
||||
</a>
|
||||
<a href="https://gitter.im/cypress-io/cypress">
|
||||
<img src="https://img.shields.io/gitter/room/cypress-io/cypress.svg" alt="Gitter chat"/>
|
||||
</a>
|
||||
<a href="https://stackshare.io/cypress">
|
||||
<img src="https://img.stackshare.io/misc/follow-on-stackshare-badge.svg" alt="StackShare"/>
|
||||
</a><br />
|
||||
</p>
|
||||
|
||||
## What is Cypress?
|
||||
|
||||
<p align="center">
|
||||
<a href="https://player.vimeo.com/video/237527670">
|
||||
<img alt="Why Cypress Video" src="https://user-images.githubusercontent.com/1271364/31739717-dbdff0ee-b41c-11e7-9b16-bfa1b6ac1814.png" width="75%" height="75%" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Installing
|
||||
|
||||
[](https://badge.fury.io/js/cypress)
|
||||
|
||||
Install Cypress for Mac, Linux, or Windows, then [get started](https://docs.cypress.io/guides/getting-started/installing-cypress.html).
|
||||
|
||||
```bash
|
||||
npm install cypress --save-dev
|
||||
```
|
||||
or
|
||||
```bash
|
||||
yarn add cypress --dev
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
- [](https://circleci.com/gh/cypress-io/cypress/tree/develop) - `develop` branch
|
||||
- [](https://circleci.com/gh/cypress-io/cypress/tree/master) - `master` branch
|
||||
|
||||
Please see our [Contributing Guideline](./CONTRIBUTING.md) which explains repo organization, linting, testing, and other steps.
|
||||
|
||||
## License
|
||||
|
||||
[](https://github.com/cypress-io/cypress/blob/master/LICENSE)
|
||||
|
||||
This project is licensed under the terms of the [MIT license](/LICENSE).
|
||||
|
||||
## Badges
|
||||
|
||||
Let the world know your project is using Cypress.io to test with this cool badge
|
||||
|
||||
[](https://www.cypress.io/)
|
||||
|
||||
```
|
||||
[](https://www.cypress.io/)
|
||||
```
|
||||
<p align="center">
|
||||
<a href="" rel="noopener">
|
||||
<img width=200px height=200px src="https://i.imgur.com/FxL5qM0.jpg" alt="Bot logo"></a>
|
||||
</p>
|
||||
|
||||
<h3 align="center">cypress</h3>
|
||||
|
||||
<div align="center">
|
||||
|
||||
[]()
|
||||
[](https://www.reddit.com/user/Wordbook_Bot)
|
||||
[](https://github.com/kylelobo/The-Documentation-Compendium/issues)
|
||||
[](https://github.com/kylelobo/The-Documentation-Compendium/pulls)
|
||||
[](/LICENSE)
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
<p align="center"> 🤖 Few lines describing what your bot does.
|
||||
<br>
|
||||
</p>
|
||||
|
||||
## 📝 Table of Contents
|
||||
|
||||
- [About](#about)
|
||||
- [Demo / Working](#demo)
|
||||
- [How it works](#working)
|
||||
- [Usage](#usage)
|
||||
- [Getting Started](#getting_started)
|
||||
- [Deploying your own bot](#deployment)
|
||||
- [Built Using](#built_using)
|
||||
- [TODO](../TODO.md)
|
||||
- [Contributing](../CONTRIBUTING.md)
|
||||
- [Authors](#authors)
|
||||
- [Acknowledgments](#acknowledgement)
|
||||
|
||||
## 🧐 About <a name = "about"></a>
|
||||
|
||||
Write about 1-2 paragraphs describing the purpose of your bot.
|
||||
|
||||
## 🎥 Demo / Working <a name = "demo"></a>
|
||||
|
||||

|
||||
|
||||
## 💭 How it works <a name = "working"></a>
|
||||
|
||||
The bot first extracts the word from the comment and then fetches word definitions, part of speech, example and source from the Oxford Dictionary API.
|
||||
|
||||
If the word does not exist in the Oxford Dictionary, the Oxford API then returns a 404 response upon which the bot then tries to fetch results form the Urban Dictionary API.
|
||||
|
||||
The bot uses the Pushshift API to fetch comments, PRAW module to reply to comments and Heroku as a server.
|
||||
|
||||
The entire bot is written in Python 3.6
|
||||
|
||||
## 🎈 Usage <a name = "usage"></a>
|
||||
|
||||
To use the bot, type:
|
||||
|
||||
```
|
||||
!dict word
|
||||
```
|
||||
|
||||
The first part, i.e. "!dict" **is not** case sensitive.
|
||||
|
||||
The bot will then give you the Oxford Dictionary (or Urban Dictionary; if the word does not exist in the Oxford Dictionary) definition of the word as a comment reply.
|
||||
|
||||
### Example:
|
||||
|
||||
> !dict what is love
|
||||
|
||||
**Definition:**
|
||||
|
||||
Baby, dont hurt me~
|
||||
Dont hurt me~ no more.
|
||||
|
||||
**Example:**
|
||||
|
||||
Dude1: Bruh, what is love?
|
||||
Dude2: Baby, dont hurt me, dont hurt me- no more!
|
||||
Dude1: dafuq?
|
||||
|
||||
**Source:** https://www.urbandictionary.com/define.php?term=what%20is%20love
|
||||
|
||||
---
|
||||
|
||||
<sup>Beep boop. I am a bot. If there are any issues, contact my [Master](https://www.reddit.com/message/compose/?to=PositivePlayer1&subject=/u/Wordbook_Bot)</sup>
|
||||
|
||||
<sup>Want to make a similar reddit bot? Check out: [GitHub](https://github.com/kylelobo/Reddit-Bot)</sup>
|
||||
|
||||
## 🏁 Getting Started <a name = "getting_started"></a>
|
||||
|
||||
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See [deployment](#deployment) for notes on how to deploy the project on a live system.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
What things you need to install the software and how to install them.
|
||||
|
||||
```
|
||||
Give examples
|
||||
```
|
||||
|
||||
### Installing
|
||||
|
||||
A step by step series of examples that tell you how to get a development env running.
|
||||
|
||||
Say what the step will be
|
||||
|
||||
```
|
||||
Give the example
|
||||
```
|
||||
|
||||
And repeat
|
||||
|
||||
```
|
||||
until finished
|
||||
```
|
||||
|
||||
End with an example of getting some data out of the system or using it for a little demo.
|
||||
|
||||
## 🚀 Deploying your own bot <a name = "deployment"></a>
|
||||
|
||||
To see an example project on how to deploy your bot, please see my own configuration:
|
||||
|
||||
- **Heroku**: https://github.com/kylelobo/Reddit-Bot#deploying_the_bot
|
||||
|
||||
## ⛏️ Built Using <a name = "built_using"></a>
|
||||
|
||||
- [PRAW](https://praw.readthedocs.io/en/latest/) - Python Reddit API Wrapper
|
||||
- [Heroku](https://www.heroku.com/) - SaaS hosting platform
|
||||
|
||||
## ✍️ Authors <a name = "authors"></a>
|
||||
|
||||
- [@kylelobo](https://github.com/kylelobo) - Idea & Initial work
|
||||
|
||||
See also the list of [contributors](https://github.com/kylelobo/The-Documentation-Compendium/contributors) who participated in this project.
|
||||
|
||||
## 🎉 Acknowledgements <a name = "acknowledgement"></a>
|
||||
|
||||
- Hat tip to anyone whose code was used
|
||||
- Inspiration
|
||||
- References
|
||||
|
||||
@@ -17,7 +17,7 @@ interface RuleConfig {
|
||||
}
|
||||
|
||||
const makeRuleForClass = ({ name, theme, weight, color }: RuleConfig) => {
|
||||
const resolvedColor = color ? color : weight ? theme(`colors.${name}.${weight}`) : theme(`colors.${name}`)
|
||||
const resolvedColor = color ? color : weight ? theme?.(`colors.${name}.${weight}`) : theme?.(`colors.${name}`)
|
||||
let [lightKey, darkKey] = [`.icon-light-${name}`, `.icon-dark-${name}`]
|
||||
|
||||
// transparent, black, and white
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { registerMountFn } from '@packages/frontend-shared/cypress/support/commands'
|
||||
import { registerMountFn } from '@packages/frontend-shared/cypress/support/common'
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
@@ -19,7 +19,6 @@ import { registerMountFn } from '@packages/frontend-shared/cypress/support/comma
|
||||
import 'virtual:windi.css'
|
||||
import '../../src/main.scss'
|
||||
import '@iconify/iconify'
|
||||
import '@purge-icons/generated'
|
||||
import { createRouter } from '../../src/router/router'
|
||||
|
||||
registerMountFn({ plugins: [() => createRouter()] })
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"@iconify/json": "1.1.368",
|
||||
"@iconify/vue": "3.0.0-beta.1",
|
||||
"@intlify/vite-plugin-vue-i18n": "2.4.0",
|
||||
"@packages/frontend-shared": "0.0.0-development",
|
||||
"@testing-library/cypress": "8.0.0",
|
||||
"@urql/core": "2.3.1",
|
||||
"@urql/vue": "0.4.3",
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
{
|
||||
"links": {
|
||||
"learnMore": "Learn more."
|
||||
},
|
||||
"components": {
|
||||
"modal": {
|
||||
"dismiss": "Dismiss"
|
||||
},
|
||||
"select": {
|
||||
"placeholder": "Choose an option..."
|
||||
}
|
||||
},
|
||||
"clipboard": {
|
||||
"copy": "Copy",
|
||||
"copied": "Copied"
|
||||
},
|
||||
"file": {
|
||||
"edit": "Edit"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled"
|
||||
},
|
||||
"setupPage": {
|
||||
"projectSetup": {
|
||||
"frameworkLabel": "Front-end Framework",
|
||||
"frameworkPlaceholder": "Pick a framework",
|
||||
"bundlerLabel": "Bundler",
|
||||
"bundlerPlaceholder": "Pick a bundler"
|
||||
},
|
||||
"install": {
|
||||
"startButton": "Install",
|
||||
"confirmManualInstall": "I've installed them"
|
||||
},
|
||||
"step": {
|
||||
"next": "Next Step",
|
||||
"back": "Back"
|
||||
}
|
||||
},
|
||||
"globalPage": {
|
||||
"empty": {
|
||||
"title": "Welcome to Cypress!",
|
||||
"helper": "Add your first project below to start testing with Cypress.",
|
||||
"dropText": "Drag your project here or {0}",
|
||||
"browseManually": "browse manually."
|
||||
},
|
||||
"searchPlaceholder": "Search Projects",
|
||||
"newProjectButton": "New Project"
|
||||
},
|
||||
"welcomeGuide": {
|
||||
"header": {
|
||||
"title": "Cypress",
|
||||
"description": "A powerful open-source testing platform for developers and engineering teams all around the world."
|
||||
},
|
||||
"projectListHeader": "Recently Viewed Projects",
|
||||
"linkHeader": "Quick Access",
|
||||
"confirmWelcomeGuide": "Show the welcome guide when opening Cypress."
|
||||
},
|
||||
"settingsPage": {
|
||||
"config": {
|
||||
"title": "Resolved Configuration",
|
||||
"description": "Since the options in the {0} can be set dynamically by your development environment, please refer to the legend below to understand how the configuration options are resolved.",
|
||||
"legend": {
|
||||
"env": {
|
||||
"label": "env",
|
||||
"description": "Set from environment variables"
|
||||
},
|
||||
"default": {
|
||||
"label": "default",
|
||||
"description": "Default values"
|
||||
},
|
||||
"dynamic": {
|
||||
"label": "dynamic",
|
||||
"description": "Set by the {0} function"
|
||||
},
|
||||
"cli": {
|
||||
"label": "cli",
|
||||
"description": "Set from CLI arguments"
|
||||
},
|
||||
"config": {
|
||||
"label": "config",
|
||||
"description": "Set from {0}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"proxy": {
|
||||
"title": "Proxy Settings",
|
||||
"description": "Cypress auto-detected the following proxy settings from your operating system.",
|
||||
"bypassList": "Proxy Bypass List",
|
||||
"proxyServer": "Proxy Server"
|
||||
},
|
||||
"editor": {
|
||||
"title": "External Editor",
|
||||
"description": "External editor to use for editing code opened when using Cypress.",
|
||||
"noEditorSelectedPlaceholder": "Choose your editor..."
|
||||
},
|
||||
"projectId": {
|
||||
"title": "Project ID",
|
||||
"description": "The Project ID configured for this project inside of Cypress Cloud. {0}"
|
||||
},
|
||||
"recordKey": {
|
||||
"title": "Record Key",
|
||||
"description": "The Record Key configured for this project inside of Cypress Cloud. {0}",
|
||||
"manageKeys": "Manage Keys"
|
||||
},
|
||||
"project": {
|
||||
"title": "Project Settings",
|
||||
"description": "Settings for this project."
|
||||
},
|
||||
"experiments": {
|
||||
"title": "Experiments",
|
||||
"description": "If you'd like to try out new features that we're working on, you can enable beta features for your project by turning on the experimental features you'd like to try. {0}"
|
||||
},
|
||||
"device": {
|
||||
"title": "Device Settings",
|
||||
"description": "Settings for this device."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,4 @@
|
||||
/* Define the "system" font family */
|
||||
@font-face {
|
||||
font-family: system;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local(".SFNSText-Light"), local(".HelveticaNeueDeskInterface-Light"),
|
||||
local(".LucidaGrandeUI"), local("Ubuntu Light"), local("Segoe UI Light"),
|
||||
local("Roboto-Light"), local("DroidSans"), local("Tahoma");
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
/**
|
||||
* Animations
|
||||
* -------------------------
|
||||
*/
|
||||
@use '@packages/frontend-shared/src/styles/shared.scss';
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
@@ -42,251 +25,3 @@ body {
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Resets
|
||||
* -------------------------
|
||||
*/
|
||||
|
||||
// Input Resets
|
||||
// Taken from Tailwind CSS Forms -- a plugin for tailwind.
|
||||
// We could probably add these into WindiCSS directly
|
||||
// https://github.com/tailwindlabs/tailwindcss-forms
|
||||
|
||||
[multiple],
|
||||
[type=date],
|
||||
[type=datetime-local],
|
||||
[type=email],
|
||||
[type=month],
|
||||
[type=number],
|
||||
[type=password],
|
||||
[type=search],
|
||||
[type=tel],
|
||||
[type=text],
|
||||
[type=time],
|
||||
[type=url],
|
||||
[type=week],
|
||||
select,
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: #fff;
|
||||
border-color: #6b7280;
|
||||
border-width: 1px;
|
||||
border-radius: 0;
|
||||
padding-top: 0.35rem;
|
||||
padding-bottom: 0.35rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
[multiple]:focus,
|
||||
[type=date]:focus,
|
||||
[type=datetime-local]:focus,
|
||||
[type=email]:focus,
|
||||
[type=month]:focus,
|
||||
[type=number]:focus,
|
||||
[type=password]:focus,
|
||||
[type=search]:focus,
|
||||
[type=tel]:focus,
|
||||
[type=text]:focus,
|
||||
[type=time]:focus,
|
||||
[type=url]:focus,
|
||||
[type=week]:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
--tw-ring-inset: var(--tw-empty, );
|
||||
/*!*/
|
||||
/*!*/
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: #2563eb;
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
border-color: #2563eb;
|
||||
}
|
||||
|
||||
input::-moz-placeholder,
|
||||
textarea::-moz-placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input:-ms-input-placeholder,
|
||||
textarea:-ms-input-placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input::placeholder,
|
||||
textarea::placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-date-and-time-value {
|
||||
min-height: 1.5em;
|
||||
}
|
||||
|
||||
select {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||
background-position: right .5rem center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1.5em 1.5em;
|
||||
padding-right: 2.5rem;
|
||||
-webkit-print-color-adjust: exact;
|
||||
color-adjust: exact;
|
||||
}
|
||||
|
||||
[multiple] {
|
||||
background-image: initial;
|
||||
background-position: initial;
|
||||
background-repeat: unset;
|
||||
background-size: initial;
|
||||
padding-right: .75rem;
|
||||
-webkit-print-color-adjust: unset;
|
||||
color-adjust: unset;
|
||||
}
|
||||
|
||||
[type=checkbox],
|
||||
[type=radio] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
padding: 0;
|
||||
-webkit-print-color-adjust: exact;
|
||||
color-adjust: exact;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background-origin: border-box;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
flex-shrink: 0;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
color: #2563eb;
|
||||
background-color: #fff;
|
||||
border-color: #6b7280;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
[type=checkbox] {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
[type=radio] {
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
[type=checkbox]:focus,
|
||||
[type=radio]:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
--tw-ring-inset: var(--tw-empty);
|
||||
--tw-ring-offset-width: 2px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: #2563eb;
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
}
|
||||
|
||||
[type=checkbox]:checked,
|
||||
[type=radio]:checked {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[type=checkbox]:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
[type=radio]:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
[type=checkbox]:checked:focus,
|
||||
[type=checkbox]:checked:hover,
|
||||
[type=radio]:checked:focus,
|
||||
[type=radio]:checked:hover {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
[type=checkbox]:indeterminate {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[type=checkbox]:indeterminate:focus,
|
||||
[type=checkbox]:indeterminate:hover {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
[type=file] {
|
||||
background: unset;
|
||||
border-color: inherit;
|
||||
border-width: 0;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
font-size: unset;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
[type=file]:focus {
|
||||
outline: 1px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
|
||||
input[type="search"].dark {
|
||||
background: #222;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
input[type="search"].light {
|
||||
background: #fff;
|
||||
color: #222;
|
||||
}
|
||||
input[type="search"].suffix::-webkit-search-cancel-button {
|
||||
@apply pr-3.25em;
|
||||
}
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 1em;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
border-radius: 50em;
|
||||
background: url(https://pro.fontawesome.com/releases/v5.10.0/svgs/solid/times-circle.svg)
|
||||
no-repeat 50% 50%;
|
||||
background-size: contain;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
input[type="search"]:focus::-webkit-search-cancel-button {
|
||||
opacity: 0.3;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
input[type="search"].dark::-webkit-search-cancel-button {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'virtual:windi.css'
|
||||
import urql from '@urql/vue'
|
||||
import App from './App.vue'
|
||||
import { makeUrqlClient } from '@packages/frontend-shared/src/graphql/urqlClient'
|
||||
import { createI18n } from './locales/i18n'
|
||||
import { createI18n } from '@cy/i18n'
|
||||
import { createRouter } from './router/router'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
@@ -1,4 +1,19 @@
|
||||
{
|
||||
"extends": "../frontend-shared/tsconfig.json",
|
||||
"include": ["src/**/*.vue", "src/**/*.tsx", "cypress/**/*.ts"]
|
||||
"include": [
|
||||
"src/**/*.vue",
|
||||
"src/**/*.tsx",
|
||||
"cypress/**/*.ts",
|
||||
"cypress/**/*.tsx",
|
||||
"../frontend-shared/src/**/*.vue",
|
||||
"../frontend-shared/src/**/*.tsx",
|
||||
"../frontend-shared/cypress/**/*.ts"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@cy/i18n": ["../frontend-shared/src/locales/i18n"],
|
||||
"@cy/components/*": ["../frontend-shared/src/components/*"],
|
||||
"@packages/*": ["../*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +1,10 @@
|
||||
import path from 'path'
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import WindiCSS from 'vite-plugin-windicss'
|
||||
import PurgeIcons from 'vite-plugin-purge-icons'
|
||||
import VueI18n from '@intlify/vite-plugin-vue-i18n'
|
||||
import VueSvgLoader from 'vite-svg-loader'
|
||||
import { makeConfig } from '../frontend-shared/vite.config'
|
||||
import Layouts from 'vite-plugin-vue-layouts'
|
||||
import Pages from 'vite-plugin-pages'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import Icons from 'unplugin-icons/vite'
|
||||
import IconsResolver from 'unplugin-icons/resolver'
|
||||
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
|
||||
|
||||
export default defineConfig({
|
||||
base: './',
|
||||
build: {
|
||||
minify: false,
|
||||
},
|
||||
export default makeConfig({}, {
|
||||
plugins: [
|
||||
vue(),
|
||||
vueJsx(),
|
||||
Layouts(),
|
||||
Pages({
|
||||
extensions: ['vue'],
|
||||
}),
|
||||
PurgeIcons(),
|
||||
VueI18n({
|
||||
include: path.resolve(__dirname, './src/locales/**'),
|
||||
}),
|
||||
Icons({
|
||||
customCollections: {
|
||||
// ~icons/cy/book-x16
|
||||
cy: FileSystemIconLoader('./src/assets/icons'),
|
||||
},
|
||||
}),
|
||||
Components({
|
||||
// <i-cy-book-x16/>
|
||||
resolvers: IconsResolver({
|
||||
customCollections: ['cy'],
|
||||
}),
|
||||
}),
|
||||
WindiCSS(),
|
||||
VueSvgLoader(),
|
||||
Pages({ extensions: ['vue'] }),
|
||||
],
|
||||
define: {
|
||||
'process.env': {},
|
||||
'setImmediate': {},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,32 +1,3 @@
|
||||
import { defineConfig } from 'windicss/helpers'
|
||||
import InteractionVariants from '@windicss/plugin-interaction-variants'
|
||||
import { IconDuotoneColorsPlugin } from './.windicss/icon-color-plugins'
|
||||
import { safelist } from './.windicss/safelist'
|
||||
import WindiConfig from '@packages/frontend-shared/windi.config'
|
||||
|
||||
export default defineConfig({
|
||||
// This adds !important to all utility classes. https://csswizardry.com/2016/05/the-importance-of-important/
|
||||
important: true,
|
||||
theme: {
|
||||
extend: {
|
||||
gridTemplateColumns: {
|
||||
launchpad: '64px 1fr',
|
||||
},
|
||||
gridTemplateRows: {
|
||||
launchpad: '64px 1fr',
|
||||
},
|
||||
},
|
||||
},
|
||||
safelist,
|
||||
variants: {
|
||||
backgroundColor: ['group-focus-within', 'group-focus-visible', 'group-active', 'group-visited', 'group-disabled', 'hocus', 'group-hocus', 'can-hover', 'no-hover'],
|
||||
},
|
||||
plugins: [
|
||||
InteractionVariants,
|
||||
IconDuotoneColorsPlugin,
|
||||
],
|
||||
extract: {
|
||||
// accepts globs and file paths relative to project root
|
||||
include: ['index.html', 'src/**/*.{vue,html,tsx}'],
|
||||
exclude: ['node_modules/**/*', '.git/**/*'],
|
||||
},
|
||||
})
|
||||
export default WindiConfig
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const colors = {
|
||||
import Colors from 'windicss/colors'
|
||||
|
||||
const customColors = {
|
||||
jade: {
|
||||
50: '#E0F6FA',
|
||||
100: '#C2F1DE',
|
||||
@@ -144,46 +146,48 @@ const colors = {
|
||||
},
|
||||
}
|
||||
|
||||
export const customColors = {
|
||||
...colors,
|
||||
export const cyColors = {
|
||||
...customColors,
|
||||
primary: {
|
||||
...colors.indigo,
|
||||
DEFAULT: colors.indigo[500],
|
||||
...customColors.indigo,
|
||||
DEFAULT: customColors.indigo[500],
|
||||
},
|
||||
secondary: {
|
||||
...colors.indigo,
|
||||
DEFAULT: colors.indigo[50],
|
||||
...customColors.indigo,
|
||||
DEFAULT: customColors.indigo[50],
|
||||
},
|
||||
error: {
|
||||
...colors.red,
|
||||
DEFAULT: colors.red[400],
|
||||
...customColors.red,
|
||||
DEFAULT: customColors.red[400],
|
||||
},
|
||||
caution: {
|
||||
...colors.red,
|
||||
DEFAULT: colors.red[500],
|
||||
...customColors.red,
|
||||
DEFAULT: customColors.red[500],
|
||||
},
|
||||
warning: {
|
||||
...colors.orange,
|
||||
DEFAULT: colors.orange[500],
|
||||
...customColors.orange,
|
||||
DEFAULT: customColors.orange[500],
|
||||
},
|
||||
'warning-light': {
|
||||
...colors.orange,
|
||||
DEFAULT: colors.orange[400],
|
||||
...customColors.orange,
|
||||
DEFAULT: customColors.orange[400],
|
||||
},
|
||||
success: {
|
||||
...colors.jade,
|
||||
DEFAULT: colors.jade[400],
|
||||
...customColors.jade,
|
||||
DEFAULT: customColors.jade[400],
|
||||
},
|
||||
'success-light': {
|
||||
...colors.jade,
|
||||
DEFAULT: colors.jade[300],
|
||||
...customColors.jade,
|
||||
DEFAULT: customColors.jade[300],
|
||||
},
|
||||
confirm: {
|
||||
...colors.jade,
|
||||
DEFAULT: colors.jade[500],
|
||||
...customColors.jade,
|
||||
DEFAULT: customColors.jade[500],
|
||||
},
|
||||
'body-gray': {
|
||||
...colors.gray,
|
||||
DEFAULT: colors.gray[600],
|
||||
...customColors.gray,
|
||||
DEFAULT: customColors.gray[600],
|
||||
},
|
||||
}
|
||||
|
||||
export const colors = { ...Colors, ...cyColors }
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* This package adds support for targeting
|
||||
* light vs dark classes in duotone icons.
|
||||
*
|
||||
* It works by adding utility classes and specific selectors
|
||||
*/
|
||||
|
||||
import createPlugin from 'windicss/plugin'
|
||||
import { reduce, kebabCase, isObject } from 'lodash'
|
||||
import Colors from 'windicss/colors'
|
||||
|
||||
interface RuleConfig {
|
||||
name: string
|
||||
theme?: (key: string) => string
|
||||
weight?: string
|
||||
color?: string
|
||||
}
|
||||
|
||||
const makeRuleForClass = ({ name, theme, weight, color }: RuleConfig) => {
|
||||
const resolvedColor = color ? color : weight ? theme?.(`colors.${name}.${weight}`) : theme?.(`colors.${name}`)
|
||||
let [lightKey, darkKey] = [`.icon-light-${name}`, `.icon-dark-${name}`]
|
||||
|
||||
// transparent, black, and white
|
||||
if (weight) {
|
||||
lightKey += `-${weight}`
|
||||
darkKey += `-${weight}`
|
||||
}
|
||||
|
||||
return {
|
||||
// When we're targeting an svg with icon-light-red-500
|
||||
// only attach the fill and stroke for those same icons
|
||||
// and vice versa for icon-dark
|
||||
[lightKey]: {
|
||||
'> *[fill].icon-light': {
|
||||
fill: resolvedColor,
|
||||
},
|
||||
'> *[stroke].icon-light': {
|
||||
stroke: resolvedColor,
|
||||
},
|
||||
'> *[fill][stroke].icon-light-fill': {
|
||||
fill: resolvedColor,
|
||||
},
|
||||
},
|
||||
[darkKey]: {
|
||||
'> *[fill].icon-dark-fill': {
|
||||
fill: resolvedColor,
|
||||
},
|
||||
'> *[fill].icon-dark': {
|
||||
fill: resolvedColor,
|
||||
},
|
||||
'> *[stroke].icon-dark': {
|
||||
stroke: resolvedColor,
|
||||
},
|
||||
'> *[fill][stroke].icon-dark-stroke': {
|
||||
stroke: resolvedColor,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function addIconUtilityClasses (theme) {
|
||||
return reduce(Colors, (acc, variants, colorName) => {
|
||||
// lightGray => light-gray
|
||||
const name = kebabCase(colorName)
|
||||
|
||||
// Collect the classes we're going to add to the windicss class registry
|
||||
let additionalClasses = {}
|
||||
|
||||
// There are both nested and not-nested colors (e.g. black, white)
|
||||
if (isObject(variants)) {
|
||||
// multiple levels of colors
|
||||
additionalClasses = reduce(variants, (variantAcc, _, weight) => {
|
||||
const rules = makeRuleForClass({ name, theme, weight })
|
||||
|
||||
return { ...variantAcc, ...rules }
|
||||
}, {})
|
||||
} else {
|
||||
// single values like black, white
|
||||
additionalClasses = makeRuleForClass({ name, theme })
|
||||
}
|
||||
|
||||
// Output is an object where each new class is a key
|
||||
// And the selectors and values affected are values
|
||||
/**
|
||||
* {
|
||||
* `.icon-light-green-500`: {
|
||||
* '> *[stroke].icon-light': {
|
||||
* stroke: resolvedColor
|
||||
* },
|
||||
* '> *[fill].icon-light': {
|
||||
* fill: resolvedColor
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
return { ...acc, ...additionalClasses }
|
||||
}, {
|
||||
|
||||
// These technically aren't under "colors"
|
||||
...makeRuleForClass({ name: 'transparent', color: 'transparent' }),
|
||||
...makeRuleForClass({ name: 'current', color: 'currentColor' }),
|
||||
})
|
||||
}
|
||||
|
||||
export const IconDuotoneColorsPlugin = createPlugin(({ theme, addUtilities }) => {
|
||||
// @ts-ignore - dunno
|
||||
addUtilities(addIconUtilityClasses(theme))
|
||||
})
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* WindiCSS will strip out any styles that aren't used.
|
||||
* We do a lot of dynamic stuff, and we're not too concerned
|
||||
* ith bundle size, so this is a pretty greedy list
|
||||
*/
|
||||
import { colors } from './colors'
|
||||
import { map, reduce, kebabCase } from 'lodash'
|
||||
|
||||
const textSafelist = ['xs', 'sm', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl', '6xl'].map((v) => `text-${v}`).join(' ')
|
||||
const colorSafelist = reduce(colors, (acc, variants, colorName) => {
|
||||
const name = kebabCase(colorName)
|
||||
|
||||
return `${acc}
|
||||
${map(variants, (_: string, k: string) => {
|
||||
return `bg-${name}-${k}
|
||||
text-${name}-${k}
|
||||
before:bg-${name}-${k}
|
||||
before:text-${name}-${k}`
|
||||
}).join(' ')}`
|
||||
}, '')
|
||||
|
||||
export const safelist = `${textSafelist} ${colorSafelist}`
|
||||
@@ -0,0 +1,31 @@
|
||||
# Frontend Shared
|
||||
|
||||
## Building
|
||||
|
||||
### For development
|
||||
|
||||
We only use Cypress Component Tests to develop the components in isolation
|
||||
|
||||
```bash
|
||||
## from repo root
|
||||
yarn workspace @packages/frontend-shared cypress:open
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
For the best development experience, you will want to use VS Code with the [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) extension. This will give you type completion inside `vue` files.
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
yarn workspace @packages/frontend-shared test-unit
|
||||
```
|
||||
|
||||
## Utility class usage
|
||||
|
||||
Windi CSS can create an awesome interactive summary showing our usage of utility classes and design tokens. Running this command will generate this report and serve it on localhost.
|
||||
|
||||
```bash
|
||||
## from this directory
|
||||
yarn windi
|
||||
```
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"projectId": "sehy69",
|
||||
"baseUrl": "http://localhost:5555",
|
||||
"viewportWidth": 800,
|
||||
"viewportHeight": 850,
|
||||
"video": false,
|
||||
"retries": {
|
||||
"runMode": 2,
|
||||
"openMode": 0
|
||||
},
|
||||
"nodeVersion": "system",
|
||||
"testFiles": "**/*.spec.{js,ts,tsx,jsx}",
|
||||
"reporter": "../../node_modules/cypress-multi-reporters/index.js",
|
||||
"reporterOptions": {
|
||||
"configFile": "../../mocha-reporter-config.json"
|
||||
},
|
||||
"component": {
|
||||
"componentFolder": "src/components"
|
||||
},
|
||||
"e2e": {
|
||||
"supportFile": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @type {import('@cypress/vite-dev-server')}
|
||||
*/
|
||||
const { startDevServer } = require('@cypress/vite-dev-server')
|
||||
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
|
||||
if (config.testingType === 'component') {
|
||||
on('dev-server:start', async (options) => {
|
||||
return startDevServer({
|
||||
options,
|
||||
viteConfig: {
|
||||
// TODO(tim): Figure out why this isn't being picked up
|
||||
optimizeDeps: {
|
||||
include: ['@headlessui/vue', 'vue-prism-component'],
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return config // IMPORTANT to return a config
|
||||
}
|
||||
@@ -15,13 +15,14 @@ import { navigationMenu } from '../../src/graphql/testNavigationMenu'
|
||||
import { query as stubQuery } from '../../src/graphql/testQuery'
|
||||
import { wizard as stubWizard } from '../../src/graphql/testWizard'
|
||||
import { app as stubApp } from '../../src/graphql/testApp'
|
||||
import { createI18n } from '@cy/i18n'
|
||||
|
||||
/**
|
||||
* This variable is mimicing ipc provided by electron.
|
||||
* It has to be loaded run before initializing GraphQL
|
||||
* because graphql uses it.
|
||||
*/
|
||||
(window as any).ipc = {
|
||||
;(window as any).ipc = {
|
||||
on: () => {},
|
||||
send: () => {},
|
||||
}
|
||||
@@ -37,7 +38,11 @@ const createContext = (): ClientTestContext => {
|
||||
}
|
||||
}
|
||||
|
||||
export const registerMountFn = ({ plugins }) => {
|
||||
export interface MountFnOptions {
|
||||
plugins?: (() => any)[]
|
||||
}
|
||||
|
||||
export const registerMountFn = ({ plugins }: MountFnOptions = {}) => {
|
||||
Cypress.Commands.add(
|
||||
'mount',
|
||||
<C extends Parameters<typeof mount>[0]>(comp: C, options: CyMountOptions<C> = {}) => {
|
||||
@@ -49,6 +54,8 @@ export const registerMountFn = ({ plugins }) => {
|
||||
options?.global?.plugins?.push(pluginFn())
|
||||
})
|
||||
|
||||
options.global.plugins.push(createI18n())
|
||||
|
||||
const context = createContext()
|
||||
|
||||
options.global.plugins.push({
|
||||
@@ -75,6 +82,7 @@ export const registerMountFn = ({ plugins }) => {
|
||||
transition: false,
|
||||
},
|
||||
plugins: [
|
||||
createI18n(),
|
||||
{
|
||||
install (app) {
|
||||
app.use(urql, testUrqlClient({
|
||||
@@ -0,0 +1,5 @@
|
||||
import { registerMountFn } from './common'
|
||||
import '../../src/styles/shared.scss'
|
||||
import 'virtual:windi.css'
|
||||
|
||||
registerMountFn()
|
||||
@@ -4,29 +4,56 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build-prod": "tsc || echo 'built, with type errors'",
|
||||
"check-ts": "tsc --noEmit",
|
||||
"check-ts": "vue-tsc --noEmit",
|
||||
"clean-deps": "rimraf node_modules",
|
||||
"clean": "rimraf src/*.js src/**/*.js"
|
||||
"clean": "rimraf dist ./node_modules/.vite src/*.js src/**/*.js && echo 'cleaned'",
|
||||
"test": "yarn cypress:run && yarn types",
|
||||
"windi": "yarn windicss-analysis",
|
||||
"cypress:open": "cross-env TZ=America/New_York node ../../scripts/cypress open-ct --project ${PWD}",
|
||||
"cypress:run": "cross-env TZ=America/New_York node ../../scripts/cypress run-ct --project ${PWD}",
|
||||
"dev": "vite --open"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@antfu/utils": "^0.3.0",
|
||||
"@cypress/vite-dev-server": "0.0.0-development",
|
||||
"@cypress/vue": "0.0.0-development",
|
||||
"@headlessui/vue": "1.4.0",
|
||||
"@iconify/json": "1.1.368",
|
||||
"@iconify/vue": "3.0.0-beta.1",
|
||||
"@intlify/vite-plugin-vue-i18n": "2.4.0",
|
||||
"@testing-library/cypress": "8.0.0",
|
||||
"@urql/core": "2.3.1",
|
||||
"@urql/exchange-execute": "1.1.0",
|
||||
"@urql/exchange-graphcache": "4.3.3",
|
||||
"@urql/vue": "0.4.3",
|
||||
"@vitejs/plugin-vue": "^1.9.2",
|
||||
"@vitejs/plugin-vue-jsx": "^1.1.8",
|
||||
"@vue/compiler-core": "3.2.6",
|
||||
"@vue/compiler-dom": "3.2.6",
|
||||
"@vue/compiler-sfc": "3.2.6",
|
||||
"@windicss/plugin-interaction-variants": "1.0.0",
|
||||
"bluebird": "3.5.3",
|
||||
"classnames": "2.3.1",
|
||||
"fake-uuid": "^1.0.0",
|
||||
"graphql": "^15.5.1",
|
||||
"graphql-relay": "^0.9.0",
|
||||
"graphql-tag": "^2.12.5",
|
||||
"lodash": "^4.17.21",
|
||||
"modern-normalize": "1.1.0",
|
||||
"rimraf": "3.0.2",
|
||||
"unplugin-icons": "^0.11.4",
|
||||
"unplugin-vue-components": "^0.15.4",
|
||||
"vite": "^2.5.10",
|
||||
"vite-plugin-icons": "0.6.3",
|
||||
"vite-plugin-windicss": "^1.4.7",
|
||||
"vite-svg-loader": "^2.2.0",
|
||||
"vue": "3.2.6",
|
||||
"vue-eslint-parser": "7.11.0",
|
||||
"vue-i18n": "9.2.0-beta.1",
|
||||
"vue-i18n": "^9.2.0-beta.7",
|
||||
"vue-tsc": "^0.3.0",
|
||||
"windicss": "3.1.8",
|
||||
"windicss-analysis": "^0.3.4",
|
||||
"wonka": "^4.0.15"
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 476 B After Width: | Height: | Size: 476 B |
|
Before Width: | Height: | Size: 476 B After Width: | Height: | Size: 476 B |
|
Before Width: | Height: | Size: 440 B After Width: | Height: | Size: 440 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 650 B After Width: | Height: | Size: 650 B |
|
Before Width: | Height: | Size: 658 B After Width: | Height: | Size: 658 B |
|
Before Width: | Height: | Size: 597 B After Width: | Height: | Size: 597 B |
|
Before Width: | Height: | Size: 755 B After Width: | Height: | Size: 755 B |
|
Before Width: | Height: | Size: 763 B After Width: | Height: | Size: 763 B |
|
Before Width: | Height: | Size: 734 B After Width: | Height: | Size: 734 B |
|
Before Width: | Height: | Size: 760 B After Width: | Height: | Size: 760 B |
|
Before Width: | Height: | Size: 751 B After Width: | Height: | Size: 751 B |
|
Before Width: | Height: | Size: 743 B After Width: | Height: | Size: 743 B |
|
Before Width: | Height: | Size: 768 B After Width: | Height: | Size: 768 B |
|
Before Width: | Height: | Size: 751 B After Width: | Height: | Size: 751 B |
|
Before Width: | Height: | Size: 435 B After Width: | Height: | Size: 435 B |
|
Before Width: | Height: | Size: 424 B After Width: | Height: | Size: 424 B |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,5 +1,5 @@
|
||||
import Button from './Button.vue'
|
||||
import IconCoffee from 'virtual:vite-icons/mdi/coffee'
|
||||
import IconCoffee from '~icons/mdi/coffee'
|
||||
|
||||
describe('<Button />', () => {
|
||||
it('playground', { viewportWidth: 200, viewportHeight: 300 }, () => {
|
||||
@@ -35,13 +35,21 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
inheritAttrs: true,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, useAttrs, ButtonHTMLAttributes, FunctionalComponent, SVGAttributes } from 'vue'
|
||||
import Icon from './Icon.vue'
|
||||
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import { computed, useAttrs } from 'vue'
|
||||
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import type { ButtonHTMLAttributes, FunctionalComponent, SVGAttributes } from 'vue'
|
||||
|
||||
const VariantClassesTable = {
|
||||
primary: 'border-indigo-600 bg-indigo-600 text-white',
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, nextTick, ref } from 'vue'
|
||||
import { useI18n } from '../../composables'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -1,6 +1,6 @@
|
||||
import Icon from './Icon.vue'
|
||||
import IconCoffee from 'virtual:vite-icons/mdi/coffee'
|
||||
import IconHeart from 'virtual:vite-icons/mdi/heart'
|
||||
import IconCoffee from '~icons/mdi/coffee'
|
||||
import IconHeart from '~icons/mdi/heart'
|
||||
|
||||
describe('<Icon />', () => {
|
||||
it('handles an icon SVG', () => {
|
||||
@@ -55,10 +55,14 @@ export default {
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, useSlots, useAttrs, InputHTMLAttributes, FunctionalComponent, SVGAttributes } from 'vue'
|
||||
import _ from 'lodash'
|
||||
import IconSearch from 'virtual:vite-icons/mdi/magnify'
|
||||
import { useModelWrapper } from '../../composables'
|
||||
import Icon from './Icon.vue'
|
||||
import IconSearch from '~icons/mdi/magnify'
|
||||
|
||||
import type { InputHTMLAttributes, FunctionalComponent, SVGAttributes } from 'vue'
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import { computed, useSlots, useAttrs } from 'vue'
|
||||
import { useModelWrapper } from '../composables'
|
||||
|
||||
const slots = useSlots()
|
||||
const attrs = useAttrs()
|
||||
@@ -1,13 +1,13 @@
|
||||
import Icon from '../icon/Icon.vue'
|
||||
import Icon from './Icon.vue'
|
||||
import IconHeart from '~icons/mdi/heart'
|
||||
import { defaultMessages } from '@cy/i18n'
|
||||
import { h } from 'vue'
|
||||
import IconHeart from 'virtual:vite-icons/mdi/heart'
|
||||
import { defaultMessages } from '../../locales/i18n'
|
||||
|
||||
const selectText = defaultMessages.components.select
|
||||
|
||||
// Subject Under Test
|
||||
import Select from './Select.vue'
|
||||
|
||||
const selectText = defaultMessages.components.select
|
||||
|
||||
// Selectors
|
||||
const optionsSelector = '[role=option]'
|
||||
const inputSelector = '[aria-haspopup=true]'
|
||||
@@ -141,11 +141,11 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Listbox, ListboxButton, ListboxLabel, ListboxOption, ListboxOptions } from '@headlessui/vue'
|
||||
import IconCheck from 'virtual:vite-icons/mdi/check'
|
||||
import IconCaret from 'virtual:vite-icons/mdi/caret'
|
||||
import Icon from '../icon/Icon.vue'
|
||||
import IconCheck from '~icons/mdi/check'
|
||||
import IconCaret from '~icons/mdi/caret'
|
||||
import Icon from './Icon.vue'
|
||||
import { get } from 'lodash'
|
||||
import { useI18n } from '../../composables'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { computed } from 'vue'
|
||||
|
||||
/**
|
||||
* This snippet comes from Thorsten Lünborg and is explained in this blog post https://www.vuemastery.com/blog/vue-3-data-down-events-up/
|
||||
* @example const localValue = useModelWrapper(props, emit, 'modelValue')
|
||||
*/
|
||||
export function useModelWrapper<T, N extends string = 'modelValue'> (
|
||||
props: T,
|
||||
emit: (event: N, ...args: any[]) => void,
|
||||
name = 'modelValue',
|
||||
) {
|
||||
return computed({
|
||||
get: () => props[name],
|
||||
set: (value: any) => {
|
||||
emit(`update:${name}` as any, value)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
import { createI18n as _createI18n } from 'vue-i18n'
|
||||
import {
|
||||
useI18n as _useI18n,
|
||||
createI18n as _createI18n,
|
||||
} from 'vue-i18n'
|
||||
|
||||
import type enUS from './en-US.json'
|
||||
// Imports a special compiled messages object
|
||||
@@ -20,3 +23,7 @@ export function createI18n (opts = {}) {
|
||||
...opts,
|
||||
})
|
||||
}
|
||||
|
||||
export function useI18n () {
|
||||
return _useI18n<{ message: MessageSchema }>({ useScope: 'global' })
|
||||
}
|
||||
@@ -0,0 +1,825 @@
|
||||
/**
|
||||
* Tailwind's Preflight Style Reset
|
||||
* https://tailwindcss.com/docs/preflight
|
||||
*
|
||||
* Why is this here?
|
||||
* 1. Tailwind doesn't publish their style reset (which is
|
||||
* derived from modern-normalize).
|
||||
* 2. WindiCSS's version of this doesn't work with third-party
|
||||
* DOM elements that it can't extract.
|
||||
*/
|
||||
|
||||
/*! tailwindcss v2.2.16 | MIT License | https://tailwindcss.com */
|
||||
/*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */
|
||||
@use 'modern-normalize/modern-normalize.css';
|
||||
|
||||
/*
|
||||
Document
|
||||
========
|
||||
*/
|
||||
|
||||
/**
|
||||
Use a better box model (opinionated).
|
||||
*/
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/**
|
||||
Use a more readable tab size (opinionated).
|
||||
*/
|
||||
|
||||
html {
|
||||
-moz-tab-size: 4;
|
||||
tab-size: 4;
|
||||
}
|
||||
|
||||
/**
|
||||
1. Correct the line height in all browsers.
|
||||
2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Sections
|
||||
========
|
||||
*/
|
||||
|
||||
/**
|
||||
Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
|
||||
*/
|
||||
|
||||
body {
|
||||
font-family:
|
||||
system-ui,
|
||||
-apple-system, /* Firefox supports this but not yet `system-ui` */
|
||||
'Segoe UI',
|
||||
Roboto,
|
||||
Helvetica,
|
||||
Arial,
|
||||
sans-serif,
|
||||
'Apple Color Emoji',
|
||||
'Segoe UI Emoji';
|
||||
}
|
||||
|
||||
/*
|
||||
Grouping content
|
||||
================
|
||||
*/
|
||||
|
||||
/**
|
||||
1. Add the correct height in Firefox.
|
||||
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
|
||||
*/
|
||||
|
||||
hr {
|
||||
height: 0; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Text-level semantics
|
||||
====================
|
||||
*/
|
||||
|
||||
/**
|
||||
Add the correct text decoration in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
Add the correct font weight in Edge and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
|
||||
2. Correct the odd 'em' font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp,
|
||||
pre {
|
||||
font-family:
|
||||
ui-monospace,
|
||||
SFMono-Regular,
|
||||
Consolas,
|
||||
'Liberation Mono',
|
||||
Menlo,
|
||||
monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
Prevent 'sub' and 'sup' elements from affecting the line height in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/*
|
||||
Tabular data
|
||||
============
|
||||
*/
|
||||
|
||||
/**
|
||||
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
|
||||
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
|
||||
*/
|
||||
|
||||
table {
|
||||
text-indent: 0; /* 1 */
|
||||
border-color: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Forms
|
||||
=====
|
||||
*/
|
||||
|
||||
/**
|
||||
1. Change the font styles in all browsers.
|
||||
2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the inheritance of text transform in Edge and Firefox.
|
||||
1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type='button'],
|
||||
[type='reset'],
|
||||
[type='submit'] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the additional ':invalid' styles in Firefox.
|
||||
See: https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737
|
||||
*/
|
||||
|
||||
:-moz-ui-invalid {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Add the correct vertical alignment in Chrome and Firefox.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
Correct the cursor style of increment and decrement buttons in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-inner-spin-button,
|
||||
::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
1. Correct the odd appearance in Chrome and Safari.
|
||||
2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type='search'] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
1. Correct the inability to style clickable types in iOS and Safari.
|
||||
2. Change font properties to 'inherit' in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
Interactive
|
||||
===========
|
||||
*/
|
||||
|
||||
/*
|
||||
Add the correct display in Chrome and Safari.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually forked from SUIT CSS Base: https://github.com/suitcss/base
|
||||
* A thin layer on top of normalize.css that provides a starting point more
|
||||
* suitable for web applications.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Removes the default spacing and border for appropriate elements.
|
||||
*/
|
||||
|
||||
blockquote,
|
||||
dl,
|
||||
dd,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
hr,
|
||||
figure,
|
||||
p,
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tailwind custom reset styles
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. Use the user's configured `sans` font-family (with Tailwind's default
|
||||
* sans-serif font stack as a fallback) as a sane default.
|
||||
* 2. Use Tailwind's default "normal" line-height so the user isn't forced
|
||||
* to override it to ensure consistency even when using the default theme.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 1 */
|
||||
line-height: 1.5; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit font-family and line-height from `html` so users can set them as
|
||||
* a class directly on the `html` element.
|
||||
*/
|
||||
|
||||
body {
|
||||
font-family: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Prevent padding and border from affecting element width.
|
||||
*
|
||||
* We used to set this in the html element and inherit from
|
||||
* the parent element for everything else. This caused issues
|
||||
* in shadow-dom-enhanced elements like <details> where the content
|
||||
* is wrapped by a div with box-sizing set to `content-box`.
|
||||
*
|
||||
* https://github.com/mozdevs/cssremedy/issues/4
|
||||
*
|
||||
*
|
||||
* 2. Allow adding a border to an element by just adding a border-width.
|
||||
*
|
||||
* By default, the way the browser specifies that an element should have no
|
||||
* border is by setting it's border-style to `none` in the user-agent
|
||||
* stylesheet.
|
||||
*
|
||||
* In order to easily add borders to elements by just setting the `border-width`
|
||||
* property, we change the default border-style for all elements to `solid`, and
|
||||
* use border-width to hide them instead. This way our `border` utilities only
|
||||
* need to set the `border-width` property instead of the entire `border`
|
||||
* shorthand, making our border utilities much more straightforward to compose.
|
||||
*
|
||||
* https://github.com/tailwindcss/tailwindcss/pull/116
|
||||
*/
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box; /* 1 */
|
||||
border-width: 0; /* 2 */
|
||||
border-style: solid; /* 2 */
|
||||
border-color: currentColor; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure horizontal rules are visible by default
|
||||
*/
|
||||
|
||||
hr {
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo the `border-style: none` reset that Normalize applies to images so that
|
||||
* our `border-{width}` utilities have the expected effect.
|
||||
*
|
||||
* The Normalize reset is unnecessary for us since we default the border-width
|
||||
* to 0 on all elements.
|
||||
*
|
||||
* https://github.com/tailwindcss/tailwindcss/issues/362
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
input::placeholder,
|
||||
textarea::placeholder {
|
||||
opacity: 1;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
button,
|
||||
[role="button"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override legacy focus reset from Normalize with modern Firefox focus styles.
|
||||
*
|
||||
* This is actually an improvement over the new defaults in Firefox in our testing,
|
||||
* as it triggers the better focus styles even for links, which still use a dotted
|
||||
* outline in Firefox by default.
|
||||
*/
|
||||
|
||||
:-moz-focusring {
|
||||
outline: auto;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset links to optimize for opt-in styling instead of
|
||||
* opt-out.
|
||||
*/
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset form element properties that are easy to forget to
|
||||
* style explicitly so you don't inadvertently introduce
|
||||
* styles that deviate from your design system. These styles
|
||||
* supplement a partial reset that is already applied by
|
||||
* normalize.css.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
padding: 0;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the configured 'mono' font family for elements that
|
||||
* are expected to be rendered with a monospace font, falling
|
||||
* back to the system monospace stack if there is no configured
|
||||
* 'mono' font family.
|
||||
*/
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Make replaced elements `display: block` by default as that's
|
||||
* the behavior you want almost all of the time. Inspired by
|
||||
* CSS Remedy, with `svg` added as well.
|
||||
*
|
||||
* https://github.com/mozdevs/cssremedy/issues/14
|
||||
*
|
||||
* 2. Add `vertical-align: middle` to align replaced elements more
|
||||
* sensibly by default when overriding `display` by adding a
|
||||
* utility like `inline`.
|
||||
*
|
||||
* This can trigger a poorly considered linting error in some
|
||||
* tools but is included by design.
|
||||
*
|
||||
* https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210
|
||||
*/
|
||||
|
||||
img,
|
||||
svg,
|
||||
video,
|
||||
canvas,
|
||||
audio,
|
||||
iframe,
|
||||
embed,
|
||||
object {
|
||||
display: block; /* 1 */
|
||||
vertical-align: middle; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrain images and videos to the parent width and preserve
|
||||
* their intrinsic aspect ratio.
|
||||
*
|
||||
* https://github.com/mozdevs/cssremedy/issues/14
|
||||
*/
|
||||
|
||||
img,
|
||||
video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the default browser behavior of the `hidden` attribute.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
*, ::before, ::after {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgba(229, 231, 235, var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Global Resets
|
||||
* -------------------------
|
||||
*/
|
||||
|
||||
// Input Resets
|
||||
// Taken from Tailwind CSS Forms -- a plugin for tailwind.
|
||||
// We could probably add these into WindiCSS directly
|
||||
// https://github.com/tailwindlabs/tailwindcss-forms
|
||||
|
||||
[multiple],
|
||||
[type=date],
|
||||
[type=datetime-local],
|
||||
[type=email],
|
||||
[type=month],
|
||||
[type=number],
|
||||
[type=password],
|
||||
[type=search],
|
||||
[type=tel],
|
||||
[type=text],
|
||||
[type=time],
|
||||
[type=url],
|
||||
[type=week],
|
||||
select,
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: #fff;
|
||||
border-color: #6b7280;
|
||||
border-width: 1px;
|
||||
border-radius: 0;
|
||||
padding-top: 0.35rem;
|
||||
padding-bottom: 0.35rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
[multiple]:focus,
|
||||
[type=date]:focus,
|
||||
[type=datetime-local]:focus,
|
||||
[type=email]:focus,
|
||||
[type=month]:focus,
|
||||
[type=number]:focus,
|
||||
[type=password]:focus,
|
||||
[type=search]:focus,
|
||||
[type=tel]:focus,
|
||||
[type=text]:focus,
|
||||
[type=time]:focus,
|
||||
[type=url]:focus,
|
||||
[type=week]:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
--tw-ring-inset: var(--tw-empty, );
|
||||
/*!*/
|
||||
/*!*/
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: #2563eb;
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
border-color: #2563eb;
|
||||
}
|
||||
|
||||
input::-moz-placeholder,
|
||||
textarea::-moz-placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input:-ms-input-placeholder,
|
||||
textarea:-ms-input-placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input::placeholder,
|
||||
textarea::placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-date-and-time-value {
|
||||
min-height: 1.5em;
|
||||
}
|
||||
|
||||
select {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||
background-position: right .5rem center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1.5em 1.5em;
|
||||
padding-right: 2.5rem;
|
||||
-webkit-print-color-adjust: exact;
|
||||
color-adjust: exact;
|
||||
}
|
||||
|
||||
[multiple] {
|
||||
background-image: initial;
|
||||
background-position: initial;
|
||||
background-repeat: unset;
|
||||
background-size: initial;
|
||||
padding-right: .75rem;
|
||||
-webkit-print-color-adjust: unset;
|
||||
color-adjust: unset;
|
||||
}
|
||||
|
||||
[type=checkbox],
|
||||
[type=radio] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
padding: 0;
|
||||
-webkit-print-color-adjust: exact;
|
||||
color-adjust: exact;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background-origin: border-box;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
flex-shrink: 0;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
color: #2563eb;
|
||||
background-color: #fff;
|
||||
border-color: #6b7280;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
[type=checkbox] {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
[type=radio] {
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
[type=checkbox]:focus,
|
||||
[type=radio]:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
--tw-ring-inset: var(--tw-empty);
|
||||
--tw-ring-offset-width: 2px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: #2563eb;
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
}
|
||||
|
||||
[type=checkbox]:checked,
|
||||
[type=radio]:checked {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[type=checkbox]:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
[type=radio]:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
[type=checkbox]:checked:focus,
|
||||
[type=checkbox]:checked:hover,
|
||||
[type=radio]:checked:focus,
|
||||
[type=radio]:checked:hover {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
[type=checkbox]:indeterminate {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[type=checkbox]:indeterminate:focus,
|
||||
[type=checkbox]:indeterminate:hover {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
[type=file] {
|
||||
background: unset;
|
||||
border-color: inherit;
|
||||
border-width: 0;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
font-size: unset;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
[type=file]:focus {
|
||||
outline: 1px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
|
||||
input[type="search"].dark {
|
||||
background: #222;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
input[type="search"].light {
|
||||
background: #fff;
|
||||
color: #222;
|
||||
}
|
||||
input[type="search"].suffix::-webkit-search-cancel-button {
|
||||
@apply pr-3.25em;
|
||||
}
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 1em;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
border-radius: 50em;
|
||||
background: url(https://pro.fontawesome.com/releases/v5.10.0/svgs/solid/times-circle.svg)
|
||||
no-repeat 50% 50%;
|
||||
background-size: contain;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
input[type="search"]:focus::-webkit-search-cancel-button {
|
||||
opacity: 0.3;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
input[type="search"].dark::-webkit-search-cancel-button {
|
||||
filter: invert(1);
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
@use './normalize.scss';
|
||||
|
||||
/* Define the "system" font family */
|
||||
@font-face {
|
||||
font-family: system;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local(".SFNSText-Light"), local(".HelveticaNeueDeskInterface-Light"),
|
||||
local(".LucidaGrandeUI"), local("Ubuntu Light"), local("Segoe UI Light"),
|
||||
local("Roboto-Light"), local("DroidSans"), local("Tahoma");
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
em {
|
||||
@apply text-purple-400 not-italic;
|
||||
}
|
||||
|
||||
a {
|
||||
@apply text-indigo-600 hover:underline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
* -------------------------
|
||||
*/
|
||||
|
||||
// Hides the scrollbar when overflow: auto. Use this sparingly -- it's not accessible!
|
||||
.hide-scrollbar {
|
||||
scrollbar-width: 0; // Firefox
|
||||
|
||||
// Chrome
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Resets
|
||||
* -------------------------
|
||||
*/
|
||||
|
||||
// Input Resets
|
||||
// Taken from Tailwind CSS Forms -- a plugin for tailwind.
|
||||
// We could probably add these into WindiCSS directly
|
||||
// https://github.com/tailwindlabs/tailwindcss-forms
|
||||
|
||||
[multiple],
|
||||
[type=date],
|
||||
[type=datetime-local],
|
||||
[type=email],
|
||||
[type=month],
|
||||
[type=number],
|
||||
[type=password],
|
||||
[type=search],
|
||||
[type=tel],
|
||||
[type=text],
|
||||
[type=time],
|
||||
[type=url],
|
||||
[type=week],
|
||||
select,
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: #fff;
|
||||
border-color: #6b7280;
|
||||
border-width: 1px;
|
||||
border-radius: 0;
|
||||
padding-top: 0.35rem;
|
||||
padding-bottom: 0.35rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
[multiple]:focus,
|
||||
[type=date]:focus,
|
||||
[type=datetime-local]:focus,
|
||||
[type=email]:focus,
|
||||
[type=month]:focus,
|
||||
[type=number]:focus,
|
||||
[type=password]:focus,
|
||||
[type=search]:focus,
|
||||
[type=tel]:focus,
|
||||
[type=text]:focus,
|
||||
[type=time]:focus,
|
||||
[type=url]:focus,
|
||||
[type=week]:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
--tw-ring-inset: var(--tw-empty, );
|
||||
/*!*/
|
||||
/*!*/
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: #2563eb;
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
border-color: #2563eb;
|
||||
}
|
||||
|
||||
input::-moz-placeholder,
|
||||
textarea::-moz-placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input:-ms-input-placeholder,
|
||||
textarea:-ms-input-placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input::placeholder,
|
||||
textarea::placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-date-and-time-value {
|
||||
min-height: 1.5em;
|
||||
}
|
||||
|
||||
select {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||
background-position: right .5rem center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1.5em 1.5em;
|
||||
padding-right: 2.5rem;
|
||||
-webkit-print-color-adjust: exact;
|
||||
color-adjust: exact;
|
||||
}
|
||||
|
||||
[multiple] {
|
||||
background-image: initial;
|
||||
background-position: initial;
|
||||
background-repeat: unset;
|
||||
background-size: initial;
|
||||
padding-right: .75rem;
|
||||
-webkit-print-color-adjust: unset;
|
||||
color-adjust: unset;
|
||||
}
|
||||
|
||||
[type=checkbox],
|
||||
[type=radio] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
padding: 0;
|
||||
-webkit-print-color-adjust: exact;
|
||||
color-adjust: exact;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background-origin: border-box;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
flex-shrink: 0;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
color: #2563eb;
|
||||
background-color: #fff;
|
||||
border-color: #6b7280;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
[type=checkbox] {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
[type=radio] {
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
[type=checkbox]:focus,
|
||||
[type=radio]:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
--tw-ring-inset: var(--tw-empty);
|
||||
--tw-ring-offset-width: 2px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: #2563eb;
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
}
|
||||
|
||||
[type=checkbox]:checked,
|
||||
[type=radio]:checked {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[type=checkbox]:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
[type=radio]:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
[type=checkbox]:checked:focus,
|
||||
[type=checkbox]:checked:hover,
|
||||
[type=radio]:checked:focus,
|
||||
[type=radio]:checked:hover {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
[type=checkbox]:indeterminate {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[type=checkbox]:indeterminate:focus,
|
||||
[type=checkbox]:indeterminate:hover {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
[type=file] {
|
||||
background: unset;
|
||||
border-color: inherit;
|
||||
border-width: 0;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
font-size: unset;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
[type=file]:focus {
|
||||
outline: 1px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
|
||||
input[type="search"].dark {
|
||||
background: #222;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
input[type="search"].light {
|
||||
background: #fff;
|
||||
color: #222;
|
||||
}
|
||||
input[type="search"].suffix::-webkit-search-cancel-button {
|
||||
@apply pr-3.25em;
|
||||
}
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 1em;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
border-radius: 50em;
|
||||
background: url(https://pro.fontawesome.com/releases/v5.10.0/svgs/solid/times-circle.svg)
|
||||
no-repeat 50% 50%;
|
||||
background-size: contain;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
input[type="search"]:focus::-webkit-search-cancel-button {
|
||||
opacity: 0.3;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
input[type="search"].dark::-webkit-search-cancel-button {
|
||||
filter: invert(1);
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"include": ["src/**/*.vue", "src/**/*.tsx", "cypress/**/*.ts"],
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
"target": "esnext",
|
||||
@@ -48,7 +47,21 @@
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": ["../driver/src"], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [] /* List of folders to include type definitions from. */
|
||||
"types": ["chrome", "./vue-shims", "./vite-env", "vite-plugin-icons", "@intlify/vite-plugin-vue-i18n/client", "@testing-library/cypress", "cypress-file-upload"], /* Type declaration files to be included in compilation. */
|
||||
|
||||
/* Type declaration files to be included in compilation. */
|
||||
"paths": {
|
||||
"@cy/i18n": ["../frontend-shared/src/locales/i18n"],
|
||||
"@cy/components/*": ["../frontend-shared/src/components/*"]
|
||||
},
|
||||
"types": [
|
||||
"chrome",
|
||||
"./vue-shims",
|
||||
"./vite-env",
|
||||
"@intlify/vite-plugin-vue-i18n/client",
|
||||
"@testing-library/cypress",
|
||||
"cypress-file-upload",
|
||||
"cypress"
|
||||
],
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"noErrorTruncation": true,
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
/// <reference types="vite/client" />
|
||||
/// <reference types="vite-plugin-pages/client" />
|
||||
/// <reference types="vite-plugin-vue-layouts/client" />
|
||||
/// <reference types="vite-svg-loader" />
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import path from 'path'
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import WindiCSS from 'vite-plugin-windicss'
|
||||
import VueI18n from '@intlify/vite-plugin-vue-i18n'
|
||||
import VueSvgLoader from 'vite-svg-loader'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import Icons from 'unplugin-icons/vite'
|
||||
import IconsResolver from 'unplugin-icons/resolver'
|
||||
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
|
||||
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import type { UserConfig } from 'vite'
|
||||
import type { ArgumentsType } from '@antfu/utils'
|
||||
|
||||
type PluginOptions = {
|
||||
plugins?: any[]
|
||||
|
||||
// These types aren't publicly exported
|
||||
vueI18nOptions?: ArgumentsType<typeof VueI18n>[0]
|
||||
iconsOptions?: ArgumentsType<typeof Icons>[0]
|
||||
componentsOptions?: ArgumentsType<typeof Components>[0]
|
||||
}
|
||||
|
||||
const base = './'
|
||||
|
||||
const alias = {
|
||||
'@cy/components': path.resolve(__dirname, './src/components'),
|
||||
|
||||
// import { defaultMessages, useI18n } from '@cy/i18n'
|
||||
'@cy/i18n': path.resolve(__dirname, './src/locales/i18n'),
|
||||
}
|
||||
|
||||
const makePlugins = (plugins) => {
|
||||
return ([
|
||||
vue(),
|
||||
vueJsx(),
|
||||
VueI18n({
|
||||
include: path.resolve(__dirname, './src/locales/**'),
|
||||
...plugins.vueI18nOptions,
|
||||
}),
|
||||
Icons({
|
||||
customCollections: {
|
||||
// ~icons/cy/book-x16
|
||||
cy: FileSystemIconLoader(path.resolve(__dirname, './src/assets/icons')),
|
||||
...plugins.iconsOptions?.customCollections,
|
||||
},
|
||||
...plugins.iconsOptions,
|
||||
}),
|
||||
Components({
|
||||
// <i-cy-book-x16/>
|
||||
resolvers: IconsResolver({
|
||||
customCollections: ['cy'],
|
||||
}),
|
||||
...plugins?.componentsOptions,
|
||||
}),
|
||||
WindiCSS(),
|
||||
VueSvgLoader(),
|
||||
// For new plugins only! Merge options for shared plugins via PluginOptions.
|
||||
...(plugins?.plugins || []),
|
||||
])
|
||||
}
|
||||
|
||||
export const makeConfig = (config: Partial<UserConfig> = {}, plugins: PluginOptions = {}): UserConfig => {
|
||||
// Don't overwrite plugins
|
||||
delete config.plugins
|
||||
|
||||
return {
|
||||
base,
|
||||
|
||||
// Production-only build options
|
||||
build: {
|
||||
minify: false,
|
||||
},
|
||||
|
||||
resolve: { alias },
|
||||
|
||||
// You cannot add or remove arbitrary options from shared plugins.
|
||||
// Please use the PluginsOverride option for this.
|
||||
plugins: makePlugins(plugins),
|
||||
define: {
|
||||
'process.env': {
|
||||
CYPRESS_INTERNAL_ENV: 'development',
|
||||
},
|
||||
'setImmediate': {},
|
||||
},
|
||||
...config,
|
||||
}
|
||||
}
|
||||
|
||||
export default defineConfig(makeConfig())
|
||||
@@ -3,3 +3,30 @@ declare module 'virtual:*' {
|
||||
const src: Component
|
||||
export default src
|
||||
}
|
||||
|
||||
declare module 'virtual:icons/*' {
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import { FunctionalComponent, SVGAttributes } from 'vue'
|
||||
const component: FunctionalComponent<SVGAttributes>
|
||||
export default component
|
||||
}
|
||||
declare module '~icons/*' {
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import { FunctionalComponent, SVGAttributes } from 'vue'
|
||||
const component: FunctionalComponent<SVGAttributes>
|
||||
export default component
|
||||
}
|
||||
|
||||
declare module '~icons/cy/*' {
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import { FunctionalComponent, SVGAttributes } from 'vue'
|
||||
const component: FunctionalComponent<SVGAttributes>
|
||||
export default component
|
||||
}
|
||||
|
||||
declare module '~icons/mdi/*' {
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import { FunctionalComponent, SVGAttributes } from 'vue'
|
||||
const component: FunctionalComponent<SVGAttributes>
|
||||
export default component
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { defineConfig } from 'windicss/helpers'
|
||||
import InteractionVariants from '@windicss/plugin-interaction-variants'
|
||||
import { IconDuotoneColorsPlugin } from './.windicss/icon-color-plugins'
|
||||
import { safelist } from './.windicss/safelist'
|
||||
import { colors } from './.windicss/colors'
|
||||
|
||||
export default defineConfig({
|
||||
// This adds !important to all utility classes. https://csswizardry.com/2016/05/the-importance-of-important/
|
||||
important: true,
|
||||
theme: {
|
||||
extend: {
|
||||
gridTemplateColumns: {
|
||||
launchpad: '64px 1fr',
|
||||
},
|
||||
gridTemplateRows: {
|
||||
launchpad: '64px 1fr',
|
||||
},
|
||||
colors,
|
||||
},
|
||||
},
|
||||
safelist,
|
||||
variants: {
|
||||
backgroundColor: ['group-focus-within', 'group-focus-visible', 'group-active', 'group-visited', 'group-disabled', 'hocus', 'group-hocus', 'can-hover', 'no-hover'],
|
||||
},
|
||||
plugins: [
|
||||
InteractionVariants,
|
||||
IconDuotoneColorsPlugin,
|
||||
],
|
||||
extract: {
|
||||
// accepts globs and file paths relative to project root
|
||||
include: ['index.html', '**/*.{vue,html,tsx}', '../frontend-shared/**/*.{vue,html,tsx}'],
|
||||
exclude: ['node_modules/**/*', '.git/**/*'],
|
||||
},
|
||||
})
|
||||
@@ -1,4 +1,3 @@
|
||||
import { registerMountFn } from '@packages/frontend-shared/cypress/support/commands'
|
||||
import { createI18n } from '@packages/launchpad/src/locales/i18n'
|
||||
import { registerMountFn } from '@packages/frontend-shared/cypress/support/common'
|
||||
|
||||
registerMountFn({ plugins: [() => createI18n()] })
|
||||
registerMountFn()
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"@iconify/json": "1.1.368",
|
||||
"@iconify/vue": "3.0.0-beta.1",
|
||||
"@intlify/vite-plugin-vue-i18n": "2.4.0",
|
||||
"@packages/frontend-shared": "0.0.0-development",
|
||||
"@testing-library/cypress": "8.0.0",
|
||||
"@urql/core": "2.3.1",
|
||||
"@urql/devtools": "2.0.3",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import HeartIcon from 'virtual:vite-icons/mdi/heart'
|
||||
import HeartIcon from '~icons/mdi/heart'
|
||||
import InlineCodeEditor from './InlineCodeEditor.vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
|
||||
@@ -48,7 +48,11 @@ import _ from 'lodash'
|
||||
import 'prismjs'
|
||||
import '@packages/reporter/src/errors/prism.scss'
|
||||
import CodeEditor from './CodeEditor.vue'
|
||||
import { FunctionalComponent, SVGAttributes, computed, useSlots } from 'vue'
|
||||
import Icon from '@cy/components/Icon.vue'
|
||||
import type { FunctionalComponent, SVGAttributes } from 'vue'
|
||||
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import { computed, useSlots } from 'vue'
|
||||
import { useModelWrapper } from '../../composables'
|
||||
|
||||
const slots = useSlots()
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { computed } from 'vue'
|
||||
import { useI18n as _useI18n } from 'vue-i18n'
|
||||
import type { MessageSchema } from '../locales/schema'
|
||||
|
||||
/**
|
||||
* This snippet comes from Thorsten Lünborg and is explained in this blog post https://www.vuemastery.com/blog/vue-3-data-down-events-up/
|
||||
@@ -18,7 +16,3 @@ export function useModelWrapper<T, N extends string = 'modelValue'> (
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useI18n () {
|
||||
return _useI18n<{ message: MessageSchema }>({ useScope: 'global' })
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defaultMessages } from '../locales/i18n'
|
||||
import { defaultMessages } from '@cy/i18n'
|
||||
import GlobalEmpty from './GlobalEmpty.vue'
|
||||
|
||||
const emptyText = defaultMessages.globalPage.empty
|
||||
|
||||
@@ -47,8 +47,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from '../composables'
|
||||
import IconPlaceholder from 'virtual:vite-icons/icons8/circle-thin'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
import IconPlaceholder from '~icons/icons8/circle-thin'
|
||||
import { FileSelector, Dropzone } from 'vue3-file-selector'
|
||||
import { ref, watch, onMounted } from 'vue'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defaultMessages } from '../locales/i18n'
|
||||
import { defaultMessages } from '@cy/i18n'
|
||||
import GlobalPage from './GlobalPage.vue'
|
||||
|
||||
const searchSelector = `input[placeholder="${defaultMessages.globalPage.searchPlaceholder}"`
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defaultMessages } from '../locales/i18n'
|
||||
import { defaultMessages } from '@cy/i18n'
|
||||
import GlobalPageHeader from './GlobalPageHeader.vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Button from '../components/button/Button.vue'
|
||||
import Input from '../components/input/Input.vue'
|
||||
import IconPlus from 'virtual:vite-icons/mdi/plus'
|
||||
import { useI18n, useModelWrapper } from '../composables'
|
||||
import Button from '@cy/components/Button.vue'
|
||||
import Input from '@cy/components/Input.vue'
|
||||
import IconPlus from '~icons/mdi/plus'
|
||||
import { useModelWrapper } from '../composables'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import Icon from '../components/icon/Icon.vue'
|
||||
import IconChecked from 'virtual:vite-icons/mdi/check-circle'
|
||||
import IconX from 'virtual:vite-icons/mdi/plus-circle'
|
||||
import IconPending from 'virtual:vite-icons/mdi/refresh-circle'
|
||||
import Icon from '@cy/components/Icon.vue'
|
||||
import IconChecked from '~icons/mdi/check-circle'
|
||||
import IconX from '~icons/mdi/plus-circle'
|
||||
import IconPending from '~icons/mdi/refresh-circle'
|
||||
|
||||
import { getTimeAgo } from '../utils/time'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defaultMessages } from '../locales/i18n'
|
||||
import { defaultMessages } from '@cy/i18n'
|
||||
import WelcomeGuide from './WelcomeGuide.vue'
|
||||
|
||||
const welcomeGuide = defaultMessages.welcomeGuide.header
|
||||
|
||||
@@ -60,12 +60,12 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { useI18n } from '../composables'
|
||||
import Checkbox from '../components/checkbox/Checkbox.vue'
|
||||
import Button from '../components/button/Button.vue'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
import Checkbox from '@cy/components/Checkbox.vue'
|
||||
import Button from '@cy/components/Button.vue'
|
||||
import WelcomeGuideLinks from './WelcomeGuideLinks.vue'
|
||||
import IconCircleX from 'virtual:vite-icons/akar-icons/circle-x'
|
||||
import IconPlaceholder from 'virtual:vite-icons/icons8/circle-thin'
|
||||
import IconCircleX from '~icons/akar-icons/circle-x'
|
||||
import IconPlaceholder from '~icons/icons8/circle-thin'
|
||||
|
||||
const projects = [
|
||||
{ path: '~/Documents/GitHub/web' },
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Button from '../components/button/Button.vue'
|
||||
import Button from '@cy/components/Button.vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'itemSelected', item: Record<string, string>): void
|
||||
|
||||
@@ -68,10 +68,10 @@ import bottomBackground from '../images/bottom_filler.svg'
|
||||
import { gql } from '@urql/core'
|
||||
import { useMutation, useQuery } from '@urql/vue'
|
||||
import { LayoutDocument, NavigationMenuSetItemDocument, NavItem } from '../generated/graphql'
|
||||
import IconDashboardLine from 'virtual:vite-icons/clarity/dashboard-line'
|
||||
import IconTerminalLine from 'virtual:vite-icons/clarity/terminal-line'
|
||||
import IconSettingsLine from 'virtual:vite-icons/clarity/settings-line'
|
||||
import IconRunsLine from 'virtual:vite-icons/clarity/bullet-list-line'
|
||||
import IconDashboardLine from '~icons/clarity/dashboard-line'
|
||||
import IconTerminalLine from '~icons/clarity/terminal-line'
|
||||
import IconSettingsLine from '~icons/clarity/settings-line'
|
||||
import IconRunsLine from '~icons/clarity/bullet-list-line'
|
||||
|
||||
gql`
|
||||
query Layout {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import SideBarItem from './SideBarItem.vue'
|
||||
import IconCoffee from 'virtual:vite-icons/mdi/coffee'
|
||||
import IconCoffee from '~icons/mdi/coffee'
|
||||
import { SideBarItemFragmentDoc } from '../generated/graphql-test'
|
||||
|
||||
describe('<SideBarItem />', { viewportWidth: 200, viewportHeight: 150 }, () => {
|
||||
|
||||
@@ -18,8 +18,12 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Icon from '../components/icon/Icon.vue'
|
||||
import { HTMLAttributes, FunctionalComponent, SVGAttributes, computed } from 'vue'
|
||||
import Icon from '@cy/components/Icon.vue'
|
||||
import { computed } from 'vue'
|
||||
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import type { FunctionalComponent, SVGAttributes, HTMLAttributes } from 'vue'
|
||||
|
||||
import type { SideBarItemFragment } from '../generated/graphql'
|
||||
import { gql } from '@urql/core'
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { createI18n as _createI18n } from 'vue-i18n'
|
||||
|
||||
import type enUS from './en-US.json'
|
||||
// Imports a special compiled messages object
|
||||
import compiledMessages from '@intlify/vite-plugin-vue-i18n/messages'
|
||||
|
||||
// The raw strings for the default language (en) used for testing
|
||||
import rawJsonMessages from './en-US.json?raw'
|
||||
|
||||
export type MessageSchema = typeof enUS
|
||||
|
||||
export const defaultMessages: MessageSchema = JSON.parse(rawJsonMessages)
|
||||
|
||||
export const VueI18n = createI18n()
|
||||
|
||||
export function createI18n (opts = {}) {
|
||||
return _createI18n<MessageSchema, 'en-US'>({
|
||||
locale: 'en-US',
|
||||
messages: compiledMessages,
|
||||
...opts,
|
||||
})
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
/**
|
||||
* define the resource schema
|
||||
*/
|
||||
|
||||
import type enUS from './en-US.json'
|
||||
|
||||
// define the locale message schema as master
|
||||
export type MessageSchema = typeof enUS
|
||||
@@ -1,285 +1 @@
|
||||
/* Define the "system" font family */
|
||||
@font-face {
|
||||
font-family: system;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local(".SFNSText-Light"), local(".HelveticaNeueDeskInterface-Light"),
|
||||
local(".LucidaGrandeUI"), local("Ubuntu Light"), local("Segoe UI Light"),
|
||||
local("Roboto-Light"), local("DroidSans"), local("Tahoma");
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
em {
|
||||
@apply text-purple-400 not-italic;
|
||||
}
|
||||
|
||||
a {
|
||||
@apply text-indigo-600 hover:underline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
* -------------------------
|
||||
*/
|
||||
|
||||
// Hides the scrollbar when overflow: auto. Use this sparingly -- it's not accessible!
|
||||
.hide-scrollbar {
|
||||
scrollbar-width: 0; // Firefox
|
||||
|
||||
// Chrome
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Resets
|
||||
* -------------------------
|
||||
*/
|
||||
|
||||
// Input Resets
|
||||
// Taken from Tailwind CSS Forms -- a plugin for tailwind.
|
||||
// We could probably add these into WindiCSS directly
|
||||
// https://github.com/tailwindlabs/tailwindcss-forms
|
||||
|
||||
[multiple],
|
||||
[type=date],
|
||||
[type=datetime-local],
|
||||
[type=email],
|
||||
[type=month],
|
||||
[type=number],
|
||||
[type=password],
|
||||
[type=search],
|
||||
[type=tel],
|
||||
[type=text],
|
||||
[type=time],
|
||||
[type=url],
|
||||
[type=week],
|
||||
select,
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: #fff;
|
||||
border-color: #6b7280;
|
||||
border-width: 1px;
|
||||
border-radius: 0;
|
||||
padding-top: 0.35rem;
|
||||
padding-bottom: 0.35rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
[multiple]:focus,
|
||||
[type=date]:focus,
|
||||
[type=datetime-local]:focus,
|
||||
[type=email]:focus,
|
||||
[type=month]:focus,
|
||||
[type=number]:focus,
|
||||
[type=password]:focus,
|
||||
[type=search]:focus,
|
||||
[type=tel]:focus,
|
||||
[type=text]:focus,
|
||||
[type=time]:focus,
|
||||
[type=url]:focus,
|
||||
[type=week]:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
--tw-ring-inset: var(--tw-empty, );
|
||||
/*!*/
|
||||
/*!*/
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: #2563eb;
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
border-color: #2563eb;
|
||||
}
|
||||
|
||||
input::-moz-placeholder,
|
||||
textarea::-moz-placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input:-ms-input-placeholder,
|
||||
textarea:-ms-input-placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input::placeholder,
|
||||
textarea::placeholder {
|
||||
color: #6b7280;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-date-and-time-value {
|
||||
min-height: 1.5em;
|
||||
}
|
||||
|
||||
select {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||
background-position: right .5rem center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1.5em 1.5em;
|
||||
padding-right: 2.5rem;
|
||||
-webkit-print-color-adjust: exact;
|
||||
color-adjust: exact;
|
||||
}
|
||||
|
||||
[multiple] {
|
||||
background-image: initial;
|
||||
background-position: initial;
|
||||
background-repeat: unset;
|
||||
background-size: initial;
|
||||
padding-right: .75rem;
|
||||
-webkit-print-color-adjust: unset;
|
||||
color-adjust: unset;
|
||||
}
|
||||
|
||||
[type=checkbox],
|
||||
[type=radio] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
padding: 0;
|
||||
-webkit-print-color-adjust: exact;
|
||||
color-adjust: exact;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background-origin: border-box;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
flex-shrink: 0;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
color: #2563eb;
|
||||
background-color: #fff;
|
||||
border-color: #6b7280;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
[type=checkbox] {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
[type=radio] {
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
[type=checkbox]:focus,
|
||||
[type=radio]:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
--tw-ring-inset: var(--tw-empty);
|
||||
--tw-ring-offset-width: 2px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-color: #2563eb;
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
}
|
||||
|
||||
[type=checkbox]:checked,
|
||||
[type=radio]:checked {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[type=checkbox]:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
[type=radio]:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
[type=checkbox]:checked:focus,
|
||||
[type=checkbox]:checked:hover,
|
||||
[type=radio]:checked:focus,
|
||||
[type=radio]:checked:hover {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
[type=checkbox]:indeterminate {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[type=checkbox]:indeterminate:focus,
|
||||
[type=checkbox]:indeterminate:hover {
|
||||
border-color: transparent;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
[type=file] {
|
||||
background: unset;
|
||||
border-color: inherit;
|
||||
border-width: 0;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
font-size: unset;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
[type=file]:focus {
|
||||
outline: 1px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
|
||||
input[type="search"].dark {
|
||||
background: #222;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
input[type="search"].light {
|
||||
background: #fff;
|
||||
color: #222;
|
||||
}
|
||||
input[type="search"].suffix::-webkit-search-cancel-button {
|
||||
@apply pr-3.25em;
|
||||
}
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 1em;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
border-radius: 50em;
|
||||
background: url(https://pro.fontawesome.com/releases/v5.10.0/svgs/solid/times-circle.svg)
|
||||
no-repeat 50% 50%;
|
||||
background-size: contain;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
input[type="search"]:focus::-webkit-search-cancel-button {
|
||||
opacity: 0.3;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
input[type="search"].dark::-webkit-search-cancel-button {
|
||||
filter: invert(1);
|
||||
}
|
||||
@use '@packages/frontend-shared/src/styles/shared.scss';
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'virtual:windi.css'
|
||||
import urql from '@urql/vue'
|
||||
import App from './App.vue'
|
||||
import { makeUrqlClient } from '@packages/frontend-shared/src/graphql/urqlClient'
|
||||
import { createI18n } from './locales/i18n'
|
||||
import { createI18n } from '@cy/i18n'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
import RunIcon from './RunIcon.vue'
|
||||
import RunResults from './RunResults.vue'
|
||||
// bx:bx-user-circle
|
||||
import IconUserCircle from 'virtual:vite-icons/bx/bx-user-circle'
|
||||
import IconUserCircle from '~icons/bx/bx-user-circle'
|
||||
// carbon:branch
|
||||
import IconBranch from 'virtual:vite-icons/carbon/branch'
|
||||
import IconBranch from '~icons/carbon/branch'
|
||||
import { gql } from '@urql/core'
|
||||
import type { RunCardFragment } from '../generated/graphql'
|
||||
import { computed } from 'vue-demi'
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
import type { RunResultsFragment } from '../generated/graphql'
|
||||
import { gql } from '@urql/core'
|
||||
// bi:check-lg
|
||||
import IconPass from 'virtual:vite-icons/bi/check-lg'
|
||||
import IconPass from '~icons/bi/check-lg'
|
||||
// eva:close-fill
|
||||
import IconFail from 'virtual:vite-icons/eva/close-fill'
|
||||
import IconFail from '~icons/eva/close-fill'
|
||||
// fa-solid:snowflake
|
||||
import IconFlake from 'virtual:vite-icons/fa-solid/snowflake'
|
||||
import IconFlake from '~icons/fa-solid/snowflake'
|
||||
// line-md:cancel
|
||||
import IconCancel from 'virtual:vite-icons/line-md/cancel'
|
||||
import IconCancel from '~icons/line-md/cancel'
|
||||
|
||||
gql`
|
||||
fragment RunResults on CloudRun {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import SettingsCard from './SettingsCard.vue'
|
||||
import IconLaptop from 'virtual:vite-icons/mdi/laptop'
|
||||
import IconLaptop from '~icons/mdi/laptop'
|
||||
|
||||
describe('<SettingsCard />', () => {
|
||||
it('renders', () => {
|
||||
|
||||
@@ -46,8 +46,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import IconCaret from 'virtual:vite-icons/mdi/caret'
|
||||
import Icon from '../components/icon/Icon.vue'
|
||||
import IconCaret from '~icons/mdi/caret'
|
||||
import Icon from '@cy/components/Icon.vue'
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import type { FunctionalComponent, SVGAttributes } from 'vue'
|
||||
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue'
|
||||
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from '../composables'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
import SettingsCard from './SettingsCard.vue'
|
||||
import ProjectSettings from './project/ProjectSettings.vue'
|
||||
import DeviceSettings from './device/DeviceSettings.vue'
|
||||
import IconLaptop from 'virtual:vite-icons/mdi/laptop'
|
||||
import IconBook from 'virtual:vite-icons/mdi/book'
|
||||
import IconLaptop from '~icons/mdi/laptop'
|
||||
import IconBook from '~icons/mdi/book'
|
||||
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ExternalEditorSettings from './ExternalEditorSettings.vue'
|
||||
import { defaultMessages } from '../../locales/i18n'
|
||||
import { defaultMessages } from '@cy/i18n'
|
||||
|
||||
const editorText = defaultMessages.settingsPage.editor
|
||||
|
||||
|
||||
@@ -38,17 +38,17 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
import { ref } from 'vue'
|
||||
import Icon from '../../components/icon/Icon.vue'
|
||||
import Icon from '@cy/components/Icon.vue'
|
||||
import SettingsSection from '../SettingsSection.vue'
|
||||
import { useI18n } from '../../composables'
|
||||
import Select from '../../components/input/Select.vue'
|
||||
import VSCode from 'virtual:vite-icons/logos/visual-studio-code'
|
||||
import Atom from 'virtual:vite-icons/logos/atom-icon'
|
||||
import Webstorm from 'virtual:vite-icons/logos/webstorm'
|
||||
import Vim from 'virtual:vite-icons/logos/vim'
|
||||
import Sublime from 'virtual:vite-icons/logos/sublimetext-icon'
|
||||
import Emacs from 'virtual:vite-icons/logos/emacs'
|
||||
import IconTerminal from 'virtual:vite-icons/mdi/terminal'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
import Select from '@cy/components/Select.vue'
|
||||
import VSCode from '~icons/logos/visual-studio-code'
|
||||
import Atom from '~icons/logos/atom-icon'
|
||||
import Webstorm from '~icons/logos/webstorm'
|
||||
import Vim from '~icons/logos/vim'
|
||||
import Sublime from '~icons/logos/sublimetext-icon'
|
||||
import Emacs from '~icons/logos/emacs'
|
||||
import IconTerminal from '~icons/mdi/terminal'
|
||||
|
||||
// TODO, grab these from gql or the user's machine.
|
||||
const externalEditors = [
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import SettingsSection from '../SettingsSection.vue'
|
||||
import { useI18n } from '../../composables'
|
||||
import { useI18n } from '@cy/i18n'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Config from './Config.vue'
|
||||
import jsonObject from '../../../cypress.json?raw'
|
||||
import { defaultMessages } from '../../locales/i18n'
|
||||
import { defaultMessages } from '@cy/i18n'
|
||||
import { each } from 'lodash'
|
||||
|
||||
describe('<Config/>', () => {
|
||||
|
||||