refactor: hoppscotch ui (#2887)
* feat: hopp ui initialized * feat: button components added * feat: windi css integration * chore: package removed from hopp ui * feat: storybook added * feat: move all smart components hoppscotch-ui * fix: import issue from components/smart * fix: env input component import * feat: add hoppui to windicss config * fix: remove storybook * feat: move components from hoppscotch-ui * feat: storybook added * feat: storybook progress * feat: themeing storybook * feat: add stories * chore: package updated * chore: stories added * feat: stories added * feat: stories added * feat: icons resolved * feat: i18n composable resolved * feat: histoire added * chore: resolved prettier issue * feat: radio story added * feat: story added for all components * feat: new components added to stories * fix: resolved issues * feat: readme.md added * feat: context/provider added * chore: removed app component registry * chore: remove importing of all components in hopp-ui to allow code splitting * chore: fix vite config errors * chore: jsdoc added * chore: any replaced with smart-item * chore: i18n added to ui components * chore: clean up - removed a duplicate button --------- Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com> Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
"@codemirror/state": "^6.1.0",
|
"@codemirror/state": "^6.1.0",
|
||||||
"@codemirror/view": "^6.0.2",
|
"@codemirror/view": "^6.0.2",
|
||||||
"@hoppscotch/codemirror-lang-graphql": "workspace:^0.2.0",
|
"@hoppscotch/codemirror-lang-graphql": "workspace:^0.2.0",
|
||||||
|
"@hoppscotch/ui": "workspace:^0.0.1",
|
||||||
"@hoppscotch/data": "workspace:^0.4.4",
|
"@hoppscotch/data": "workspace:^0.4.4",
|
||||||
"@hoppscotch/js-sandbox": "workspace:^2.1.0",
|
"@hoppscotch/js-sandbox": "workspace:^2.1.0",
|
||||||
"@hoppscotch/vue-toasted": "^0.1.0",
|
"@hoppscotch/vue-toasted": "^0.1.0",
|
||||||
|
|||||||
44
packages/hoppscotch-common/src/components.d.ts
vendored
44
packages/hoppscotch-common/src/components.d.ts
vendored
@@ -26,8 +26,8 @@ declare module '@vue/runtime-core' {
|
|||||||
AppShortcutsPrompt: typeof import('./components/app/ShortcutsPrompt.vue')['default']
|
AppShortcutsPrompt: typeof import('./components/app/ShortcutsPrompt.vue')['default']
|
||||||
AppSidenav: typeof import('./components/app/Sidenav.vue')['default']
|
AppSidenav: typeof import('./components/app/Sidenav.vue')['default']
|
||||||
AppSupport: typeof import('./components/app/Support.vue')['default']
|
AppSupport: typeof import('./components/app/Support.vue')['default']
|
||||||
ButtonPrimary: typeof import('./components/button/Primary.vue')['default']
|
ButtonPrimary: typeof import('./../../hoppscotch-ui/src/components/button/Primary.vue')['default']
|
||||||
ButtonSecondary: typeof import('./components/button/Secondary.vue')['default']
|
ButtonSecondary: typeof import('./../../hoppscotch-ui/src/components/button/Secondary.vue')['default']
|
||||||
Collections: typeof import('./components/collections/index.vue')['default']
|
Collections: typeof import('./components/collections/index.vue')['default']
|
||||||
CollectionsAdd: typeof import('./components/collections/Add.vue')['default']
|
CollectionsAdd: typeof import('./components/collections/Add.vue')['default']
|
||||||
CollectionsAddFolder: typeof import('./components/collections/AddFolder.vue')['default']
|
CollectionsAddFolder: typeof import('./components/collections/AddFolder.vue')['default']
|
||||||
@@ -130,30 +130,30 @@ declare module '@vue/runtime-core' {
|
|||||||
RealtimeLogEntry: typeof import('./components/realtime/LogEntry.vue')['default']
|
RealtimeLogEntry: typeof import('./components/realtime/LogEntry.vue')['default']
|
||||||
RealtimeSubscription: typeof import('./components/realtime/Subscription.vue')['default']
|
RealtimeSubscription: typeof import('./components/realtime/Subscription.vue')['default']
|
||||||
SmartAccentModePicker: typeof import('./components/smart/AccentModePicker.vue')['default']
|
SmartAccentModePicker: typeof import('./components/smart/AccentModePicker.vue')['default']
|
||||||
SmartAnchor: typeof import('./components/smart/Anchor.vue')['default']
|
SmartAnchor: typeof import('./../../hoppscotch-ui/src/components/smart/Anchor.vue')['default']
|
||||||
SmartAutoComplete: typeof import('./components/smart/AutoComplete.vue')['default']
|
SmartAutoComplete: typeof import('./../../hoppscotch-ui/src/components/smart/AutoComplete.vue')['default']
|
||||||
SmartChangeLanguage: typeof import('./components/smart/ChangeLanguage.vue')['default']
|
SmartChangeLanguage: typeof import('./components/smart/ChangeLanguage.vue')['default']
|
||||||
SmartCheckbox: typeof import('./components/smart/Checkbox.vue')['default']
|
SmartCheckbox: typeof import('./../../hoppscotch-ui/src/components/smart/Checkbox.vue')['default']
|
||||||
SmartColorModePicker: typeof import('./components/smart/ColorModePicker.vue')['default']
|
SmartColorModePicker: typeof import('./components/smart/ColorModePicker.vue')['default']
|
||||||
SmartConfirmModal: typeof import('./components/smart/ConfirmModal.vue')['default']
|
SmartConfirmModal: typeof import('./../../hoppscotch-ui/src/components/smart/ConfirmModal.vue')['default']
|
||||||
SmartEnvInput: typeof import('./components/smart/EnvInput.vue')['default']
|
SmartEnvInput: typeof import('./components/smart/EnvInput.vue')['default']
|
||||||
SmartExpand: typeof import('./components/smart/Expand.vue')['default']
|
SmartExpand: typeof import('./../../hoppscotch-ui/src/components/smart/Expand.vue')['default']
|
||||||
SmartFileChip: typeof import('./components/smart/FileChip.vue')['default']
|
SmartFileChip: typeof import('./../../hoppscotch-ui/src/components/smart/FileChip.vue')['default']
|
||||||
SmartFontSizePicker: typeof import('./components/smart/FontSizePicker.vue')['default']
|
SmartFontSizePicker: typeof import('./components/smart/FontSizePicker.vue')['default']
|
||||||
SmartIntersection: typeof import('./components/smart/Intersection.vue')['default']
|
SmartIntersection: typeof import('./../../hoppscotch-ui/src/components/smart/Intersection.vue')['default']
|
||||||
SmartItem: typeof import('./components/smart/Item.vue')['default']
|
SmartItem: typeof import('./../../hoppscotch-ui/src/components/smart/Item.vue')['default']
|
||||||
SmartLink: typeof import('./components/smart/Link.vue')['default']
|
SmartLink: typeof import('./../../hoppscotch-ui/src/components/smart/Link.vue')['default']
|
||||||
SmartModal: typeof import('./components/smart/Modal.vue')['default']
|
SmartModal: typeof import('./../../hoppscotch-ui/src/components/smart/Modal.vue')['default']
|
||||||
SmartProgressRing: typeof import('./components/smart/ProgressRing.vue')['default']
|
SmartProgressRing: typeof import('./../../hoppscotch-ui/src/components/smart/ProgressRing.vue')['default']
|
||||||
SmartRadio: typeof import('./components/smart/Radio.vue')['default']
|
SmartRadio: typeof import('./../../hoppscotch-ui/src/components/smart/Radio.vue')['default']
|
||||||
SmartRadioGroup: typeof import('./components/smart/RadioGroup.vue')['default']
|
SmartRadioGroup: typeof import('./../../hoppscotch-ui/src/components/smart/RadioGroup.vue')['default']
|
||||||
SmartSlideOver: typeof import('./components/smart/SlideOver.vue')['default']
|
SmartSlideOver: typeof import('./../../hoppscotch-ui/src/components/smart/SlideOver.vue')['default']
|
||||||
SmartSpinner: typeof import('./components/smart/Spinner.vue')['default']
|
SmartSpinner: typeof import('./../../hoppscotch-ui/src/components/smart/Spinner.vue')['default']
|
||||||
SmartTab: typeof import('./components/smart/Tab.vue')['default']
|
SmartTab: typeof import('./../../hoppscotch-ui/src/components/smart/Tab.vue')['default']
|
||||||
SmartTabs: typeof import('./components/smart/Tabs.vue')['default']
|
SmartTabs: typeof import('./../../hoppscotch-ui/src/components/smart/Tabs.vue')['default']
|
||||||
SmartToggle: typeof import('./components/smart/Toggle.vue')['default']
|
SmartToggle: typeof import('./../../hoppscotch-ui/src/components/smart/Toggle.vue')['default']
|
||||||
SmartWindow: typeof import('./components/smart/Window.vue')['default']
|
SmartWindow: typeof import('./../../hoppscotch-ui/src/components/smart/Window.vue')['default']
|
||||||
SmartWindows: typeof import('./components/smart/Windows.vue')['default']
|
SmartWindows: typeof import('./../../hoppscotch-ui/src/components/smart/Windows.vue')['default']
|
||||||
TabPrimary: typeof import('./components/tab/Primary.vue')['default']
|
TabPrimary: typeof import('./components/tab/Primary.vue')['default']
|
||||||
TabSecondary: typeof import('./components/tab/Secondary.vue')['default']
|
TabSecondary: typeof import('./components/tab/Secondary.vue')['default']
|
||||||
Teams: typeof import('./components/teams/index.vue')['default']
|
Teams: typeof import('./components/teams/index.vue')['default']
|
||||||
|
|||||||
@@ -50,9 +50,9 @@
|
|||||||
ref="tippyActions"
|
ref="tippyActions"
|
||||||
class="flex flex-col focus:outline-none"
|
class="flex flex-col focus:outline-none"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@keyup.d="documentation.$el.click()"
|
@keyup.d="documentation!.$el.click()"
|
||||||
@keyup.s="shortcuts.$el.click()"
|
@keyup.s="shortcuts!.$el.click()"
|
||||||
@keyup.c="chat.$el.click()"
|
@keyup.c="chat!.$el.click()"
|
||||||
@keyup.escape="hide()"
|
@keyup.escape="hide()"
|
||||||
>
|
>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
@@ -221,9 +221,9 @@ import { useI18n } from "@composables/i18n"
|
|||||||
import { useReadonlyStream } from "@composables/stream"
|
import { useReadonlyStream } from "@composables/stream"
|
||||||
import { currentUser$ } from "~/helpers/fb/auth"
|
import { currentUser$ } from "~/helpers/fb/auth"
|
||||||
import { TippyComponent } from "vue-tippy"
|
import { TippyComponent } from "vue-tippy"
|
||||||
import SmartItem from "@components/smart/Item.vue"
|
|
||||||
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
|
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
|
||||||
import { invokeAction } from "@helpers/actions"
|
import { invokeAction } from "@helpers/actions"
|
||||||
|
import SmartItem from "@hoppscotch/ui/src/components/smart/Item.vue"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const showDeveloperOptions = ref(false)
|
const showDeveloperOptions = ref(false)
|
||||||
@@ -271,7 +271,7 @@ const showDeveloperOptionModal = () => {
|
|||||||
|
|
||||||
// Template refs
|
// Template refs
|
||||||
const tippyActions = ref<TippyComponent | null>(null)
|
const tippyActions = ref<TippyComponent | null>(null)
|
||||||
const documentation = ref<typeof SmartItem | null>(null)
|
const documentation = ref<typeof SmartItem>()
|
||||||
const shortcuts = ref<typeof SmartItem | null>(null)
|
const shortcuts = ref<typeof SmartItem>()
|
||||||
const chat = ref<typeof SmartItem | null>(null)
|
const chat = ref<typeof SmartItem>()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ import {
|
|||||||
import { useI18n } from "@composables/i18n"
|
import { useI18n } from "@composables/i18n"
|
||||||
import { useToast } from "@composables/toast"
|
import { useToast } from "@composables/toast"
|
||||||
import { TippyComponent } from "vue-tippy"
|
import { TippyComponent } from "vue-tippy"
|
||||||
import SmartItem from "@components/smart/Item.vue"
|
import SmartItem from "@hoppscotch/ui/src/components/smart/Item.vue"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
@@ -140,9 +140,9 @@ const confirmRemove = ref(false)
|
|||||||
|
|
||||||
const tippyActions = ref<TippyComponent | null>(null)
|
const tippyActions = ref<TippyComponent | null>(null)
|
||||||
const options = ref<TippyComponent | null>(null)
|
const options = ref<TippyComponent | null>(null)
|
||||||
const edit = ref<typeof SmartItem | null>(null)
|
const edit = ref<typeof SmartItem>()
|
||||||
const duplicate = ref<typeof SmartItem | null>(null)
|
const duplicate = ref<typeof SmartItem>()
|
||||||
const deleteAction = ref<typeof SmartItem | null>(null)
|
const deleteAction = ref<typeof SmartItem>()
|
||||||
|
|
||||||
const removeEnvironment = () => {
|
const removeEnvironment = () => {
|
||||||
if (props.environmentIndex === null) return
|
if (props.environmentIndex === null) return
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ import IconCopy from "~icons/lucide/copy"
|
|||||||
import IconTrash2 from "~icons/lucide/trash-2"
|
import IconTrash2 from "~icons/lucide/trash-2"
|
||||||
import IconMoreVertical from "~icons/lucide/more-vertical"
|
import IconMoreVertical from "~icons/lucide/more-vertical"
|
||||||
import { TippyComponent } from "vue-tippy"
|
import { TippyComponent } from "vue-tippy"
|
||||||
import SmartItem from "@components/smart/Item.vue"
|
import SmartItem from "@hoppscotch/ui/src/components/smart/Item.vue"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
@@ -126,9 +126,9 @@ const confirmRemove = ref(false)
|
|||||||
|
|
||||||
const tippyActions = ref<TippyComponent | null>(null)
|
const tippyActions = ref<TippyComponent | null>(null)
|
||||||
const options = ref<TippyComponent | null>(null)
|
const options = ref<TippyComponent | null>(null)
|
||||||
const edit = ref<typeof SmartItem | null>(null)
|
const edit = ref<typeof SmartItem>()
|
||||||
const duplicate = ref<typeof SmartItem | null>(null)
|
const duplicate = ref<typeof SmartItem>()
|
||||||
const deleteAction = ref<typeof SmartItem | null>(null)
|
const deleteAction = ref<typeof SmartItem>()
|
||||||
|
|
||||||
const removeEnvironment = () => {
|
const removeEnvironment = () => {
|
||||||
pipe(
|
pipe(
|
||||||
|
|||||||
21
packages/hoppscotch-common/src/modules/ui.ts
Normal file
21
packages/hoppscotch-common/src/modules/ui.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { HoppModule } from "."
|
||||||
|
import HoppUI from "./../../../hoppscotch-ui/src"
|
||||||
|
import { HoppUIPluginOptions } from "@hoppscotch/ui/src"
|
||||||
|
import { useKeybindingDisabler } from "~/helpers/keybindings"
|
||||||
|
import { useI18n } from "vue-i18n"
|
||||||
|
const { disableKeybindings, enableKeybindings } = useKeybindingDisabler()
|
||||||
|
|
||||||
|
const HoppUIOptions: HoppUIPluginOptions = {
|
||||||
|
t: (key: string) => useI18n().t(key).toString(),
|
||||||
|
onModalOpen: disableKeybindings,
|
||||||
|
onModalClose: enableKeybindings,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default <HoppModule>{
|
||||||
|
onVueAppInit(app) {
|
||||||
|
// disable eslint for this line. it's a hack because there's some unknown type error
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
app.use(HoppUI, HoppUIOptions)
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
import { defineConfig } from "windicss/helpers"
|
import { defineConfig } from "windicss/helpers"
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
extract: {
|
||||||
|
include: ["src/**/*.{vue,html}", "../hoppscotch-ui/src/**/*.{vue,html}"],
|
||||||
|
},
|
||||||
theme: {
|
theme: {
|
||||||
container: {
|
container: {
|
||||||
center: true,
|
center: true,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/lodash": "^4.14.181",
|
"@types/lodash": "^4.14.181",
|
||||||
"typescript": "^4.6.3",
|
"typescript": "^4.6.3",
|
||||||
"vite": "^3.1.0"
|
"vite": "^3.2.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fp-ts": "^2.11.10",
|
"fp-ts": "^2.11.10",
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ export default defineConfig({
|
|||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, "src/index.ts"),
|
entry: resolve(__dirname, "src/index.ts"),
|
||||||
fileName: "hoppscotch-data",
|
fileName: "hoppscotch-data",
|
||||||
formats: [
|
formats: ["es", "cjs"],
|
||||||
"es", "cjs"
|
},
|
||||||
],
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|||||||
47
packages/hoppscotch-ui/.eslintrc.js
Normal file
47
packages/hoppscotch-ui/.eslintrc.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
require("@rushstack/eslint-patch/modern-module-resolution")
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
node: true,
|
||||||
|
jest: true,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
sourceType: "module",
|
||||||
|
requireConfigFile: false,
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
"@vue/typescript/recommended",
|
||||||
|
"plugin:vue/vue3-recommended",
|
||||||
|
"plugin:prettier/recommended",
|
||||||
|
"plugin:storybook/recommended",
|
||||||
|
],
|
||||||
|
ignorePatterns: [
|
||||||
|
"static/**/*",
|
||||||
|
"./helpers/backend/graphql.ts",
|
||||||
|
"**/*.d.ts",
|
||||||
|
"types/**/*",
|
||||||
|
],
|
||||||
|
plugins: ["vue", "prettier"],
|
||||||
|
// add your custom rules here
|
||||||
|
rules: {
|
||||||
|
semi: [2, "never"],
|
||||||
|
"import/named": "off",
|
||||||
|
// because, named import issue with typescript see: https://github.com/typescript-eslint/typescript-eslint/issues/154
|
||||||
|
"no-console": "off",
|
||||||
|
"no-debugger": process.env.HOPP_LINT_FOR_PROD === "true" ? "error" : "warn",
|
||||||
|
"prettier/prettier":
|
||||||
|
process.env.HOPP_LINT_FOR_PROD === "true" ? "error" : "warn",
|
||||||
|
"vue/multi-word-component-names": "off",
|
||||||
|
"vue/no-side-effects-in-computed-properties": "off",
|
||||||
|
"import/no-named-as-default": "off",
|
||||||
|
"import/no-named-as-default-member": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars":
|
||||||
|
process.env.HOPP_LINT_FOR_PROD === "true" ? "error" : "warn",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"import/default": "off",
|
||||||
|
"no-undef": "off",
|
||||||
|
},
|
||||||
|
}
|
||||||
27
packages/hoppscotch-ui/.gitignore
vendored
Normal file
27
packages/hoppscotch-ui/.gitignore
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
# Environment Variables
|
||||||
|
.env
|
||||||
10
packages/hoppscotch-ui/.prettierignore
Normal file
10
packages/hoppscotch-ui/.prettierignore
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.dependabot
|
||||||
|
.github
|
||||||
|
.hoppscotch
|
||||||
|
.vscode
|
||||||
|
package-lock.json
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
static
|
||||||
|
components.d.ts
|
||||||
|
src/types
|
||||||
3
packages/hoppscotch-ui/.prettierrc.js
Normal file
3
packages/hoppscotch-ui/.prettierrc.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
semi: false
|
||||||
|
}
|
||||||
57
packages/hoppscotch-ui/README.md
Normal file
57
packages/hoppscotch-ui/README.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<div align="center">
|
||||||
|
|
||||||
|
<a href="https://hoppscotch.io">
|
||||||
|
|
||||||
|
<img
|
||||||
|
|
||||||
|
src="https://avatars.githubusercontent.com/u/56705483"
|
||||||
|
|
||||||
|
alt="Hoppscotch Logo"
|
||||||
|
|
||||||
|
height="64"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
# Hoppscotch UI
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Welcome to hoppscotch-ui, a collection of presentational components for our web applications. This library is part of the hoppscotch monorepo and contains components such as buttons, spinners, modals, tabs, windows, etc.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To use the components in project, simply name the component with `directory` name as alias:
|
||||||
|
|
||||||
|
For example `Primary Button` component is in `button` directory and the file name is `Primary.vue`. So, use that you have to write `<ButtonPrimary />`
|
||||||
|
|
||||||
|
## Histoire
|
||||||
|
|
||||||
|
We've included Histoire in this library which is similar to Storybook, to make it easy to play with the components in the browser. You can run Histoire in the browser with command
|
||||||
|
|
||||||
|
`pnpm run story:dev`
|
||||||
|
|
||||||
|
You can also use [Histoire](https://histoire.dev/) to create stories for your components and test them in different scenarios.
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
This project follows [Semantic Versioning](https://semver.org/) but as the project is still pre-1.0. The code and the public exposed API should not be considered to be fixed and stable. Things can change at any time!
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT) - see [`LICENSE`](https://github.com/hoppscotch/hoppscotch/blob/main/LICENSE) for more details.
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
###### built with ❤︎ by the [Hoppscotch Team](https://github.com/hoppscotch) and [contributors](https://github.com/hoppscotch/hoppscotch/graphs/contributors).
|
||||||
|
|
||||||
|
</div>
|
||||||
7
packages/hoppscotch-ui/histoire.config.ts
Normal file
7
packages/hoppscotch-ui/histoire.config.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { HstVue } from "@histoire/plugin-vue"
|
||||||
|
import { defineConfig } from "histoire"
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
setupFile: "histoire.setup.ts",
|
||||||
|
plugins: [HstVue()],
|
||||||
|
})
|
||||||
5
packages/hoppscotch-ui/histoire.setup.ts
Normal file
5
packages/hoppscotch-ui/histoire.setup.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import "./src/assets/scss/styles.scss"
|
||||||
|
import "./src/assets/scss/themes.scss"
|
||||||
|
import "virtual:windi.css"
|
||||||
|
|
||||||
|
export function setupVue3() {}
|
||||||
82
packages/hoppscotch-ui/package.json
Normal file
82
packages/hoppscotch-ui/package.json
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
{
|
||||||
|
"name": "@hoppscotch/ui",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.1",
|
||||||
|
"scripts": {
|
||||||
|
"build": "vite build",
|
||||||
|
"story:dev": "histoire dev",
|
||||||
|
"story:build": "histoire build",
|
||||||
|
"story:preview": "histoire preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@hoppscotch/vue-toasted": "^0.1.0",
|
||||||
|
"@lezer/highlight": "^1.0.0",
|
||||||
|
"@vitejs/plugin-legacy": "^2.3.0",
|
||||||
|
"@vueuse/core": "^8.7.5",
|
||||||
|
"@vueuse/head": "^0.7.9",
|
||||||
|
"acorn-walk": "^8.2.0",
|
||||||
|
"esprima": "^4.0.1",
|
||||||
|
"events": "^3.3.0",
|
||||||
|
"fp-ts": "^2.12.1",
|
||||||
|
"globalthis": "^1.0.3",
|
||||||
|
"lodash-es": "^4.17.21",
|
||||||
|
"path": "^0.12.7",
|
||||||
|
"rxjs": "^7.5.5",
|
||||||
|
"splitpanes": "^3.1.1",
|
||||||
|
"tern": "^0.24.3",
|
||||||
|
"timers": "^0.1.1",
|
||||||
|
"tippy.js": "^6.3.7",
|
||||||
|
"url": "^0.11.0",
|
||||||
|
"util": "^0.12.4",
|
||||||
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
|
"vue": "^3.2.25",
|
||||||
|
"vue-github-button": "^3.0.3",
|
||||||
|
"vue-router": "^4.0.16",
|
||||||
|
"vue-tippy": "6.0.0-alpha.58",
|
||||||
|
"vuedraggable": "^4.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@esbuild-plugins/node-globals-polyfill": "^0.1.1",
|
||||||
|
"@esbuild-plugins/node-modules-polyfill": "^0.1.4",
|
||||||
|
"@histoire/plugin-vue": "^0.12.4",
|
||||||
|
"@iconify-json/lucide": "^1.1.40",
|
||||||
|
"@intlify/vite-plugin-vue-i18n": "^6.0.1",
|
||||||
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
|
"@types/lodash-es": "^4.17.6",
|
||||||
|
"@types/splitpanes": "^2.2.1",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.19.0",
|
||||||
|
"@typescript-eslint/parser": "^5.19.0",
|
||||||
|
"@vitejs/plugin-vue": "^3.1.0",
|
||||||
|
"@vue/compiler-sfc": "^3.2.39",
|
||||||
|
"@vue/eslint-config-typescript": "^11.0.1",
|
||||||
|
"@vue/runtime-core": "^3.2.39",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"eslint": "^8.24.0",
|
||||||
|
"eslint-plugin-prettier": "^4.2.0",
|
||||||
|
"eslint-plugin-vue": "^9.5.1",
|
||||||
|
"histoire": "^0.12.4",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
|
"rollup-plugin-polyfill-node": "^0.10.1",
|
||||||
|
"sass": "^1.53.0",
|
||||||
|
"typescript": "^4.5.4",
|
||||||
|
"unplugin-icons": "^0.14.9",
|
||||||
|
"unplugin-vue-components": "^0.21.0",
|
||||||
|
"vite": "^3.2.3",
|
||||||
|
"vite-plugin-checker": "^0.5.1",
|
||||||
|
"vite-plugin-fonts": "^0.6.0",
|
||||||
|
"vite-plugin-html-config": "^1.0.10",
|
||||||
|
"vite-plugin-inspect": "^0.7.4",
|
||||||
|
"vite-plugin-pages": "^0.26.0",
|
||||||
|
"vite-plugin-pages-sitemap": "^1.4.0",
|
||||||
|
"vite-plugin-pwa": "^0.13.1",
|
||||||
|
"vite-plugin-vue-layouts": "^0.7.0",
|
||||||
|
"vite-plugin-windicss": "^1.8.8",
|
||||||
|
"vue-loader": "^16.8.3",
|
||||||
|
"vue-tsc": "^0.38.2",
|
||||||
|
"windicss": "^3.5.6"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src",
|
||||||
|
"dist"
|
||||||
|
]
|
||||||
|
}
|
||||||
562
packages/hoppscotch-ui/src/assets/scss/styles.scss
Normal file
562
packages/hoppscotch-ui/src/assets/scss/styles.scss
Normal file
@@ -0,0 +1,562 @@
|
|||||||
|
* {
|
||||||
|
@apply backface-hidden;
|
||||||
|
@apply before:backface-hidden;
|
||||||
|
@apply after:backface-hidden;
|
||||||
|
@apply selection:bg-accentDark;
|
||||||
|
@apply selection:text-accentContrast;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
@apply antialiased;
|
||||||
|
accent-color: var(--accent-color);
|
||||||
|
font-variant-ligatures: common-ligatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
@apply bg-transparent;
|
||||||
|
@apply border-solid border-l border-dividerLight border-t-0 border-b-0 border-r-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
@apply bg-divider bg-clip-content;
|
||||||
|
@apply rounded-full;
|
||||||
|
@apply border-solid border-transparent border-4;
|
||||||
|
@apply hover:bg-dividerDark;
|
||||||
|
@apply hover:bg-clip-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
@apply w-4;
|
||||||
|
@apply h-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::placeholder,
|
||||||
|
textarea::placeholder,
|
||||||
|
.cm-placeholder {
|
||||||
|
@apply text-secondary;
|
||||||
|
@apply opacity-35;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
textarea {
|
||||||
|
@apply text-secondaryDark;
|
||||||
|
@apply font-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
@apply bg-primary;
|
||||||
|
@apply text-secondary text-body;
|
||||||
|
@apply font-medium;
|
||||||
|
@apply select-none;
|
||||||
|
@apply overflow-x-hidden;
|
||||||
|
@apply leading-body;
|
||||||
|
animation: fade 300ms forwards;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade {
|
||||||
|
0% {
|
||||||
|
@apply opacity-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
@apply opacity-100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
@apply transition-opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
@apply opacity-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-enter-active,
|
||||||
|
.slide-leave-active {
|
||||||
|
@apply transition;
|
||||||
|
@apply duration-300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-enter-from,
|
||||||
|
.slide-leave-to {
|
||||||
|
@apply transform;
|
||||||
|
@apply translate-x-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bounce-enter-active,
|
||||||
|
.bounce-leave-active {
|
||||||
|
@apply transition;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bounce-enter-from,
|
||||||
|
.bounce-leave-to {
|
||||||
|
@apply transform;
|
||||||
|
@apply scale-95;
|
||||||
|
}
|
||||||
|
|
||||||
|
.svg-icons {
|
||||||
|
@apply flex-shrink-0;
|
||||||
|
@apply overflow-hidden;
|
||||||
|
height: var(--line-height-body);
|
||||||
|
width: var(--line-height-body);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
@apply inline-flex;
|
||||||
|
@apply text-current;
|
||||||
|
@apply no-underline;
|
||||||
|
@apply transition;
|
||||||
|
@apply leading-body;
|
||||||
|
@apply focus:outline-none;
|
||||||
|
|
||||||
|
&.link {
|
||||||
|
@apply items-center;
|
||||||
|
@apply py-0.5 px-1;
|
||||||
|
@apply -my-0.5 -mx-1;
|
||||||
|
@apply text-accent;
|
||||||
|
@apply rounded;
|
||||||
|
@apply hover:text-accentDark;
|
||||||
|
@apply focus-visible:ring;
|
||||||
|
@apply focus-visible:ring-accent;
|
||||||
|
@apply focus-visible:text-accentDark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-tooltip {
|
||||||
|
.tippy-box {
|
||||||
|
@apply shadow-none;
|
||||||
|
@apply fixed;
|
||||||
|
@apply inline-flex;
|
||||||
|
@apply -mt-6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tippy-box[data-theme~="tooltip"] {
|
||||||
|
@apply bg-tooltip;
|
||||||
|
@apply border-solid border-tooltip;
|
||||||
|
@apply rounded;
|
||||||
|
@apply shadow;
|
||||||
|
|
||||||
|
.tippy-content {
|
||||||
|
@apply flex;
|
||||||
|
@apply text-tiny text-primary;
|
||||||
|
@apply font-semibold;
|
||||||
|
@apply py-1 px-2;
|
||||||
|
@apply truncate;
|
||||||
|
@apply leading-normal;
|
||||||
|
@apply items-center;
|
||||||
|
|
||||||
|
kbd {
|
||||||
|
@apply hidden;
|
||||||
|
@apply font-sans;
|
||||||
|
@apply bg-gray-500/45;
|
||||||
|
@apply text-primaryLight;
|
||||||
|
@apply rounded-sm;
|
||||||
|
@apply px-1;
|
||||||
|
@apply my-0 ml-1;
|
||||||
|
@apply truncate;
|
||||||
|
@apply sm:inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.env-icon {
|
||||||
|
@apply transition;
|
||||||
|
@apply inline-flex;
|
||||||
|
@apply items-center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tippy-svg-arrow {
|
||||||
|
svg:first-child {
|
||||||
|
@apply fill-tooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg:last-child {
|
||||||
|
@apply fill-tooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tippy-box[data-theme~="popover"] {
|
||||||
|
@apply bg-popover;
|
||||||
|
@apply border-solid border-dividerDark;
|
||||||
|
@apply rounded;
|
||||||
|
@apply shadow-lg;
|
||||||
|
|
||||||
|
.tippy-content {
|
||||||
|
@apply flex flex-col;
|
||||||
|
@apply max-h-56;
|
||||||
|
@apply items-stretch;
|
||||||
|
@apply overflow-y-auto;
|
||||||
|
@apply text-secondary text-body;
|
||||||
|
@apply p-2;
|
||||||
|
@apply leading-normal;
|
||||||
|
@apply focus:outline-none;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tippy-svg-arrow {
|
||||||
|
svg:first-child {
|
||||||
|
@apply fill-dividerDark;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg:last-child {
|
||||||
|
@apply fill-popover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-v-tippy] {
|
||||||
|
@apply flex flex-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
[interactive] > div {
|
||||||
|
@apply flex flex-1;
|
||||||
|
@apply h-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
@apply border-b border-dividerLight;
|
||||||
|
@apply my-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
@apply font-bold;
|
||||||
|
@apply text-secondaryDark text-lg;
|
||||||
|
@apply tracking-tight;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input,
|
||||||
|
.select,
|
||||||
|
.textarea {
|
||||||
|
@apply flex;
|
||||||
|
@apply w-full;
|
||||||
|
@apply py-2 px-4;
|
||||||
|
@apply bg-transparent;
|
||||||
|
@apply rounded;
|
||||||
|
@apply text-secondaryDark;
|
||||||
|
@apply border border-divider;
|
||||||
|
@apply focus-visible:border-dividerDark;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
textarea,
|
||||||
|
button {
|
||||||
|
@apply truncate;
|
||||||
|
@apply transition;
|
||||||
|
@apply text-body;
|
||||||
|
@apply leading-body;
|
||||||
|
@apply focus:outline-none;
|
||||||
|
@apply disabled:cursor-not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input[type="file"],
|
||||||
|
.input[type="radio"],
|
||||||
|
#installPWA {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input ~ label {
|
||||||
|
@apply absolute;
|
||||||
|
@apply px-2 py-0.5;
|
||||||
|
@apply m-2;
|
||||||
|
@apply rounded;
|
||||||
|
@apply transition;
|
||||||
|
@apply origin-top-left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input:focus-within ~ label,
|
||||||
|
.floating-input:not(:placeholder-shown) ~ label {
|
||||||
|
@apply bg-primary;
|
||||||
|
@apply transform;
|
||||||
|
@apply origin-top-left;
|
||||||
|
@apply scale-75;
|
||||||
|
@apply translate-x-1 -translate-y-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input:focus-within ~ label {
|
||||||
|
@apply text-secondaryDark;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input ~ .end-actions {
|
||||||
|
@apply absolute;
|
||||||
|
@apply right-0.2;
|
||||||
|
@apply inset-y-0;
|
||||||
|
@apply flex;
|
||||||
|
@apply items-center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input:has(~ .end-actions) {
|
||||||
|
@apply pr-12;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.ace_editor {
|
||||||
|
@apply font-mono;
|
||||||
|
@apply resize-none;
|
||||||
|
@apply z-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select {
|
||||||
|
@apply appearance-none;
|
||||||
|
@apply cursor-pointer;
|
||||||
|
|
||||||
|
&::-ms-expand {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-wrapper {
|
||||||
|
@apply flex flex-1;
|
||||||
|
@apply relative;
|
||||||
|
@apply after:absolute;
|
||||||
|
@apply after:flex;
|
||||||
|
@apply after:inset-y-0;
|
||||||
|
@apply after:items-center;
|
||||||
|
@apply after:justify-center;
|
||||||
|
@apply after:pointer-events-none;
|
||||||
|
@apply after:font-icon;
|
||||||
|
@apply after:text-secondaryLight;
|
||||||
|
@apply after:right-3;
|
||||||
|
@apply after:content-["\e313"];
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-response {
|
||||||
|
@apply text-pink-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-response {
|
||||||
|
@apply text-green-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.redir-response {
|
||||||
|
@apply text-yellow-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cl-error-response {
|
||||||
|
@apply text-red-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sv-error-response {
|
||||||
|
@apply text-red-600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.missing-data-response {
|
||||||
|
@apply text-secondaryLight;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toasted-container {
|
||||||
|
@apply max-w-md;
|
||||||
|
|
||||||
|
.toasted {
|
||||||
|
&.toasted-primary {
|
||||||
|
@apply px-4 py-2;
|
||||||
|
@apply bg-tooltip;
|
||||||
|
@apply border-secondaryDark;
|
||||||
|
@apply text-primary text-body;
|
||||||
|
@apply justify-between;
|
||||||
|
@apply shadow-lg;
|
||||||
|
@apply font-semibold;
|
||||||
|
@apply transition;
|
||||||
|
@apply leading-body;
|
||||||
|
@apply sm:rounded;
|
||||||
|
@apply sm:border;
|
||||||
|
|
||||||
|
.action {
|
||||||
|
@apply relative;
|
||||||
|
@apply flex flex-shrink-0;
|
||||||
|
@apply text-body;
|
||||||
|
@apply px-4;
|
||||||
|
@apply my-1;
|
||||||
|
@apply ml-auto;
|
||||||
|
@apply normal-case;
|
||||||
|
@apply font-semibold;
|
||||||
|
@apply leading-body;
|
||||||
|
@apply tracking-normal;
|
||||||
|
@apply rounded;
|
||||||
|
@apply last:ml-4;
|
||||||
|
@apply sm:ml-8;
|
||||||
|
@apply before:absolute;
|
||||||
|
@apply before:bg-current;
|
||||||
|
@apply before:opacity-10;
|
||||||
|
@apply before:inset-0;
|
||||||
|
@apply before:transition;
|
||||||
|
@apply before:content-DEFAULT;
|
||||||
|
@apply hover:no-underline;
|
||||||
|
@apply hover:before:opacity-20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.info {
|
||||||
|
@apply bg-accent;
|
||||||
|
@apply text-accentContrast;
|
||||||
|
@apply border-accentDark;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
@apply bg-red-200;
|
||||||
|
@apply text-red-800;
|
||||||
|
@apply border-red-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
@apply bg-green-200;
|
||||||
|
@apply text-green-800;
|
||||||
|
@apply border-green-400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.smart-splitter .splitpanes__splitter {
|
||||||
|
@apply relative;
|
||||||
|
@apply bg-primaryLight;
|
||||||
|
@apply before:absolute;
|
||||||
|
@apply before:inset-0;
|
||||||
|
@apply before:bg-accentLight;
|
||||||
|
@apply before:opacity-0;
|
||||||
|
@apply before:z-20;
|
||||||
|
@apply before:transition;
|
||||||
|
@apply before:content-DEFAULT;
|
||||||
|
@apply after:absolute;
|
||||||
|
@apply after:inset-0;
|
||||||
|
@apply after:z-20;
|
||||||
|
@apply after:transition;
|
||||||
|
@apply after:flex;
|
||||||
|
@apply after:items-center;
|
||||||
|
@apply after:justify-center;
|
||||||
|
@apply after:text-dividerDark;
|
||||||
|
@apply after:font-icon;
|
||||||
|
@apply hover:before:opacity-100;
|
||||||
|
@apply hover:after:text-accentDark;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-splitter .splitpanes__splitter {
|
||||||
|
@apply relative;
|
||||||
|
@apply bg-primaryLight;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smart-splitter.splitpanes--vertical > .splitpanes__splitter {
|
||||||
|
@apply w-1;
|
||||||
|
@apply before:-left-0.5;
|
||||||
|
@apply before:-right-0.5;
|
||||||
|
@apply before:h-full;
|
||||||
|
@apply after:content-["\e5d4"];
|
||||||
|
}
|
||||||
|
|
||||||
|
.smart-splitter.splitpanes--horizontal > .splitpanes__splitter {
|
||||||
|
@apply h-1;
|
||||||
|
@apply before:-top-0.5;
|
||||||
|
@apply before:-bottom-0.5;
|
||||||
|
@apply before:w-full;
|
||||||
|
@apply after:content-["\e5d3"];
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-splitter.splitpanes--vertical > .splitpanes__splitter {
|
||||||
|
@apply w-0.5;
|
||||||
|
@apply pointer-events-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-splitter.splitpanes--horizontal > .splitpanes__splitter {
|
||||||
|
@apply h-0.5;
|
||||||
|
@apply pointer-events-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-focused {
|
||||||
|
@apply select-auto;
|
||||||
|
@apply outline-none #{!important};
|
||||||
|
|
||||||
|
.cm-activeLine {
|
||||||
|
@apply bg-primaryLight;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-activeLineGutter {
|
||||||
|
@apply bg-primaryDark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-editor {
|
||||||
|
.cm-line::selection {
|
||||||
|
@apply bg-accentDark #{!important};
|
||||||
|
@apply text-accentContrast #{!important};
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-line ::selection {
|
||||||
|
@apply bg-accentDark #{!important};
|
||||||
|
@apply text-accentContrast #{!important};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.shortcut-key {
|
||||||
|
@apply inline-flex;
|
||||||
|
@apply font-sans;
|
||||||
|
@apply text-tiny;
|
||||||
|
@apply bg-divider;
|
||||||
|
@apply rounded;
|
||||||
|
@apply ml-2;
|
||||||
|
@apply px-1;
|
||||||
|
@apply min-w-5;
|
||||||
|
@apply min-h-5;
|
||||||
|
@apply items-center;
|
||||||
|
@apply justify-center;
|
||||||
|
@apply border border-dividerDark;
|
||||||
|
@apply shadow-sm;
|
||||||
|
@apply <sm:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.capitalize-first {
|
||||||
|
@apply first-letter:capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
details {
|
||||||
|
@apply select-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
details summary::-webkit-details-marker {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
details summary .indicator {
|
||||||
|
@apply transition;
|
||||||
|
}
|
||||||
|
|
||||||
|
details[open] summary .indicator {
|
||||||
|
@apply transform;
|
||||||
|
@apply rotate-90;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
main {
|
||||||
|
margin-bottom: env(safe-area-inset-bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.env-highlight {
|
||||||
|
* {
|
||||||
|
@apply text-accentContrast;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#nprogress .bar {
|
||||||
|
@apply bg-accent #{!important};
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-picker[type="color"] {
|
||||||
|
@apply appearance-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-picker[type="color"]::-webkit-color-swatch-wrapper {
|
||||||
|
@apply rounded;
|
||||||
|
@apply p-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-picker[type="color"]::-webkit-color-swatch {
|
||||||
|
@apply rounded;
|
||||||
|
@apply border-0;
|
||||||
|
}
|
||||||
311
packages/hoppscotch-ui/src/assets/scss/themes.scss
Normal file
311
packages/hoppscotch-ui/src/assets/scss/themes.scss
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
@mixin base-theme {
|
||||||
|
--font-sans: "Inter", sans-serif;
|
||||||
|
--font-mono: "Roboto Mono", monospace;
|
||||||
|
--font-icon: "Material Icons";
|
||||||
|
--font-size-tiny: calc(var(--font-size-body) - 0.062rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin dark-theme {
|
||||||
|
--primary-color: theme("colors.neutral.900");
|
||||||
|
--primary-light-color: theme("colors.dark.600");
|
||||||
|
--primary-dark-color: theme("colors.neutral.800");
|
||||||
|
--primary-contrast-color: #161616;
|
||||||
|
--secondary-color: theme("colors.neutral.400");
|
||||||
|
--secondary-light-color: theme("colors.neutral.500");
|
||||||
|
--secondary-dark-color: theme("colors.neutral.100");
|
||||||
|
--divider-color: theme("colors.neutral.800");
|
||||||
|
--divider-light-color: theme("colors.dark.500");
|
||||||
|
--divider-dark-color: theme("colors.dark.300");
|
||||||
|
--error-color: theme("colors.stone.800");
|
||||||
|
--tooltip-color: theme("colors.neutral.100");
|
||||||
|
--popover-color: theme("colors.dark.700");
|
||||||
|
--editor-theme: "merbivore_soft";
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin light-theme {
|
||||||
|
--primary-color: theme("colors.white");
|
||||||
|
--primary-light-color: theme("colors.neutral.50");
|
||||||
|
--primary-dark-color: theme("colors.neutral.100");
|
||||||
|
--primary-contrast-color: #fefefe;
|
||||||
|
--secondary-color: theme("colors.neutral.500");
|
||||||
|
--secondary-light-color: theme("colors.neutral.400");
|
||||||
|
--secondary-dark-color: theme("colors.neutral.900");
|
||||||
|
--divider-color: theme("colors.gray.100");
|
||||||
|
--divider-light-color: theme("colors.neutral.100");
|
||||||
|
--divider-dark-color: theme("colors.neutral.300");
|
||||||
|
--error-color: theme("colors.yellow.100");
|
||||||
|
--tooltip-color: theme("colors.neutral.800");
|
||||||
|
--popover-color: theme("colors.white");
|
||||||
|
--editor-theme: "textmate";
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin black-theme {
|
||||||
|
--primary-color: theme("colors.dark.900");
|
||||||
|
--primary-light-color: theme("colors.neutral.900");
|
||||||
|
--primary-dark-color: theme("colors.dark.800");
|
||||||
|
--primary-contrast-color: #0e0e0e;
|
||||||
|
--secondary-color: theme("colors.neutral.400");
|
||||||
|
--secondary-light-color: theme("colors.neutral.500");
|
||||||
|
--secondary-dark-color: theme("colors.neutral.100");
|
||||||
|
--divider-color: theme("colors.neutral.800");
|
||||||
|
--divider-light-color: theme("colors.dark.800");
|
||||||
|
--divider-dark-color: theme("colors.dark.300");
|
||||||
|
--error-color: theme("colors.stone.900");
|
||||||
|
--tooltip-color: theme("colors.neutral.100");
|
||||||
|
--popover-color: theme("colors.dark.600");
|
||||||
|
--editor-theme: "twilight";
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin dark-editor-theme {
|
||||||
|
--editor-type-color: theme("colors.purple.400");
|
||||||
|
--editor-name-color: theme("colors.blue.400");
|
||||||
|
--editor-operator-color: theme("colors.indigo.400");
|
||||||
|
--editor-invalid-color: theme("colors.red.400");
|
||||||
|
--editor-separator-color: theme("colors.gray.400");
|
||||||
|
--editor-meta-color: theme("colors.gray.400");
|
||||||
|
--editor-variable-color: theme("colors.green.400");
|
||||||
|
--editor-link-color: theme("colors.cyan.400");
|
||||||
|
--editor-process-color: theme("colors.fuchsia.400");
|
||||||
|
--editor-constant-color: theme("colors.violet.400");
|
||||||
|
--editor-keyword-color: theme("colors.pink.400");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin light-editor-theme {
|
||||||
|
--editor-type-color: theme("colors.purple.600");
|
||||||
|
--editor-name-color: theme("colors.red.600");
|
||||||
|
--editor-operator-color: theme("colors.indigo.600");
|
||||||
|
--editor-invalid-color: theme("colors.red.600");
|
||||||
|
--editor-separator-color: theme("colors.gray.600");
|
||||||
|
--editor-meta-color: theme("colors.gray.600");
|
||||||
|
--editor-variable-color: theme("colors.green.600");
|
||||||
|
--editor-link-color: theme("colors.cyan.600");
|
||||||
|
--editor-process-color: theme("colors.blue.600");
|
||||||
|
--editor-constant-color: theme("colors.fuchsia.600");
|
||||||
|
--editor-keyword-color: theme("colors.pink.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin black-editor-theme {
|
||||||
|
--editor-type-color: theme("colors.purple.400");
|
||||||
|
--editor-name-color: theme("colors.fuchsia.400");
|
||||||
|
--editor-operator-color: theme("colors.indigo.400");
|
||||||
|
--editor-invalid-color: theme("colors.red.400");
|
||||||
|
--editor-separator-color: theme("colors.gray.400");
|
||||||
|
--editor-meta-color: theme("colors.gray.400");
|
||||||
|
--editor-variable-color: theme("colors.green.400");
|
||||||
|
--editor-link-color: theme("colors.cyan.400");
|
||||||
|
--editor-process-color: theme("colors.violet.400");
|
||||||
|
--editor-constant-color: theme("colors.blue.400");
|
||||||
|
--editor-keyword-color: theme("colors.pink.400");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin green-theme {
|
||||||
|
--accent-color: theme("colors.green.500");
|
||||||
|
--accent-light-color: theme("colors.green.400");
|
||||||
|
--accent-dark-color: theme("colors.green.600");
|
||||||
|
--accent-contrast-color: theme("colors.white");
|
||||||
|
--gradient-from-color: theme("colors.green.200");
|
||||||
|
--gradient-via-color: theme("colors.green.400");
|
||||||
|
--gradient-to-color: theme("colors.green.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin teal-theme {
|
||||||
|
--accent-color: theme("colors.teal.500");
|
||||||
|
--accent-light-color: theme("colors.teal.400");
|
||||||
|
--accent-dark-color: theme("colors.teal.600");
|
||||||
|
--accent-contrast-color: theme("colors.white");
|
||||||
|
--gradient-from-color: theme("colors.teal.200");
|
||||||
|
--gradient-via-color: theme("colors.teal.400");
|
||||||
|
--gradient-to-color: theme("colors.teal.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin blue-theme {
|
||||||
|
--accent-color: theme("colors.blue.500");
|
||||||
|
--accent-light-color: theme("colors.blue.400");
|
||||||
|
--accent-dark-color: theme("colors.blue.600");
|
||||||
|
--accent-contrast-color: theme("colors.white");
|
||||||
|
--gradient-from-color: theme("colors.blue.200");
|
||||||
|
--gradient-via-color: theme("colors.blue.400");
|
||||||
|
--gradient-to-color: theme("colors.blue.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin indigo-theme {
|
||||||
|
--accent-color: theme("colors.indigo.500");
|
||||||
|
--accent-light-color: theme("colors.indigo.400");
|
||||||
|
--accent-dark-color: theme("colors.indigo.600");
|
||||||
|
--accent-contrast-color: theme("colors.white");
|
||||||
|
--gradient-from-color: theme("colors.indigo.200");
|
||||||
|
--gradient-via-color: theme("colors.indigo.400");
|
||||||
|
--gradient-to-color: theme("colors.indigo.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin purple-theme {
|
||||||
|
--accent-color: theme("colors.purple.500");
|
||||||
|
--accent-light-color: theme("colors.purple.400");
|
||||||
|
--accent-dark-color: theme("colors.purple.600");
|
||||||
|
--accent-contrast-color: theme("colors.white");
|
||||||
|
--gradient-from-color: theme("colors.purple.200");
|
||||||
|
--gradient-via-color: theme("colors.purple.400");
|
||||||
|
--gradient-to-color: theme("colors.purple.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin yellow-theme {
|
||||||
|
--accent-color: theme("colors.yellow.500");
|
||||||
|
--accent-light-color: theme("colors.yellow.400");
|
||||||
|
--accent-dark-color: theme("colors.yellow.600");
|
||||||
|
--accent-contrast-color: theme("colors.white");
|
||||||
|
--gradient-from-color: theme("colors.yellow.200");
|
||||||
|
--gradient-via-color: theme("colors.yellow.400");
|
||||||
|
--gradient-to-color: theme("colors.yellow.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin orange-theme {
|
||||||
|
--accent-color: theme("colors.orange.500");
|
||||||
|
--accent-light-color: theme("colors.orange.400");
|
||||||
|
--accent-dark-color: theme("colors.orange.600");
|
||||||
|
--accent-contrast-color: theme("colors.white");
|
||||||
|
--gradient-from-color: theme("colors.orange.200");
|
||||||
|
--gradient-via-color: theme("colors.orange.400");
|
||||||
|
--gradient-to-color: theme("colors.orange.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin red-theme {
|
||||||
|
--accent-color: theme("colors.red.500");
|
||||||
|
--accent-light-color: theme("colors.red.400");
|
||||||
|
--accent-dark-color: theme("colors.red.600");
|
||||||
|
--accent-contrast-color: theme("colors.white");
|
||||||
|
--gradient-from-color: theme("colors.red.200");
|
||||||
|
--gradient-via-color: theme("colors.red.400");
|
||||||
|
--gradient-to-color: theme("colors.red.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin pink-theme {
|
||||||
|
--accent-color: theme("colors.pink.500");
|
||||||
|
--accent-light-color: theme("colors.pink.400");
|
||||||
|
--accent-dark-color: theme("colors.pink.600");
|
||||||
|
--accent-contrast-color: theme("colors.white");
|
||||||
|
--gradient-from-color: theme("colors.pink.200");
|
||||||
|
--gradient-via-color: theme("colors.pink.400");
|
||||||
|
--gradient-to-color: theme("colors.pink.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
@include base-theme;
|
||||||
|
@include dark-theme;
|
||||||
|
@include green-theme;
|
||||||
|
@include dark-editor-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.light {
|
||||||
|
@include light-theme;
|
||||||
|
@include light-editor-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark {
|
||||||
|
@include dark-theme;
|
||||||
|
@include dark-editor-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.black {
|
||||||
|
@include black-theme;
|
||||||
|
@include black-editor-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-accent="blue"] {
|
||||||
|
@include blue-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-accent="green"] {
|
||||||
|
@include green-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-accent="teal"] {
|
||||||
|
@include teal-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-accent="indigo"] {
|
||||||
|
@include indigo-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-accent="purple"] {
|
||||||
|
@include purple-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-accent="orange"] {
|
||||||
|
@include orange-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-accent="pink"] {
|
||||||
|
@include pink-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-accent="red"] {
|
||||||
|
@include red-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-accent="yellow"] {
|
||||||
|
@include yellow-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin font-small {
|
||||||
|
--font-size-body: 0.75rem;
|
||||||
|
--line-height-body: 1rem;
|
||||||
|
--upper-primary-sticky-fold: 4.125rem;
|
||||||
|
--upper-secondary-sticky-fold: 6.188rem;
|
||||||
|
--upper-tertiary-sticky-fold: 8.25rem;
|
||||||
|
--upper-mobile-primary-sticky-fold: 6.625rem;
|
||||||
|
--upper-mobile-secondary-sticky-fold: 8.688rem;
|
||||||
|
--upper-mobile-sticky-fold: 10.75rem;
|
||||||
|
--upper-mobile-tertiary-sticky-fold: 8.25rem;
|
||||||
|
--lower-primary-sticky-fold: 3rem;
|
||||||
|
--lower-secondary-sticky-fold: 5.063rem;
|
||||||
|
--lower-tertiary-sticky-fold: 7.125rem;
|
||||||
|
--sidebar-primary-sticky-fold: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin font-medium {
|
||||||
|
--font-size-body: 0.875rem;
|
||||||
|
--line-height-body: 1.25rem;
|
||||||
|
--upper-primary-sticky-fold: 4.375rem;
|
||||||
|
--upper-secondary-sticky-fold: 6.688rem;
|
||||||
|
--upper-tertiary-sticky-fold: 9rem;
|
||||||
|
--upper-mobile-primary-sticky-fold: 7.125rem;
|
||||||
|
--upper-mobile-secondary-sticky-fold: 9.438rem;
|
||||||
|
--upper-mobile-sticky-fold: 11.75rem;
|
||||||
|
--upper-mobile-tertiary-sticky-fold: 9rem;
|
||||||
|
--lower-primary-sticky-fold: 3.25rem;
|
||||||
|
--lower-secondary-sticky-fold: 5.563rem;
|
||||||
|
--lower-tertiary-sticky-fold: 7.875rem;
|
||||||
|
--sidebar-primary-sticky-fold: 2.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin font-large {
|
||||||
|
--font-size-body: 1rem;
|
||||||
|
--line-height-body: 1.5rem;
|
||||||
|
--upper-primary-sticky-fold: 4.625rem;
|
||||||
|
--upper-secondary-sticky-fold: 7.188rem;
|
||||||
|
--upper-tertiary-sticky-fold: 9.75rem;
|
||||||
|
--upper-mobile-primary-sticky-fold: 7.625rem;
|
||||||
|
--upper-mobile-secondary-sticky-fold: 10.188rem;
|
||||||
|
--upper-mobile-sticky-fold: 12.75rem;
|
||||||
|
--upper-mobile-tertiary-sticky-fold: 9.75rem;
|
||||||
|
--lower-primary-sticky-fold: 3.5rem;
|
||||||
|
--lower-secondary-sticky-fold: 6.063rem;
|
||||||
|
--lower-tertiary-sticky-fold: 8.625rem;
|
||||||
|
--sidebar-primary-sticky-fold: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-font-size="small"] {
|
||||||
|
@include font-small;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-font-size="medium"] {
|
||||||
|
@include font-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-font-size="large"] {
|
||||||
|
@include font-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
.generic {
|
||||||
|
@apply text-primary text-primaryLight bg-primary;
|
||||||
|
}
|
||||||
37
packages/hoppscotch-ui/src/components.d.ts
vendored
Normal file
37
packages/hoppscotch-ui/src/components.d.ts
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// generated by unplugin-vue-components
|
||||||
|
// We suggest you to commit this file into source control
|
||||||
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
|
import '@vue/runtime-core'
|
||||||
|
|
||||||
|
export {}
|
||||||
|
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
ButtonPrimary: typeof import('./components/button/Primary.vue')['default']
|
||||||
|
ButtonSecondary: typeof import('./components/button/Secondary.vue')['default']
|
||||||
|
IconLucideLoader: typeof import('~icons/lucide/loader')['default']
|
||||||
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
SmartAnchor: typeof import('./components/smart/Anchor.vue')['default']
|
||||||
|
SmartAutoComplete: typeof import('./components/smart/AutoComplete.vue')['default']
|
||||||
|
SmartCheckbox: typeof import('./components/smart/Checkbox.vue')['default']
|
||||||
|
SmartConfirmModal: typeof import('./components/smart/ConfirmModal.vue')['default']
|
||||||
|
SmartExpand: typeof import('./components/smart/Expand.vue')['default']
|
||||||
|
SmartFileChip: typeof import('./components/smart/FileChip.vue')['default']
|
||||||
|
SmartIntersection: typeof import('./components/smart/Intersection.vue')['default']
|
||||||
|
SmartItem: typeof import('./components/smart/Item.vue')['default']
|
||||||
|
SmartLink: typeof import('./components/smart/Link.vue')['default']
|
||||||
|
SmartModal: typeof import('./components/smart/Modal.vue')['default']
|
||||||
|
SmartProgressRing: typeof import('./components/smart/ProgressRing.vue')['default']
|
||||||
|
SmartRadio: typeof import('./components/smart/Radio.vue')['default']
|
||||||
|
SmartRadioGroup: typeof import('./components/smart/RadioGroup.vue')['default']
|
||||||
|
SmartSlideOver: typeof import('./components/smart/SlideOver.vue')['default']
|
||||||
|
SmartSpinner: typeof import('./components/smart/Spinner.vue')['default']
|
||||||
|
SmartTab: typeof import('./components/smart/Tab.vue')['default']
|
||||||
|
SmartTabs: typeof import('./components/smart/Tabs.vue')['default']
|
||||||
|
SmartToggle: typeof import('./components/smart/Toggle.vue')['default']
|
||||||
|
SmartWindow: typeof import('./components/smart/Window.vue')['default']
|
||||||
|
SmartWindows: typeof import('./components/smart/Windows.vue')['default']
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
47
packages/hoppscotch-ui/src/components/index.ts
Normal file
47
packages/hoppscotch-ui/src/components/index.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import Primary from "./button/Primary.vue"
|
||||||
|
import Secondary from "./button/Secondary.vue"
|
||||||
|
import Anchor from "./smart/Anchor.vue"
|
||||||
|
import AutoComplete from "./smart/AutoComplete.vue"
|
||||||
|
import Checkbox from "./smart/Checkbox.vue"
|
||||||
|
import ConfirmModal from "./smart/ConfirmModal.vue"
|
||||||
|
import Expand from "./smart/Expand.vue"
|
||||||
|
import FileChip from "./smart/FileChip.vue"
|
||||||
|
import Intersection from "./smart/Intersection.vue"
|
||||||
|
import Item from "./smart/Item.vue"
|
||||||
|
import Link from "./smart/Link.vue"
|
||||||
|
import Modal from "./smart/Modal.vue"
|
||||||
|
import ProgressRing from "./smart/ProgressRing.vue"
|
||||||
|
import Radio from "./smart/Radio.vue"
|
||||||
|
import RadioGroup from "./smart/RadioGroup.vue"
|
||||||
|
import SlideOver from "./smart/SlideOver.vue"
|
||||||
|
import Spinner from "./smart/Spinner.vue"
|
||||||
|
import Tab from "./smart/Tab.vue"
|
||||||
|
import Tabs from "./smart/Tabs.vue"
|
||||||
|
import Toggle from "./smart/Toggle.vue"
|
||||||
|
import Window from "./smart/Window.vue"
|
||||||
|
import Windows from "./smart/Windows.vue"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
Primary,
|
||||||
|
Secondary,
|
||||||
|
Anchor,
|
||||||
|
AutoComplete,
|
||||||
|
Checkbox,
|
||||||
|
ConfirmModal,
|
||||||
|
Expand,
|
||||||
|
FileChip,
|
||||||
|
Intersection,
|
||||||
|
Item,
|
||||||
|
Link,
|
||||||
|
Modal,
|
||||||
|
ProgressRing,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
SlideOver,
|
||||||
|
Spinner,
|
||||||
|
Tab,
|
||||||
|
Tabs,
|
||||||
|
Toggle,
|
||||||
|
Window,
|
||||||
|
Windows,
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<SmartModal
|
<SmartModal
|
||||||
v-if="show"
|
v-if="show"
|
||||||
dialog
|
dialog
|
||||||
:title="t('modal.confirm')"
|
:title="confirm ?? t?.('modal.confirm') ?? 'Confirm'"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
@close="hideModal"
|
@close="hideModal"
|
||||||
@@ -16,13 +16,13 @@
|
|||||||
<span class="flex space-x-2">
|
<span class="flex space-x-2">
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
v-focus
|
v-focus
|
||||||
:label="yes ?? t('action.yes')"
|
:label="yes ?? t?.('action.yes') ?? 'Yes'"
|
||||||
:loading="!!loadingState"
|
:loading="!!loadingState"
|
||||||
outline
|
outline
|
||||||
@click="resolve"
|
@click="resolve"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
:label="no ?? t('action.no')"
|
:label="no ?? t?.('action.no') ?? 'No'"
|
||||||
filled
|
filled
|
||||||
outline
|
outline
|
||||||
@click="hideModal"
|
@click="hideModal"
|
||||||
@@ -33,20 +33,23 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useI18n } from "@composables/i18n"
|
import { inject } from "vue"
|
||||||
|
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../index"
|
||||||
|
|
||||||
const t = useI18n()
|
const { t } = inject<HoppUIPluginOptions>(HOPP_UI_OPTIONS) ?? {}
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
show: boolean
|
show: boolean
|
||||||
title?: string | null
|
title?: string | null
|
||||||
|
confirm?: string | null
|
||||||
yes?: string | null
|
yes?: string | null
|
||||||
no?: string | null
|
no?: string | null
|
||||||
loadingState?: boolean | null
|
loadingState?: boolean | null
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
title: null,
|
title: null,
|
||||||
|
confirm: null,
|
||||||
yes: null,
|
yes: null,
|
||||||
no: null,
|
no: null,
|
||||||
loadingState: null,
|
loadingState: null,
|
||||||
@@ -9,7 +9,11 @@
|
|||||||
>
|
>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
:icon="expand ? IconChevronUp : IconChevronDown"
|
:icon="expand ? IconChevronUp : IconChevronDown"
|
||||||
:label="expand ? t('action.less') : t('action.more')"
|
:label="
|
||||||
|
expand
|
||||||
|
? less ?? t?.('action.less') ?? 'Less'
|
||||||
|
: more ?? t?.('action.more') ?? 'More'
|
||||||
|
"
|
||||||
filled
|
filled
|
||||||
rounded
|
rounded
|
||||||
@click="expand = !expand"
|
@click="expand = !expand"
|
||||||
@@ -21,10 +25,21 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import IconChevronUp from "~icons/lucide/chevron-up"
|
import IconChevronUp from "~icons/lucide/chevron-up"
|
||||||
import IconChevronDown from "~icons/lucide/chevron-down"
|
import IconChevronDown from "~icons/lucide/chevron-down"
|
||||||
import { ref } from "vue"
|
import { inject, ref } from "vue"
|
||||||
import { useI18n } from "@composables/i18n"
|
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../index"
|
||||||
|
|
||||||
const t = useI18n()
|
const { t } = inject<HoppUIPluginOptions>(HOPP_UI_OPTIONS) ?? {}
|
||||||
|
|
||||||
const expand = ref(false)
|
const expand = ref(false)
|
||||||
|
|
||||||
|
withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
less?: string
|
||||||
|
more?: string
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
less: "Less",
|
||||||
|
more: "More",
|
||||||
|
}
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="dimissible"
|
v-if="dimissible"
|
||||||
v-tippy="{ theme: 'tooltip', delay: [500, 20] }"
|
v-tippy="{ theme: 'tooltip', delay: [500, 20] }"
|
||||||
:title="t('action.close')"
|
:title="closeText ?? t?.('action.close') ?? 'Close'"
|
||||||
:icon="IconX"
|
:icon="IconX"
|
||||||
@click="close"
|
@click="close"
|
||||||
/>
|
/>
|
||||||
@@ -93,11 +93,18 @@ const stack = (() => {
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import IconX from "~icons/lucide/x"
|
import IconX from "~icons/lucide/x"
|
||||||
import { ref, computed, useSlots, onMounted, onBeforeUnmount } from "vue"
|
import {
|
||||||
import { useKeybindingDisabler } from "~/helpers/keybindings"
|
ref,
|
||||||
import { useI18n } from "@composables/i18n"
|
computed,
|
||||||
|
useSlots,
|
||||||
|
onMounted,
|
||||||
|
onBeforeUnmount,
|
||||||
|
inject,
|
||||||
|
} from "vue"
|
||||||
|
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../index"
|
||||||
|
|
||||||
const t = useI18n()
|
const { t, onModalOpen, onModalClose } =
|
||||||
|
inject<HoppUIPluginOptions>(HOPP_UI_OPTIONS) ?? {}
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
dialog: {
|
dialog: {
|
||||||
@@ -124,16 +131,18 @@ defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: "sm:max-w-lg",
|
default: "sm:max-w-lg",
|
||||||
},
|
},
|
||||||
|
closeText: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "close"): void
|
(e: "close"): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { disableKeybindings, enableKeybindings } = useKeybindingDisabler()
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
enableKeybindings()
|
onModalClose?.()
|
||||||
})
|
})
|
||||||
|
|
||||||
const stackId = ref(stackIDTicker++)
|
const stackId = ref(stackIDTicker++)
|
||||||
@@ -153,7 +162,7 @@ onMounted(() => {
|
|||||||
stack.push(stackId.value)
|
stack.push(stackId.value)
|
||||||
document.addEventListener("keydown", onKeyDown)
|
document.addEventListener("keydown", onKeyDown)
|
||||||
|
|
||||||
disableKeybindings()
|
onModalOpen?.()
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
@@ -78,7 +78,6 @@ import * as A from "fp-ts/Array"
|
|||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
import type { Component } from "vue"
|
import type { Component } from "vue"
|
||||||
import { ref, ComputedRef, computed, provide } from "vue"
|
import { ref, ComputedRef, computed, provide } from "vue"
|
||||||
import { throwError } from "~/helpers/functional/error"
|
|
||||||
|
|
||||||
export type TabMeta = {
|
export type TabMeta = {
|
||||||
label: string | null
|
label: string | null
|
||||||
@@ -124,6 +123,10 @@ const emit = defineEmits<{
|
|||||||
(e: "update:modelValue", newTabID: string): void
|
(e: "update:modelValue", newTabID: string): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const throwError = (message: string): never => {
|
||||||
|
throw new Error(message)
|
||||||
|
}
|
||||||
|
|
||||||
const tabEntries = ref<Array<[string, TabMeta]>>([])
|
const tabEntries = ref<Array<[string, TabMeta]>>([])
|
||||||
|
|
||||||
const addTabEntry = (tabID: string, meta: TabMeta) => {
|
const addTabEntry = (tabID: string, meta: TabMeta) => {
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
:style="{
|
:style="{
|
||||||
visibility: tabMeta.isRemovable ? 'visible' : 'hidden',
|
visibility: tabMeta.isRemovable ? 'visible' : 'hidden',
|
||||||
}"
|
}"
|
||||||
:title="t('action.close')"
|
:title="closeText ?? t?.('action.close') ?? 'Close'"
|
||||||
:class="[{ active: modelValue === tabID }, 'close']"
|
:class="[{ active: modelValue === tabID }, 'close']"
|
||||||
class="mx-2 !p-0.5"
|
class="mx-2 !p-0.5"
|
||||||
@click.stop="emit('removeTab', tabID)"
|
@click.stop="emit('removeTab', tabID)"
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
>
|
>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="t('action.new')"
|
:title="newText ?? t?.('action.new') ?? 'New'"
|
||||||
:icon="IconPlus"
|
:icon="IconPlus"
|
||||||
class="rounded !p-1"
|
class="rounded !p-1"
|
||||||
filled
|
filled
|
||||||
@@ -85,11 +85,10 @@ import { pipe } from "fp-ts/function"
|
|||||||
import { not } from "fp-ts/Predicate"
|
import { not } from "fp-ts/Predicate"
|
||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
import { ref, ComputedRef, computed, provide } from "vue"
|
import { ref, ComputedRef, computed, provide, inject } from "vue"
|
||||||
import type { Slot } from "vue"
|
import type { Slot } from "vue"
|
||||||
import draggable from "vuedraggable"
|
import draggable from "vuedraggable"
|
||||||
import { throwError } from "~/helpers/functional/error"
|
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../index"
|
||||||
import { useI18n } from "~/composables/i18n"
|
|
||||||
|
|
||||||
export type TabMeta = {
|
export type TabMeta = {
|
||||||
label: string | null
|
label: string | null
|
||||||
@@ -104,7 +103,7 @@ export type TabProvider = {
|
|||||||
removeTabEntry: (tabID: string) => void
|
removeTabEntry: (tabID: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const t = useI18n()
|
const { t } = inject<HoppUIPluginOptions>(HOPP_UI_OPTIONS) ?? {}
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
styles: {
|
styles: {
|
||||||
@@ -119,6 +118,14 @@ const props = defineProps({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
newText: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
closeText: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "update:modelValue", newTabID: string): void
|
(e: "update:modelValue", newTabID: string): void
|
||||||
@@ -126,6 +133,11 @@ const emit = defineEmits<{
|
|||||||
(e: "removeTab", tabID: string): void
|
(e: "removeTab", tabID: string): void
|
||||||
(e: "addTab"): void
|
(e: "addTab"): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const throwError = (message: string): never => {
|
||||||
|
throw new Error(message)
|
||||||
|
}
|
||||||
|
|
||||||
const tabEntries = ref<Array<[string, TabMeta]>>([])
|
const tabEntries = ref<Array<[string, TabMeta]>>([])
|
||||||
const tabStyles = computed(() => ({
|
const tabStyles = computed(() => ({
|
||||||
maxWidth: `${tabEntries.value.length * 184}px`,
|
maxWidth: `${tabEntries.value.length * 184}px`,
|
||||||
8
packages/hoppscotch-ui/src/env.d.ts
vendored
Normal file
8
packages/hoppscotch-ui/src/env.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
declare module "*.vue" {
|
||||||
|
import { DefineComponent } from "vue"
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
||||||
|
const component: DefineComponent<{}, {}, any>
|
||||||
|
export default component
|
||||||
|
}
|
||||||
33
packages/hoppscotch-ui/src/index.ts
Normal file
33
packages/hoppscotch-ui/src/index.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { Plugin } from "vue"
|
||||||
|
|
||||||
|
import "./assets/scss/styles.scss"
|
||||||
|
import "virtual:windi.css"
|
||||||
|
|
||||||
|
/**
|
||||||
|
@constant HOPP_UI_OPTIONS
|
||||||
|
@type {string}
|
||||||
|
A constant representing the key for storing HoppUI plugin options in the global context.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const HOPP_UI_OPTIONS = "HOPP_UI_OPTIONS"
|
||||||
|
|
||||||
|
/**
|
||||||
|
@typedef {Object} HoppUIPluginOptions
|
||||||
|
@property {Function} [t] - A function for handling translations for the plugin.
|
||||||
|
@property {Function} [onModalOpen] - A callback function that is called when a modal is opened.
|
||||||
|
@property {Function} [onModalClose] - A callback function that is called when a modal is closed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type HoppUIPluginOptions = {
|
||||||
|
t?: (key: string) => string
|
||||||
|
onModalOpen?: () => void
|
||||||
|
onModalClose?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const plugin: Plugin = {
|
||||||
|
install(app, options: HoppUIPluginOptions = {}) {
|
||||||
|
app.provide(HOPP_UI_OPTIONS, options)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default plugin
|
||||||
20
packages/hoppscotch-ui/src/stories/Anchor.story.vue
Normal file
20
packages/hoppscotch-ui/src/stories/Anchor.story.vue
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Anchor">
|
||||||
|
<div class="text-secondaryLight text-tiny">
|
||||||
|
By signing in, you are agreeing to our
|
||||||
|
<SmartAnchor
|
||||||
|
class="link text-red-800"
|
||||||
|
to="https://docs.hoppscotch.io/terms"
|
||||||
|
blank
|
||||||
|
label="Terms of Service"
|
||||||
|
/>
|
||||||
|
and
|
||||||
|
<SmartAnchor
|
||||||
|
class="link text-red-600"
|
||||||
|
to="https://docs.hoppscotch.io/privacy"
|
||||||
|
blank
|
||||||
|
label="Privacy Policy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
55
packages/hoppscotch-ui/src/stories/AutoComplete.story.vue
Normal file
55
packages/hoppscotch-ui/src/stories/AutoComplete.story.vue
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Auto Complete">
|
||||||
|
<div class="h-[50vh]">
|
||||||
|
<SmartAutoComplete
|
||||||
|
placeholder="Select a header"
|
||||||
|
:source="commonHeaders"
|
||||||
|
:spellcheck="false"
|
||||||
|
:value="header[0].key"
|
||||||
|
autofocus
|
||||||
|
styles="
|
||||||
|
bg-transparent
|
||||||
|
flex
|
||||||
|
flex-1
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
|
truncate
|
||||||
|
"
|
||||||
|
class="flex-1 !flex"
|
||||||
|
@input="updateHeader()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
type GQLHeader = {
|
||||||
|
key: string
|
||||||
|
value: string
|
||||||
|
active: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = ref<GQLHeader[]>([
|
||||||
|
{
|
||||||
|
key: "Content-Type",
|
||||||
|
value: "application/json",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const commonHeaders = [
|
||||||
|
"Push-Policy",
|
||||||
|
"Retry-After",
|
||||||
|
"Signature",
|
||||||
|
"Signed-Headers",
|
||||||
|
"Server-Timing",
|
||||||
|
"SourceMap",
|
||||||
|
"Upgrade",
|
||||||
|
]
|
||||||
|
|
||||||
|
const updateHeader = () => {
|
||||||
|
// alert("updated")
|
||||||
|
}
|
||||||
|
</script>
|
||||||
10
packages/hoppscotch-ui/src/stories/Button.story.vue
Normal file
10
packages/hoppscotch-ui/src/stories/Button.story.vue
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Button">
|
||||||
|
<Variant title="Primary">
|
||||||
|
<ButtonPrimary label="Button" />
|
||||||
|
</Variant>
|
||||||
|
<Variant title="Secondary">
|
||||||
|
<ButtonSecondary label="Button" />
|
||||||
|
</Variant>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
13
packages/hoppscotch-ui/src/stories/Checkbox.story.vue
Normal file
13
packages/hoppscotch-ui/src/stories/Checkbox.story.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Checkbox">
|
||||||
|
<Variant title="Single">
|
||||||
|
<SmartCheckbox :on="on" />
|
||||||
|
</Variant>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
const on = ref(true)
|
||||||
|
</script>
|
||||||
21
packages/hoppscotch-ui/src/stories/ConfirmModal.story.vue
Normal file
21
packages/hoppscotch-ui/src/stories/ConfirmModal.story.vue
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Confirm Modal">
|
||||||
|
<SmartConfirmModal
|
||||||
|
:show="show"
|
||||||
|
:title="'Confirm Modal'"
|
||||||
|
@hide-modal="show = false"
|
||||||
|
@resolve="resolveConfirmModal"
|
||||||
|
/>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
const show = ref(true)
|
||||||
|
|
||||||
|
const resolveConfirmModal = (resolve: string | null) => {
|
||||||
|
alert("resolved: " + resolve)
|
||||||
|
show.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
7
packages/hoppscotch-ui/src/stories/Item.story.vue
Normal file
7
packages/hoppscotch-ui/src/stories/Item.story.vue
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Item">
|
||||||
|
<Variant title="Single">
|
||||||
|
<SmartItem :label="'Item'" :active-info-icon="false" />
|
||||||
|
</Variant>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
18
packages/hoppscotch-ui/src/stories/Link.story.vue
Normal file
18
packages/hoppscotch-ui/src/stories/Link.story.vue
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Link">
|
||||||
|
<Variant title="Text Link">
|
||||||
|
<SmartLink :to="link" :blank="true"> Click here </SmartLink>
|
||||||
|
</Variant>
|
||||||
|
<Variant title="Button Link">
|
||||||
|
<SmartLink :to="link" :blank="true">
|
||||||
|
<ButtonPrimary label="Click here" />
|
||||||
|
</SmartLink>
|
||||||
|
</Variant>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
const link = ref("/graphql")
|
||||||
|
</script>
|
||||||
21
packages/hoppscotch-ui/src/stories/Modal.story.vue
Normal file
21
packages/hoppscotch-ui/src/stories/Modal.story.vue
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Modal">
|
||||||
|
<SmartModal
|
||||||
|
:show="show"
|
||||||
|
:title="'Modal Title'"
|
||||||
|
@hide-modal="show = false"
|
||||||
|
@resolve="resolveConfirmModal"
|
||||||
|
/>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
const show = ref(true)
|
||||||
|
|
||||||
|
const resolveConfirmModal = (resolve: string | null) => {
|
||||||
|
alert("resolved: " + resolve)
|
||||||
|
show.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
15
packages/hoppscotch-ui/src/stories/ProgressRing.story.vue
Normal file
15
packages/hoppscotch-ui/src/stories/ProgressRing.story.vue
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Progress Ring">
|
||||||
|
<SmartProgressRing
|
||||||
|
class="mr-2 text-red-500"
|
||||||
|
:radius="8"
|
||||||
|
:stroke="1.5"
|
||||||
|
:progress="(failedTests / totalTests) * 100"
|
||||||
|
/>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const totalTests = 10
|
||||||
|
const failedTests = 2
|
||||||
|
</script>
|
||||||
21
packages/hoppscotch-ui/src/stories/Radio.story.vue
Normal file
21
packages/hoppscotch-ui/src/stories/Radio.story.vue
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Radio">
|
||||||
|
<Variant title="Single">
|
||||||
|
<SmartRadio />
|
||||||
|
</Variant>
|
||||||
|
<Variant title="Group">
|
||||||
|
<SmartRadioGroup :radios="radios" :model-value="selected" />
|
||||||
|
</Variant>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
const selected = ref("option1")
|
||||||
|
const radios = [
|
||||||
|
{ label: "Option 1", value: "option1" },
|
||||||
|
{ label: "Option 2", value: "option2" },
|
||||||
|
{ label: "Option 3", value: "option3" },
|
||||||
|
]
|
||||||
|
</script>
|
||||||
15
packages/hoppscotch-ui/src/stories/SlideOver.story.vue
Normal file
15
packages/hoppscotch-ui/src/stories/SlideOver.story.vue
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Slider Over">
|
||||||
|
<SmartSlideOver :show="show" :title="'Title'" @close="show = false">
|
||||||
|
<template #content>
|
||||||
|
<h1>Content</h1>
|
||||||
|
</template>
|
||||||
|
</SmartSlideOver>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
const show = ref(true)
|
||||||
|
</script>
|
||||||
5
packages/hoppscotch-ui/src/stories/Spinner.story.vue
Normal file
5
packages/hoppscotch-ui/src/stories/Spinner.story.vue
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Spinner">
|
||||||
|
<SmartSpinner />
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
20
packages/hoppscotch-ui/src/stories/Tab.story.vue
Normal file
20
packages/hoppscotch-ui/src/stories/Tab.story.vue
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Tab">
|
||||||
|
<Variant title="Single">
|
||||||
|
<SmartTabs id="my-tab" v-model="selectedTab" render-inactive-tabs>
|
||||||
|
<SmartTab id="tab1" label="Tab 1">
|
||||||
|
<h1>Tab 1 content</h1>
|
||||||
|
</SmartTab>
|
||||||
|
<SmartTab id="tab2" label="Tab 2">
|
||||||
|
<h1>Tab 2 content</h1>
|
||||||
|
</SmartTab>
|
||||||
|
</SmartTabs>
|
||||||
|
</Variant>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
const selectedTab = ref("tab1")
|
||||||
|
</script>
|
||||||
15
packages/hoppscotch-ui/src/stories/Toggle.story.vue
Normal file
15
packages/hoppscotch-ui/src/stories/Toggle.story.vue
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Toggle">
|
||||||
|
<SmartToggle :on="on" @change="change"> Turn on </SmartToggle>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
const on = ref(true)
|
||||||
|
|
||||||
|
const change = () => {
|
||||||
|
alert("changed to: " + on.value)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
72
packages/hoppscotch-ui/src/stories/Window.story.vue
Normal file
72
packages/hoppscotch-ui/src/stories/Window.story.vue
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Window">
|
||||||
|
<Variant title="Single">
|
||||||
|
<SmartWindows
|
||||||
|
:id="'my-window'"
|
||||||
|
v-model="selectedWindow"
|
||||||
|
@add-tab="openNewTab"
|
||||||
|
@remove-tab="removeTab"
|
||||||
|
@sort="sortTabs"
|
||||||
|
>
|
||||||
|
<SmartWindow
|
||||||
|
v-for="window in tabs"
|
||||||
|
:id="window.id"
|
||||||
|
:key="'tab_' + window.id"
|
||||||
|
:label="window.name"
|
||||||
|
:is-removable="window.removable"
|
||||||
|
>
|
||||||
|
</SmartWindow>
|
||||||
|
</SmartWindows>
|
||||||
|
</Variant>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
const selectedWindow = ref("window1")
|
||||||
|
|
||||||
|
type Tab = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
removable: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabs = ref<Tab[]>([
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
name: "window1",
|
||||||
|
removable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "window2",
|
||||||
|
removable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
name: "window3",
|
||||||
|
removable: true,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const openNewTab = () => {
|
||||||
|
const newTab = {
|
||||||
|
id: Date.now().toString(),
|
||||||
|
name: "New Window",
|
||||||
|
removable: true,
|
||||||
|
}
|
||||||
|
tabs.value = [...tabs.value, { ...newTab }]
|
||||||
|
selectedWindow.value = newTab.id
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeTab = (tabID: string) => {
|
||||||
|
tabs.value = tabs.value.filter((tab) => tab.id !== tabID)
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortTabs = (e: { oldIndex: number; newIndex: number }) => {
|
||||||
|
const newTabs = [...tabs.value]
|
||||||
|
newTabs.splice(e.newIndex, 0, newTabs.splice(e.oldIndex, 1)[0])
|
||||||
|
tabs.value = newTabs
|
||||||
|
}
|
||||||
|
</script>
|
||||||
34
packages/hoppscotch-ui/tsconfig.json
Normal file
34
packages/hoppscotch-ui/tsconfig.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"strict": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"sourceMap": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"paths": {
|
||||||
|
"~/*": ["./src/*"],
|
||||||
|
"@composables/*": ["./src/composables/*"],
|
||||||
|
"@components/*": ["./src/components/*"],
|
||||||
|
"@helpers/*": ["./src/helpers/*"],
|
||||||
|
"@modules/*": ["./src/modules/*"],
|
||||||
|
"@workers/*": ["./src/workers/*"],
|
||||||
|
"@functional/*": ["./src/helpers/functional/*"]
|
||||||
|
},
|
||||||
|
"types": [
|
||||||
|
"vite/client",
|
||||||
|
"unplugin-icons/types/vue",
|
||||||
|
"vite-plugin-pages/client",
|
||||||
|
"vite-plugin-vue-layouts/client",
|
||||||
|
"vite-plugin-pwa/client"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||||
|
}
|
||||||
60
packages/hoppscotch-ui/vite.config.ts
Normal file
60
packages/hoppscotch-ui/vite.config.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import vue from "@vitejs/plugin-vue"
|
||||||
|
import path from "path"
|
||||||
|
import { FileSystemIconLoader } from "unplugin-icons/loaders"
|
||||||
|
import IconResolver from "unplugin-icons/resolver"
|
||||||
|
import Icons from "unplugin-icons/vite"
|
||||||
|
import Components from "unplugin-vue-components/vite"
|
||||||
|
import { defineConfig } from "vite"
|
||||||
|
import WindiCSS from "vite-plugin-windicss"
|
||||||
|
|
||||||
|
module.exports = defineConfig({
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
WindiCSS({
|
||||||
|
root: path.resolve(__dirname),
|
||||||
|
}),
|
||||||
|
Components({
|
||||||
|
dts: "./src/components.d.ts",
|
||||||
|
dirs: ["./src/components"],
|
||||||
|
directoryAsNamespace: true,
|
||||||
|
resolvers: [
|
||||||
|
IconResolver({
|
||||||
|
prefix: "icon",
|
||||||
|
customCollections: ["hopp", "auth", "brands"],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
Icons({
|
||||||
|
compiler: "vue3",
|
||||||
|
customCollections: {
|
||||||
|
hopp: FileSystemIconLoader("../hoppscotch-common/assets/icons"),
|
||||||
|
auth: FileSystemIconLoader("../hoppscotch-common/assets/icons/auth"),
|
||||||
|
brands: FileSystemIconLoader(
|
||||||
|
"../hoppscotch-common/assets/icons/brands"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
], // to process SFC
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
entry: path.resolve(__dirname, "src/index.ts"),
|
||||||
|
name: "hopp-ui",
|
||||||
|
formats: ["es"], // adding 'umd' requires globals set to every external module
|
||||||
|
fileName: (format) => `hopp-ui.${format}.js`,
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
// external modules won't be bundled into HoppUI library
|
||||||
|
external: ["vue"], // not every external has a global
|
||||||
|
output: {
|
||||||
|
// disable warning on src/index.ts using both default and named export
|
||||||
|
exports: "named",
|
||||||
|
// Provide global variables to use in the UMD build
|
||||||
|
// for externalized deps (not useful if 'umd' is not in lib.formats)
|
||||||
|
globals: {
|
||||||
|
vue: "Vue",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emptyOutDir: false, // to retain the types folder generated by tsc
|
||||||
|
},
|
||||||
|
})
|
||||||
65
packages/hoppscotch-ui/windi.config.ts
Normal file
65
packages/hoppscotch-ui/windi.config.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { defineConfig } from "windicss/helpers"
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
theme: {
|
||||||
|
container: {
|
||||||
|
center: true,
|
||||||
|
},
|
||||||
|
extend: {
|
||||||
|
inset: {
|
||||||
|
upperPrimaryStickyFold: "var(--upper-primary-sticky-fold)",
|
||||||
|
upperSecondaryStickyFold: "var(--upper-secondary-sticky-fold)",
|
||||||
|
upperTertiaryStickyFold: "var(--upper-tertiary-sticky-fold)",
|
||||||
|
upperMobilePrimaryStickyFold: "var(--upper-mobile-primary-sticky-fold)",
|
||||||
|
upperMobileSecondaryStickyFold:
|
||||||
|
"var(--upper-mobile-secondary-sticky-fold)",
|
||||||
|
upperMobileStickyFold: "var(--upper-mobile-sticky-fold)",
|
||||||
|
upperMobileTertiaryStickyFold:
|
||||||
|
"var(--upper-mobile-tertiary-sticky-fold)",
|
||||||
|
lowerPrimaryStickyFold: "var(--lower-primary-sticky-fold)",
|
||||||
|
lowerSecondaryStickyFold: "var(--lower-secondary-sticky-fold)",
|
||||||
|
lowerTertiaryStickyFold: "var(--lower-tertiary-sticky-fold)",
|
||||||
|
sidebarPrimaryStickyFold: "var(--sidebar-primary-sticky-fold)",
|
||||||
|
},
|
||||||
|
colors: {
|
||||||
|
primary: "var(--primary-color)",
|
||||||
|
primaryLight: "var(--primary-light-color)",
|
||||||
|
primaryDark: "var(--primary-dark-color)",
|
||||||
|
primaryContrast: "var(--primary-contrast-color)",
|
||||||
|
secondary: "var(--secondary-color)",
|
||||||
|
secondaryLight: "var(--secondary-light-color)",
|
||||||
|
secondaryDark: "var(--secondary-dark-color)",
|
||||||
|
accent: "var(--accent-color)",
|
||||||
|
accentLight: "var(--accent-light-color)",
|
||||||
|
accentDark: "var(--accent-dark-color)",
|
||||||
|
accentContrast: "var(--accent-contrast-color)",
|
||||||
|
divider: "var(--divider-color)",
|
||||||
|
dividerLight: "var(--divider-light-color)",
|
||||||
|
dividerDark: "var(--divider-dark-color)",
|
||||||
|
error: "var(--error-color)",
|
||||||
|
tooltip: "var(--tooltip-color)",
|
||||||
|
popover: "var(--popover-color)",
|
||||||
|
gradientFrom: "var(--gradient-from-color)",
|
||||||
|
gradientVia: "var(--gradient-via-color)",
|
||||||
|
gradientTo: "var(--gradient-to-color)",
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
sans: "var(--font-sans)",
|
||||||
|
mono: "var(--font-mono)",
|
||||||
|
icon: "var(--font-icon)",
|
||||||
|
},
|
||||||
|
fontSize: {
|
||||||
|
tiny: "var(--font-size-tiny)",
|
||||||
|
body: "var(--font-size-body)",
|
||||||
|
},
|
||||||
|
lineHeight: {
|
||||||
|
body: "var(--line-height-body)",
|
||||||
|
},
|
||||||
|
cursor: {
|
||||||
|
nsResize: "ns-resize",
|
||||||
|
grab: "grab",
|
||||||
|
grabbing: "grabbing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -107,7 +107,10 @@ export default defineConfig({
|
|||||||
}),
|
}),
|
||||||
Components({
|
Components({
|
||||||
dts: "../hoppscotch-common/src/components.d.ts",
|
dts: "../hoppscotch-common/src/components.d.ts",
|
||||||
dirs: ["../hoppscotch-common/src/components"],
|
dirs: [
|
||||||
|
"../hoppscotch-common/src/components",
|
||||||
|
"../hoppscotch-ui/src/components",
|
||||||
|
],
|
||||||
directoryAsNamespace: true,
|
directoryAsNamespace: true,
|
||||||
resolvers: [
|
resolvers: [
|
||||||
IconResolver({
|
IconResolver({
|
||||||
|
|||||||
1246
pnpm-lock.yaml
generated
1246
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user