refactor: update hopp-ui to be independent (#2927)
Co-authored-by: Anwarul Islam <anwaarulislaam@gmail.com>
This commit is contained in:
@@ -19,7 +19,7 @@ Welcome to hoppscotch-ui, a collection of presentational components for our web
|
||||
|
||||
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 />`
|
||||
For example `Primary Button` component is in `button` directory and the file name is `Primary.vue`. So, use that you have to write `<HoppButtonPrimary />`
|
||||
|
||||
## Histoire
|
||||
|
||||
|
||||
@@ -2,13 +2,20 @@
|
||||
"name": "@hoppscotch/ui",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
"story:dev": "histoire dev",
|
||||
"story:build": "histoire build",
|
||||
"story:preview": "histoire preview",
|
||||
"do-build-prod": "pnpm run build",
|
||||
"postinstall": "pnpm run build",
|
||||
"do-build-ui": "pnpm run story:build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2.25",
|
||||
"vue-router": "^4.0.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hoppscotch/vue-toasted": "^0.1.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@@ -30,11 +37,10 @@
|
||||
"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"
|
||||
"vuedraggable-es": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@esbuild-plugins/node-globals-polyfill": "^0.1.1",
|
||||
@@ -60,10 +66,11 @@
|
||||
"rollup-plugin-polyfill-node": "^0.10.1",
|
||||
"sass": "^1.53.0",
|
||||
"typescript": "^4.5.4",
|
||||
"unplugin-icons": "^0.14.9",
|
||||
"unplugin-icons": "^0.15.3",
|
||||
"unplugin-vue-components": "^0.21.0",
|
||||
"vite": "^3.2.3",
|
||||
"vite": "^4.1.3",
|
||||
"vite-plugin-checker": "^0.5.1",
|
||||
"vite-plugin-dts": "2.0.0-beta.3",
|
||||
"vite-plugin-fonts": "^0.6.0",
|
||||
"vite-plugin-html-config": "^1.0.10",
|
||||
"vite-plugin-inspect": "^0.7.4",
|
||||
@@ -77,7 +84,13 @@
|
||||
"windicss": "^3.5.6"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"dist"
|
||||
]
|
||||
],
|
||||
"module": "./dist/index.es.js",
|
||||
"main": "./dist/index.es.js",
|
||||
"exports": {
|
||||
".": "./dist/index.es.js",
|
||||
"./style.css": "./dist/style.css"
|
||||
},
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
|
||||
@@ -1,64 +1,3 @@
|
||||
* {
|
||||
@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-50;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -130,89 +69,6 @@ a {
|
||||
}
|
||||
}
|
||||
|
||||
.cm-tooltip {
|
||||
.tippy-box {
|
||||
@apply shadow-none;
|
||||
@apply fixed;
|
||||
@apply inline-flex;
|
||||
@apply -mt-8;
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
@@ -246,243 +102,6 @@ hr {
|
||||
@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 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 hover:before:opacity-100;
|
||||
}
|
||||
|
||||
.no-splitter .splitpanes__splitter {
|
||||
@apply relative;
|
||||
}
|
||||
|
||||
.smart-splitter.splitpanes--vertical > .splitpanes__splitter {
|
||||
@apply w-0;
|
||||
@apply before:-left-0.5;
|
||||
@apply before:-right-0.5;
|
||||
@apply before:h-full;
|
||||
@apply bg-divider;
|
||||
}
|
||||
|
||||
.smart-splitter.splitpanes--horizontal > .splitpanes__splitter {
|
||||
@apply h-0;
|
||||
@apply before:-top-0.5;
|
||||
@apply before:-bottom-0.5;
|
||||
@apply before:w-full;
|
||||
@apply bg-divider;
|
||||
}
|
||||
|
||||
.no-splitter.splitpanes--vertical > .splitpanes__splitter {
|
||||
@apply w-0;
|
||||
@apply pointer-events-none;
|
||||
@apply bg-dividerLight;
|
||||
}
|
||||
|
||||
.no-splitter.splitpanes--horizontal > .splitpanes__splitter {
|
||||
@apply h-0;
|
||||
@apply pointer-events-none;
|
||||
@apply bg-dividerLight;
|
||||
}
|
||||
|
||||
.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;
|
||||
@@ -499,62 +118,3 @@ pre.ace_editor {
|
||||
@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;
|
||||
|
||||
&.env-found {
|
||||
@apply bg-accentDark;
|
||||
@apply hover:bg-accent;
|
||||
}
|
||||
|
||||
&.env-not-found {
|
||||
@apply bg-red-500;
|
||||
@apply hover:bg-red-600;
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
37
packages/hoppscotch-ui/src/components.d.ts
vendored
37
packages/hoppscotch-ui/src/components.d.ts
vendored
@@ -1,37 +0,0 @@
|
||||
// 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']
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<SmartLink
|
||||
:to="to"
|
||||
:blank="blank"
|
||||
<HoppSmartLink :to="to" :blank="blank"
|
||||
class="relative inline-flex items-center justify-center py-2 font-bold transition focus:outline-none focus-visible:bg-accentDark"
|
||||
:class="[
|
||||
color
|
||||
@@ -21,45 +19,29 @@
|
||||
'border border-accent hover:border-accentDark focus-visible:border-accentDark':
|
||||
outline,
|
||||
},
|
||||
]"
|
||||
:disabled="disabled"
|
||||
:tabindex="loading ? '-1' : '0'"
|
||||
role="button"
|
||||
>
|
||||
<span
|
||||
class="inline-flex items-center justify-center whitespace-nowrap"
|
||||
:class="[{ 'flex-row-reverse': reverse }, { 'opacity-50': loading }]"
|
||||
>
|
||||
<component
|
||||
:is="icon"
|
||||
v-if="icon"
|
||||
class="svg-icons"
|
||||
:class="[
|
||||
{ '!text-2xl': large },
|
||||
label ? (reverse ? 'ml-2' : 'mr-2') : '',
|
||||
]"
|
||||
/>
|
||||
]" :disabled="disabled" :tabindex="loading ? '-1' : '0'" role="button">
|
||||
<span class="inline-flex items-center justify-center whitespace-nowrap"
|
||||
:class="[{ 'flex-row-reverse': reverse }, { 'opacity-50': loading }]">
|
||||
<component :is="icon" v-if="icon" class="svg-icons" :class="[
|
||||
{ '!text-2xl': large },
|
||||
label ? (reverse ? 'ml-2' : 'mr-2') : '',
|
||||
]" />
|
||||
{{ label }}
|
||||
<div v-if="shortcut.length" class="<sm:hidden">
|
||||
<kbd
|
||||
v-for="(key, index) in shortcut"
|
||||
:key="`key-${index}`"
|
||||
class="shortcut-key !bg-accentDark !border-accentLight"
|
||||
>
|
||||
<kbd v-for="(key, index) in shortcut" :key="`key-${index}`"
|
||||
class="shortcut-key !bg-accentDark !border-accentLight">
|
||||
{{ key }}
|
||||
</kbd>
|
||||
</div>
|
||||
</span>
|
||||
<span
|
||||
v-if="loading"
|
||||
class="absolute inset-0 flex items-center justify-center"
|
||||
>
|
||||
<SmartSpinner />
|
||||
<span v-if="loading" class="absolute inset-0 flex items-center justify-center">
|
||||
<HoppSmartSpinner />
|
||||
</span>
|
||||
</SmartLink>
|
||||
</HoppSmartLink>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartLink, HoppSmartSpinner } from "../smart"
|
||||
import type { Component } from "vue"
|
||||
|
||||
interface Props {
|
||||
@@ -80,6 +62,7 @@ interface Props {
|
||||
outline?: boolean
|
||||
shortcut?: string[]
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
to: "",
|
||||
exact: true,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
<template>
|
||||
<SmartLink
|
||||
:to="to"
|
||||
:exact="exact"
|
||||
:blank="blank"
|
||||
<HoppSmartLink :to="to" :exact="exact" :blank="blank"
|
||||
class="inline-flex items-center justify-center py-2 font-semibold transition whitespace-nowrap focus:outline-none"
|
||||
:class="[
|
||||
color
|
||||
@@ -22,41 +19,26 @@
|
||||
'bg-primaryLight hover:bg-primaryDark focus-visible:bg-primaryDark':
|
||||
filled,
|
||||
},
|
||||
]"
|
||||
:disabled="disabled"
|
||||
:tabindex="loading ? '-1' : '0'"
|
||||
role="button"
|
||||
>
|
||||
<span
|
||||
v-if="!loading"
|
||||
class="inline-flex items-center justify-center whitespace-nowrap"
|
||||
:class="{ 'flex-row-reverse': reverse }"
|
||||
>
|
||||
<component
|
||||
:is="icon"
|
||||
v-if="icon"
|
||||
class="svg-icons"
|
||||
:class="[
|
||||
{ '!text-2xl': large },
|
||||
label ? (reverse ? 'ml-2' : 'mr-2') : '',
|
||||
]"
|
||||
/>
|
||||
]" :disabled="disabled" :tabindex="loading ? '-1' : '0'" role="button">
|
||||
<span v-if="!loading" class="inline-flex items-center justify-center whitespace-nowrap"
|
||||
:class="{ 'flex-row-reverse': reverse }">
|
||||
<component :is="icon" v-if="icon" class="svg-icons" :class="[
|
||||
{ '!text-2xl': large },
|
||||
label ? (reverse ? 'ml-2' : 'mr-2') : '',
|
||||
]" />
|
||||
{{ label }}
|
||||
<div v-if="shortcut.length" class="<sm:hidden">
|
||||
<kbd
|
||||
v-for="(key, index) in shortcut"
|
||||
:key="`key-${index}`"
|
||||
class="shortcut-key !bg-inherit"
|
||||
>
|
||||
<kbd v-for="(key, index) in shortcut" :key="`key-${index}`" class="shortcut-key !bg-inherit">
|
||||
{{ key }}
|
||||
</kbd>
|
||||
</div>
|
||||
</span>
|
||||
<SmartSpinner v-else />
|
||||
</SmartLink>
|
||||
<HoppSmartSpinner v-else />
|
||||
</HoppSmartLink>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartLink, HoppSmartSpinner } from "../smart";
|
||||
import type { Component } from "vue"
|
||||
|
||||
interface Props {
|
||||
|
||||
2
packages/hoppscotch-ui/src/components/button/index.ts
Normal file
2
packages/hoppscotch-ui/src/components/button/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as HoppButtonPrimary } from "./Primary.vue"
|
||||
export { default as HoppButtonSecondary } from "./Secondary.vue"
|
||||
@@ -1,47 +1,2 @@
|
||||
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,
|
||||
}
|
||||
export * from "./button"
|
||||
export * from "./smart"
|
||||
|
||||
@@ -1,33 +1,25 @@
|
||||
<template>
|
||||
<SmartLink
|
||||
:to="to"
|
||||
:exact="exact"
|
||||
:blank="blank"
|
||||
class="inline-flex items-center justify-center focus:outline-none"
|
||||
<HoppSmartLink :to="to" :exact="exact" :blank="blank" class="inline-flex items-center justify-center focus:outline-none"
|
||||
:class="[
|
||||
color
|
||||
? `text-${color}-500 hover:text-${color}-600 focus-visible:text-${color}-600`
|
||||
: 'hover:text-secondaryDark focus-visible:text-secondaryDark',
|
||||
{ 'opacity-75 cursor-not-allowed': disabled },
|
||||
{ 'flex-row-reverse': reverse },
|
||||
]"
|
||||
:disabled="disabled"
|
||||
tabindex="0"
|
||||
>
|
||||
<component
|
||||
:is="icon"
|
||||
v-if="icon"
|
||||
class="svg-icons"
|
||||
:class="label ? (reverse ? 'ml-2' : 'mr-2') : ''"
|
||||
/>
|
||||
]" :disabled="disabled" tabindex="0">
|
||||
<component :is="icon" v-if="icon" class="svg-icons" :class="label ? (reverse ? 'ml-2' : 'mr-2') : ''" />
|
||||
{{ label }}
|
||||
</SmartLink>
|
||||
</HoppSmartLink>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import HoppSmartLink from "./Link.vue";
|
||||
import { Component, defineComponent, PropType } from "vue"
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
HoppSmartLink
|
||||
},
|
||||
props: {
|
||||
to: {
|
||||
type: String,
|
||||
|
||||
@@ -1,36 +1,17 @@
|
||||
<template>
|
||||
<div class="autocomplete-wrapper">
|
||||
<input
|
||||
ref="acInput"
|
||||
:value="text"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
:placeholder="placeholder"
|
||||
:spellcheck="spellcheck"
|
||||
:autocapitalize="autocapitalize"
|
||||
:class="styles"
|
||||
@input.stop="
|
||||
<input ref="acInput" :value="text" type="text" autocomplete="off" :placeholder="placeholder" :spellcheck="spellcheck"
|
||||
:autocapitalize="autocapitalize" :class="styles" @input.stop="
|
||||
(e) => {
|
||||
$emit('input', e.target.value)
|
||||
updateSuggestions(e)
|
||||
}
|
||||
"
|
||||
@keyup="updateSuggestions"
|
||||
@click="updateSuggestions"
|
||||
@keydown="handleKeystroke"
|
||||
@change="$emit('change', $event)"
|
||||
/>
|
||||
<ul
|
||||
v-if="suggestions.length > 0 && suggestionsVisible"
|
||||
class="suggestions"
|
||||
:style="{ transform: `translate(${suggestionsOffsetLeft}px, 0)` }"
|
||||
>
|
||||
<li
|
||||
v-for="(suggestion, index) in suggestions"
|
||||
:key="`suggestion-${index}`"
|
||||
:class="{ active: currentSuggestionIndex === index }"
|
||||
@click.prevent="forceSuggestion(suggestion)"
|
||||
>
|
||||
" @keyup="updateSuggestions" @click="updateSuggestions" @keydown="handleKeystroke"
|
||||
@change="$emit('change', $event)" />
|
||||
<ul v-if="suggestions.length > 0 && suggestionsVisible" class="suggestions"
|
||||
:style="{ transform: `translate(${suggestionsOffsetLeft}px, 0)` }">
|
||||
<li v-for="(suggestion, index) in suggestions" :key="`suggestion-${index}`"
|
||||
:class="{ active: currentSuggestionIndex === index }" @click.prevent="forceSuggestion(suggestion)">
|
||||
{{ suggestion }}
|
||||
</li>
|
||||
</ul>
|
||||
@@ -182,7 +163,7 @@ export default defineComponent({
|
||||
case "Tab": {
|
||||
const activeSuggestion =
|
||||
this.suggestions[
|
||||
this.currentSuggestionIndex >= 0 ? this.currentSuggestionIndex : 0
|
||||
this.currentSuggestionIndex >= 0 ? this.currentSuggestionIndex : 0
|
||||
]
|
||||
|
||||
if (!activeSuggestion) {
|
||||
@@ -205,7 +186,7 @@ export default defineComponent({
|
||||
@apply relative;
|
||||
@apply contents;
|
||||
|
||||
input:focus + ul.suggestions,
|
||||
input:focus+ul.suggestions,
|
||||
ul.suggestions:hover {
|
||||
@apply block;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<template>
|
||||
<SmartModal
|
||||
v-if="show"
|
||||
dialog
|
||||
:title="confirm ?? t?.('modal.confirm') ?? 'Confirm'"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
@close="hideModal"
|
||||
>
|
||||
<HoppSmartModal v-if="show" dialog :title="confirm ?? t?.('modal.confirm') ?? 'Confirm'" role="dialog" aria-modal="true"
|
||||
@close="hideModal">
|
||||
<template #body>
|
||||
<div class="flex flex-col items-center justify-center">
|
||||
{{ title }}
|
||||
@@ -14,27 +8,19 @@
|
||||
</template>
|
||||
<template #footer>
|
||||
<span class="flex space-x-2">
|
||||
<ButtonPrimary
|
||||
v-focus
|
||||
:label="yes ?? t?.('action.yes') ?? 'Yes'"
|
||||
:loading="!!loadingState"
|
||||
outline
|
||||
@click="resolve"
|
||||
/>
|
||||
<ButtonSecondary
|
||||
:label="no ?? t?.('action.no') ?? 'No'"
|
||||
filled
|
||||
outline
|
||||
@click="hideModal"
|
||||
/>
|
||||
<HoppButtonPrimary v-focus :label="yes ?? t?.('action.yes') ?? 'Yes'" :loading="!!loadingState" outline
|
||||
@click="resolve" />
|
||||
<HoppButtonSecondary :label="no ?? t?.('action.no') ?? 'No'" filled outline @click="hideModal" />
|
||||
</span>
|
||||
</template>
|
||||
</SmartModal>
|
||||
</HoppSmartModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { inject } from "vue"
|
||||
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../index"
|
||||
import { HoppButtonPrimary, HoppButtonSecondary } from "../button"
|
||||
import { HoppSmartModal } from "."
|
||||
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../plugin"
|
||||
|
||||
const { t } = inject<HoppUIPluginOptions>(HOPP_UI_OPTIONS) ?? {}
|
||||
|
||||
|
||||
@@ -1,32 +1,22 @@
|
||||
<template>
|
||||
<div
|
||||
class="relative flex flex-col space-y-2 overflow-hidden"
|
||||
:class="expand ? 'h-full' : 'max-h-32'"
|
||||
>
|
||||
<div class="relative flex flex-col space-y-2 overflow-hidden" :class="expand ? 'h-full' : 'max-h-32'">
|
||||
<slot name="body"></slot>
|
||||
<div
|
||||
class="sticky inset-x-0 bottom-0 flex items-center justify-center flex-shrink-0 overflow-x-auto"
|
||||
>
|
||||
<ButtonSecondary
|
||||
:icon="expand ? IconChevronUp : IconChevronDown"
|
||||
:label="
|
||||
expand
|
||||
? less ?? t?.('action.less') ?? 'Less'
|
||||
: more ?? t?.('action.more') ?? 'More'
|
||||
"
|
||||
filled
|
||||
rounded
|
||||
@click="expand = !expand"
|
||||
/>
|
||||
<div class="sticky inset-x-0 bottom-0 flex items-center justify-center flex-shrink-0 overflow-x-auto">
|
||||
<HoppButtonSecondary :icon="expand ? IconChevronUp : IconChevronDown" :label="
|
||||
expand
|
||||
? less ?? t?.('action.less') ?? 'Less'
|
||||
: more ?? t?.('action.more') ?? 'More'
|
||||
" filled rounded @click="expand = !expand" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppButtonSecondary } from "../button"
|
||||
import IconChevronUp from "~icons/lucide/chevron-up"
|
||||
import IconChevronDown from "~icons/lucide/chevron-down"
|
||||
import { inject, ref } from "vue"
|
||||
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../index"
|
||||
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../plugin"
|
||||
|
||||
const { t } = inject<HoppUIPluginOptions>(HOPP_UI_OPTIONS) ?? {}
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
<template>
|
||||
<SmartLink
|
||||
:to="to"
|
||||
:exact="exact"
|
||||
:blank="blank"
|
||||
<HoppSmartLink :to="to" :exact="exact" :blank="blank"
|
||||
class="inline-flex items-center flex-shrink-0 px-4 py-2 rounded transition hover:bg-primaryDark hover:text-secondaryDark focus:outline-none focus-visible:bg-primaryDark focus-visible:text-secondaryDark"
|
||||
:class="[
|
||||
{ 'opacity-75 cursor-not-allowed': disabled },
|
||||
@@ -13,31 +10,15 @@
|
||||
'border border-divider hover:border-dividerDark focus-visible:border-dividerDark':
|
||||
outline,
|
||||
},
|
||||
]"
|
||||
:disabled="disabled"
|
||||
:tabindex="loading ? '-1' : '0'"
|
||||
role="menuitem"
|
||||
>
|
||||
<span
|
||||
v-if="!loading"
|
||||
class="inline-flex items-center"
|
||||
:class="{ 'self-start': !!infoIcon }"
|
||||
>
|
||||
<component
|
||||
:is="icon"
|
||||
v-if="icon"
|
||||
class="opacity-75 svg-icons"
|
||||
:class="[
|
||||
label ? (reverse ? 'ml-4' : 'mr-4') : '',
|
||||
{ 'text-accent': active },
|
||||
]"
|
||||
/>
|
||||
]" :disabled="disabled" :tabindex="loading ? '-1' : '0'" role="menuitem">
|
||||
<span v-if="!loading" class="inline-flex items-center" :class="{ 'self-start': !!infoIcon }">
|
||||
<component :is="icon" v-if="icon" class="opacity-75 svg-icons" :class="[
|
||||
label ? (reverse ? 'ml-4' : 'mr-4') : '',
|
||||
{ 'text-accent': active },
|
||||
]" />
|
||||
</span>
|
||||
<SmartSpinner v-else class="mr-4 text-secondaryDark" />
|
||||
<div
|
||||
class="inline-flex items-start flex-1 truncate"
|
||||
:class="{ 'flex-col': description }"
|
||||
>
|
||||
<HoppSmartSpinner v-else class="mr-4 text-secondaryDark" />
|
||||
<div class="inline-flex items-start flex-1 truncate" :class="{ 'flex-col': description }">
|
||||
<div class="font-semibold truncate">
|
||||
{{ label }}
|
||||
</div>
|
||||
@@ -45,28 +26,26 @@
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
<component
|
||||
:is="infoIcon"
|
||||
v-if="infoIcon"
|
||||
class="items-center self-center ml-4 svg-icons"
|
||||
:class="{ 'text-accent': activeInfoIcon }"
|
||||
/>
|
||||
<component :is="infoIcon" v-if="infoIcon" class="items-center self-center ml-4 svg-icons"
|
||||
:class="{ 'text-accent': activeInfoIcon }" />
|
||||
<div v-if="shortcut.length" class="ml-4 <sm:hidden font-medium">
|
||||
<kbd
|
||||
v-for="(key, index) in shortcut"
|
||||
:key="`key-${index}`"
|
||||
class="-mr-2 shortcut-key"
|
||||
>
|
||||
<kbd v-for="(key, index) in shortcut" :key="`key-${index}`" class="-mr-2 shortcut-key">
|
||||
{{ key }}
|
||||
</kbd>
|
||||
</div>
|
||||
</SmartLink>
|
||||
</HoppSmartLink>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import HoppSmartLink from "./Link.vue"
|
||||
import HoppSmartSpinner from "./Spinner.vue"
|
||||
import { defineComponent } from "vue"
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
HoppSmartLink,
|
||||
HoppSmartSpinner
|
||||
},
|
||||
props: {
|
||||
to: {
|
||||
type: String,
|
||||
|
||||
@@ -1,30 +1,12 @@
|
||||
<template>
|
||||
<button
|
||||
v-if="renderedTag === 'BUTTON'"
|
||||
aria-label="button"
|
||||
role="button"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<button v-if="renderedTag === 'BUTTON'" aria-label="button" role="button" v-bind="$attrs">
|
||||
<slot></slot>
|
||||
</button>
|
||||
<a
|
||||
v-else-if="renderedTag === 'ANCHOR' && !blank"
|
||||
aria-label="Link"
|
||||
:href="to"
|
||||
role="link"
|
||||
v-bind="updatedAttrs"
|
||||
>
|
||||
<a v-else-if="renderedTag === 'ANCHOR' && !blank" aria-label="Link" :href="to" role="link" v-bind="updatedAttrs">
|
||||
<slot></slot>
|
||||
</a>
|
||||
<a
|
||||
v-else-if="renderedTag === 'ANCHOR' && blank"
|
||||
aria-label="Link"
|
||||
:href="to"
|
||||
role="link"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
v-bind="updatedAttrs"
|
||||
>
|
||||
<a v-else-if="renderedTag === 'ANCHOR' && blank" aria-label="Link" :href="to" role="link" target="_blank" rel="noopener"
|
||||
v-bind="updatedAttrs">
|
||||
<slot></slot>
|
||||
</a>
|
||||
<RouterLink v-else :to="to" v-bind="updatedAttrs">
|
||||
@@ -33,6 +15,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { RouterLink } from "vue-router"
|
||||
/**
|
||||
* for preventing the automatic binding of $attrs.
|
||||
* we are manually binding $attrs or updatedAttrs.
|
||||
|
||||
@@ -101,7 +101,7 @@ import {
|
||||
onBeforeUnmount,
|
||||
inject,
|
||||
} from "vue"
|
||||
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../index"
|
||||
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../plugin"
|
||||
|
||||
const { t, onModalOpen, onModalClose } =
|
||||
inject<HoppUIPluginOptions>(HOPP_UI_OPTIONS) ?? {}
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
<template>
|
||||
<SmartItem
|
||||
:label="label"
|
||||
:icon="selected ? IconCircleDot : IconCircle"
|
||||
:active="selected"
|
||||
role="radio"
|
||||
:aria-checked="selected"
|
||||
@click="emit('change', value)"
|
||||
/>
|
||||
<HoppSmartItem :label="label" :icon="selected ? IconCircleDot : IconCircle" :active="selected" role="radio"
|
||||
:aria-checked="selected" @click="emit('change', value)" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartItem } from "."
|
||||
import IconCircleDot from "~icons/lucide/circle-dot"
|
||||
import IconCircle from "~icons/lucide/circle"
|
||||
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<SmartRadio
|
||||
v-for="(radio, index) in radios"
|
||||
:key="`radio-${index}`"
|
||||
:value="radio.value"
|
||||
:label="radio.label"
|
||||
:selected="modelValue === radio.value"
|
||||
@change="emit('update:modelValue', radio.value)"
|
||||
/>
|
||||
<HoppSmartRadio v-for="(radio, index) in radios" :key="`radio-${index}`" :value="radio.value" :label="radio.label"
|
||||
:selected="modelValue === radio.value" @change="emit('update:modelValue', radio.value)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartRadio } from '.';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:modelValue", value: string): void
|
||||
}>()
|
||||
|
||||
@@ -1,30 +1,18 @@
|
||||
<template>
|
||||
<div>
|
||||
<Transition name="fade" appear>
|
||||
<div
|
||||
v-if="show"
|
||||
class="fixed inset-0 z-20 transition-opacity"
|
||||
@keydown.esc="close()"
|
||||
>
|
||||
<div
|
||||
class="absolute inset-0 bg-primaryLight opacity-90 focus:outline-none"
|
||||
tabindex="0"
|
||||
@click="close()"
|
||||
></div>
|
||||
<div v-if="show" class="fixed inset-0 z-20 transition-opacity" @keydown.esc="close()">
|
||||
<div class="absolute inset-0 bg-primaryLight opacity-90 focus:outline-none" tabindex="0" @click="close()"></div>
|
||||
</div>
|
||||
</Transition>
|
||||
<Transition name="slide" appear>
|
||||
<aside
|
||||
v-if="show"
|
||||
class="fixed top-0 right-0 z-30 flex flex-col h-full max-w-full overflow-auto border-l shadow-xl border-dividerDark bg-primary w-96"
|
||||
>
|
||||
<div
|
||||
class="flex items-center justify-between p-2 border-b border-dividerLight"
|
||||
>
|
||||
<aside v-if="show"
|
||||
class="fixed top-0 right-0 z-30 flex flex-col h-full max-w-full overflow-auto border-l shadow-xl border-dividerDark bg-primary w-96">
|
||||
<div class="flex items-center justify-between p-2 border-b border-dividerLight">
|
||||
<h3 class="ml-4 heading">{{ title }}</h3>
|
||||
<span class="flex items-center">
|
||||
<kbd class="mr-2 shortcut-key">ESC</kbd>
|
||||
<ButtonSecondary :icon="IconX" @click="close()" />
|
||||
<HoppButtonSecondary :icon="IconX" @click="close()" />
|
||||
</span>
|
||||
</div>
|
||||
<slot name="content"></slot>
|
||||
@@ -34,6 +22,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppButtonSecondary } from "../button"
|
||||
import { onMounted, watch } from "vue"
|
||||
import IconX from "~icons/lucide/x"
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<template>
|
||||
<icon-lucide-loader class="animate-spin svg-icons" />
|
||||
<IconLucideLoader class="animate-spin svg-icons" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue"
|
||||
|
||||
export default defineComponent({})
|
||||
<script setup lang="ts">
|
||||
import IconLucideLoader from "~icons/lucide/loader"
|
||||
</script>
|
||||
|
||||
@@ -1,71 +1,37 @@
|
||||
<template>
|
||||
<div class="flex flex-col flex-1 h-auto overflow-y-hidden flex-nowrap">
|
||||
<div
|
||||
class="relative sticky top-0 z-10 flex-shrink-0 overflow-x-auto tabs bg-primaryLight"
|
||||
>
|
||||
<div class="relative sticky top-0 z-10 flex-shrink-0 overflow-x-auto tabs bg-primaryLight">
|
||||
<div class="flex flex-1 flex-shrink-0 w-0 overflow-x-auto">
|
||||
<div class="flex justify-between divide-x divide-dividerLight">
|
||||
<div class="flex">
|
||||
<draggable
|
||||
v-bind="dragOptions"
|
||||
:list="tabEntries"
|
||||
:style="tabStyles"
|
||||
:item-key="'window-'"
|
||||
class="flex flex-shrink-0 overflow-x-auto transition divide-x divide-dividerLight"
|
||||
@sort="sortTabs"
|
||||
>
|
||||
<draggable v-bind="dragOptions" :list="tabEntries" :style="tabStyles" :item-key="'window-'"
|
||||
class="flex flex-shrink-0 overflow-x-auto transition divide-x divide-dividerLight" @sort="sortTabs">
|
||||
<template #item="{ element: [tabID, tabMeta] }">
|
||||
<button
|
||||
:key="`removable-tab-${tabID}`"
|
||||
class="tab"
|
||||
:class="[{ active: modelValue === tabID }]"
|
||||
:aria-label="tabMeta.label || ''"
|
||||
role="button"
|
||||
@keyup.enter="selectTab(tabID)"
|
||||
@click="selectTab(tabID)"
|
||||
>
|
||||
<button :key="`removable-tab-${tabID}`" class="tab" :class="[{ active: modelValue === tabID }]"
|
||||
:aria-label="tabMeta.label || ''" role="button" @keyup.enter="selectTab(tabID)"
|
||||
@click="selectTab(tabID)">
|
||||
<div class="flex items-stretch truncate">
|
||||
<span
|
||||
v-if="tabMeta.icon"
|
||||
class="flex items-center justify-center mx-4 cursor-pointer"
|
||||
>
|
||||
<span v-if="tabMeta.icon" class="flex items-center justify-center mx-4 cursor-pointer">
|
||||
<component :is="tabMeta.icon" class="w-4 h-4 svg-icons" />
|
||||
</span>
|
||||
<span class="truncate">
|
||||
{{ tabMeta.label }}
|
||||
</span>
|
||||
</div>
|
||||
<ButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip', delay: [500, 20] }"
|
||||
:icon="IconX"
|
||||
:style="{
|
||||
visibility: tabMeta.isRemovable ? 'visible' : 'hidden',
|
||||
}"
|
||||
:title="closeText ?? t?.('action.close') ?? 'Close'"
|
||||
:class="[{ active: modelValue === tabID }, 'close']"
|
||||
class="mx-2 !p-0.5"
|
||||
@click.stop="emit('removeTab', tabID)"
|
||||
/>
|
||||
<HoppButtonSecondary v-tippy="{ theme: 'tooltip', delay: [500, 20] }" :icon="IconX" :style="{
|
||||
visibility: tabMeta.isRemovable ? 'visible' : 'hidden',
|
||||
}" :title="closeText ?? t?.('action.close') ?? 'Close'"
|
||||
:class="[{ active: modelValue === tabID }, 'close']" class="mx-2 !p-0.5"
|
||||
@click.stop="emit('removeTab', tabID)" />
|
||||
</button>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
<div
|
||||
class="sticky right-0 flex items-center justify-center flex-shrink-0 overflow-x-auto z-8"
|
||||
>
|
||||
<div class="sticky right-0 flex items-center justify-center flex-shrink-0 overflow-x-auto z-8">
|
||||
<slot name="actions">
|
||||
<span
|
||||
v-if="canAddNewTab"
|
||||
class="flex items-center justify-center px-2 py-1.5 bg-primaryLight z-8"
|
||||
>
|
||||
<ButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="newText ?? t?.('action.new') ?? 'New'"
|
||||
:icon="IconPlus"
|
||||
class="rounded !p-1"
|
||||
filled
|
||||
@click="addTab"
|
||||
/>
|
||||
<span v-if="canAddNewTab" class="flex items-center justify-center px-2 py-1.5 bg-primaryLight z-8">
|
||||
<ButtonSecondary v-tippy="{ theme: 'tooltip' }" :title="newText ?? t?.('action.new') ?? 'New'"
|
||||
:icon="IconPlus" class="rounded !p-1" filled @click="addTab" />
|
||||
</span>
|
||||
</slot>
|
||||
</div>
|
||||
@@ -79,15 +45,15 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppButtonSecondary } from "../button"
|
||||
import IconPlus from "~icons/lucide/plus"
|
||||
import IconX from "~icons/lucide/x"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import { not } from "fp-ts/Predicate"
|
||||
import * as A from "fp-ts/Array"
|
||||
import * as O from "fp-ts/Option"
|
||||
import { ref, ComputedRef, computed, provide, inject } from "vue"
|
||||
import type { Slot } from "vue"
|
||||
import draggable from "vuedraggable"
|
||||
import { ref, ComputedRef, computed, provide, inject, Slot } from "vue"
|
||||
import draggable from "vuedraggable-es"
|
||||
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../index"
|
||||
|
||||
export type TabMeta = {
|
||||
@@ -213,13 +179,13 @@ const addTab = () => {
|
||||
@apply whitespace-nowrap;
|
||||
@apply overflow-auto;
|
||||
@apply flex-shrink-0;
|
||||
@apply after:absolute;
|
||||
@apply after:inset-x-0;
|
||||
@apply after:bottom-0;
|
||||
@apply after:bg-dividerLight;
|
||||
@apply after:z-10;
|
||||
@apply after:h-0.25;
|
||||
@apply after:content-DEFAULT;
|
||||
@apply after: absolute;
|
||||
@apply after: inset-x-0;
|
||||
@apply after: bottom-0;
|
||||
@apply after: bg-dividerLight;
|
||||
@apply after: z-10;
|
||||
@apply after: h-0.25;
|
||||
@apply after: content-DEFAULT;
|
||||
|
||||
.tab {
|
||||
@apply relative;
|
||||
@@ -232,23 +198,23 @@ const addTab = () => {
|
||||
@apply items-center;
|
||||
@apply justify-between;
|
||||
@apply text-secondaryLight;
|
||||
@apply hover:bg-primaryDark;
|
||||
@apply hover:text-secondary;
|
||||
@apply focus-visible:text-secondaryDark;
|
||||
@apply before:absolute;
|
||||
@apply before:left-0;
|
||||
@apply before:right-0;
|
||||
@apply before:top-0;
|
||||
@apply before:bg-transparent;
|
||||
@apply before:z-2;
|
||||
@apply before:h-0.5;
|
||||
@apply before:content-DEFAULT;
|
||||
@apply hover: bg-primaryDark;
|
||||
@apply hover: text-secondary;
|
||||
@apply focus-visible: text-secondaryDark;
|
||||
@apply before: absolute;
|
||||
@apply before: left-0;
|
||||
@apply before: right-0;
|
||||
@apply before: top-0;
|
||||
@apply before: bg-transparent;
|
||||
@apply before: z-2;
|
||||
@apply before: h-0.5;
|
||||
@apply before: content-DEFAULT;
|
||||
@apply focus: before: bg-divider;
|
||||
|
||||
&.active {
|
||||
@apply text-secondaryDark;
|
||||
@apply bg-primary;
|
||||
@apply before:bg-accent;
|
||||
@apply before: bg-accent;
|
||||
}
|
||||
|
||||
.close {
|
||||
|
||||
20
packages/hoppscotch-ui/src/components/smart/index.ts
Normal file
20
packages/hoppscotch-ui/src/components/smart/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export { default as HoppSmartAnchor } from "./Anchor.vue"
|
||||
export { default as HoppSmartAutoComplete } from "./AutoComplete.vue"
|
||||
export { default as HoppSmartCheckbox } from "./Checkbox.vue"
|
||||
export { default as HoppSmartConfirmModal } from "./ConfirmModal.vue"
|
||||
export { default as HoppSmartExpand } from "./Expand.vue"
|
||||
export { default as HoppSmartFileChip } from "./FileChip.vue"
|
||||
export { default as HoppSmartIntersection } from "./Intersection.vue"
|
||||
export { default as HoppSmartItem } from "./Item.vue"
|
||||
export { default as HoppSmartLink } from "./Link.vue"
|
||||
export { default as HoppSmartModal } from "./Modal.vue"
|
||||
export { default as HoppSmartProgressRing } from "./ProgressRing.vue"
|
||||
export { default as HoppSmartRadio } from "./Radio.vue"
|
||||
export { default as HoppSmartRadioGroup } from "./RadioGroup.vue"
|
||||
export { default as HoppSmartSlideOver } from "./SlideOver.vue"
|
||||
export { default as HoppSmartSpinner } from "./Spinner.vue"
|
||||
export { default as HoppSmartTab } from "./Tab.vue"
|
||||
export { default as HoppSmartTabs } from "./Tabs.vue"
|
||||
export { default as HoppSmartToggle } from "./Toggle.vue"
|
||||
export { default as HoppSmartWindow } from "./Window.vue"
|
||||
export { default as HoppSmartWindows } from "./Windows.vue"
|
||||
@@ -1,33 +1,2 @@
|
||||
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
|
||||
export * from "./components"
|
||||
export * from "./plugin"
|
||||
|
||||
30
packages/hoppscotch-ui/src/plugin.ts
Normal file
30
packages/hoppscotch-ui/src/plugin.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import type { Plugin, App } from "vue"
|
||||
|
||||
import "./assets/scss/styles.scss"
|
||||
import "virtual:windi.css"
|
||||
|
||||
/**
|
||||
@constant HOPP_UI_OPTIONS
|
||||
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 [t] - A function for handling translations for the plugin.
|
||||
@property [onModalOpen] - A callback function that is called when a modal is opened.
|
||||
@property [onModalClose] - A callback function that is called when a modal is closed.
|
||||
*/
|
||||
|
||||
export type HoppUIPluginOptions = {
|
||||
t?: (key: string) => string
|
||||
onModalOpen?: () => void
|
||||
onModalClose?: () => void
|
||||
}
|
||||
|
||||
export const plugin: Plugin = {
|
||||
install(app: App, options: HoppUIPluginOptions = {}) {
|
||||
app.provide(HOPP_UI_OPTIONS, options)
|
||||
},
|
||||
}
|
||||
@@ -2,19 +2,14 @@
|
||||
<Story title="Anchor">
|
||||
<div class="text-secondaryLight text-tiny">
|
||||
By signing in, you are agreeing to our
|
||||
<SmartAnchor
|
||||
class="text-red-800 link"
|
||||
to="https://docs.hoppscotch.io/terms"
|
||||
blank
|
||||
label="Terms of Service"
|
||||
/>
|
||||
<HoppSmartAnchor class="text-red-800 link" to="https://docs.hoppscotch.io/terms" blank label="Terms of Service" />
|
||||
and
|
||||
<SmartAnchor
|
||||
class="text-red-600 link"
|
||||
to="https://docs.hoppscotch.io/privacy"
|
||||
blank
|
||||
label="Privacy Policy"
|
||||
/>
|
||||
<HoppSmartAnchor class="text-red-600 link" to="https://docs.hoppscotch.io/privacy" blank label="Privacy Policy" />
|
||||
</div>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartAnchor } from "../components/smart"
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,28 +1,21 @@
|
||||
<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()"
|
||||
/>
|
||||
<HoppSmartAutoComplete 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 { HoppSmartAutoComplete } from "../components/smart"
|
||||
import { ref } from "vue"
|
||||
|
||||
type GQLHeader = {
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<template>
|
||||
<Story title="Button">
|
||||
<Variant title="Primary">
|
||||
<ButtonPrimary label="Button" />
|
||||
<HoppButtonPrimary label="Button" />
|
||||
</Variant>
|
||||
<Variant title="Secondary">
|
||||
<ButtonSecondary label="Button" />
|
||||
<HoppButtonSecondary label="Button" />
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppButtonPrimary, HoppButtonSecondary } from "../components/button"
|
||||
</script>
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<Story title="Checkbox">
|
||||
<Variant title="Single">
|
||||
<SmartCheckbox :on="on" />
|
||||
<HoppSmartCheckbox :on="on" />
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartCheckbox } from "../components/smart"
|
||||
|
||||
import { ref } from "vue"
|
||||
|
||||
const on = ref(true)
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<template>
|
||||
<Story title="Confirm Modal">
|
||||
<SmartConfirmModal
|
||||
:show="show"
|
||||
:title="'Confirm Modal'"
|
||||
@hide-modal="show = false"
|
||||
@resolve="resolveConfirmModal"
|
||||
/>
|
||||
<HoppSmartConfirmModal :show="show" :title="'Confirm Modal'" @hide-modal="show = false"
|
||||
@resolve="resolveConfirmModal" />
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue"
|
||||
import { HoppSmartConfirmModal } from "../components/smart"
|
||||
|
||||
const show = ref(true)
|
||||
|
||||
|
||||
20
packages/hoppscotch-ui/src/stories/Expand.story.vue
Normal file
20
packages/hoppscotch-ui/src/stories/Expand.story.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<Story title="Expand">
|
||||
<HoppSmartExpand>
|
||||
<template #body>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quia quas culpa ea nesciunt, magni natus ex numquam perspiciatis,
|
||||
reprehenderit reiciendis necessitatibus nostrum laudantium illum tempora ducimus! Dignissimos officiis sed nisi.
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quia quas culpa ea nesciunt, magni natus ex numquam perspiciatis,
|
||||
reprehenderit reiciendis necessitatibus nostrum laudantium illum tempora ducimus! Dignissimos officiis sed nisi.
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quia quas culpa ea nesciunt, magni natus ex numquam perspiciatis,
|
||||
reprehenderit reiciendis necessitatibus nostrum laudantium illum tempora ducimus! Dignissimos officiis sed nisi.
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quia quas culpa ea nesciunt, magni natus ex numquam perspiciatis,
|
||||
reprehenderit reiciendis necessitatibus nostrum laudantium illum tempora ducimus! Dignissimos officiis sed nisi.
|
||||
</template>
|
||||
</HoppSmartExpand>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartExpand } from "../components/smart"
|
||||
</script>
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<Story title="Item">
|
||||
<Variant title="Single">
|
||||
<SmartItem :label="'Item'" :active-info-icon="false" />
|
||||
<HoppSmartItem :label="'Item'" :active-info-icon="false" />
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartItem } from "../components/smart"
|
||||
</script>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
<template>
|
||||
<Story title="Link">
|
||||
<Variant title="Text Link">
|
||||
<SmartLink :to="link" :blank="true"> Click here </SmartLink>
|
||||
<HoppSmartLink :to="link" :blank="true"> Click here </HoppSmartLink>
|
||||
</Variant>
|
||||
<Variant title="Button Link">
|
||||
<SmartLink :to="link" :blank="true">
|
||||
<ButtonPrimary label="Click here" />
|
||||
</SmartLink>
|
||||
<HoppSmartLink :to="link" :blank="true">
|
||||
<HoppButtonPrimary label="Click here" />
|
||||
</HoppSmartLink>
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartLink } from "../components/smart"
|
||||
import { HoppButtonPrimary } from "../components/button"
|
||||
import { ref } from "vue"
|
||||
|
||||
const link = ref("/")
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
<template>
|
||||
<Story title="Modal">
|
||||
<SmartModal
|
||||
:show="show"
|
||||
:title="'Modal Title'"
|
||||
@hide-modal="show = false"
|
||||
@resolve="resolveConfirmModal"
|
||||
/>
|
||||
<HoppSmartModal :show="show" :title="'Modal Title'" @hide-modal="show = false" @resolve="resolveConfirmModal" />
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { HoppSmartModal } from "../components/smart"
|
||||
import { ref } from "vue"
|
||||
|
||||
const show = ref(true)
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
<template>
|
||||
<Story title="Progress Ring">
|
||||
<SmartProgressRing
|
||||
class="mr-2 text-red-500"
|
||||
:radius="8"
|
||||
:stroke="1.5"
|
||||
:progress="(failedTests / totalTests) * 100"
|
||||
/>
|
||||
<HoppSmartProgressRing class="mr-2 text-red-500" :radius="8" :stroke="1.5"
|
||||
:progress="(failedTests / totalTests) * 100" />
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartProgressRing } from "../components/smart"
|
||||
const totalTests = 10
|
||||
const failedTests = 2
|
||||
</script>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<template>
|
||||
<Story title="Radio">
|
||||
<Variant title="Single">
|
||||
<SmartRadio />
|
||||
<HoppSmartRadio />
|
||||
</Variant>
|
||||
<Variant title="Group">
|
||||
<SmartRadioGroup :radios="radios" :model-value="selected" />
|
||||
<HoppSmartRadioGroup :radios="radios" :model-value="selected" />
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue"
|
||||
import { HoppSmartRadio, HoppSmartRadioGroup } from "../components/smart"
|
||||
|
||||
const selected = ref("option1")
|
||||
const radios = [
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
<template>
|
||||
<Story title="Slider Over">
|
||||
<SmartSlideOver :show="show" :title="'Title'" @close="show = false">
|
||||
<HoppSmartSlideOver :show="show" :title="'Title'" @close="show = false">
|
||||
<template #content>
|
||||
<h1>Content</h1>
|
||||
</template>
|
||||
</SmartSlideOver>
|
||||
</HoppSmartSlideOver>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartSlideOver } from "../components/smart"
|
||||
import { ref } from "vue"
|
||||
|
||||
const show = ref(true)
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<Story title="Spinner">
|
||||
<SmartSpinner />
|
||||
<HoppSmartSpinner />
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartSpinner } from "../components/smart"
|
||||
</script>
|
||||
|
||||
@@ -1,19 +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">
|
||||
<HoppSmartTabs id="my-tab" v-model="selectedTab" render-inactive-tabs>
|
||||
<HoppSmartTab id="tab1" label="Tab 1">
|
||||
<h1>Tab 1 content</h1>
|
||||
</SmartTab>
|
||||
<SmartTab id="tab2" label="Tab 2">
|
||||
</HoppSmartTab>
|
||||
<HoppSmartTab id="tab2" label="Tab 2">
|
||||
<h1>Tab 2 content</h1>
|
||||
</SmartTab>
|
||||
</SmartTabs>
|
||||
</HoppSmartTab>
|
||||
</HoppSmartTabs>
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartTabs, HoppSmartTab } from "../components/smart"
|
||||
import { ref } from "vue"
|
||||
|
||||
const selectedTab = ref("tab1")
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<template>
|
||||
<Story title="Toggle">
|
||||
<SmartToggle :on="on" @change="change"> Turn on </SmartToggle>
|
||||
<HoppSmartToggle :on="on" @change="change"> Turn on </HoppSmartToggle>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartToggle } from "../components/smart"
|
||||
import { ref } from "vue"
|
||||
|
||||
const on = ref(true)
|
||||
|
||||
@@ -1,27 +1,18 @@
|
||||
<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>
|
||||
<HoppSmartWindows :id="'my-window'" v-model="selectedWindow" @add-tab="openNewTab" @remove-tab="removeTab"
|
||||
@sort="sortTabs">
|
||||
<HoppSmartWindow v-for="window in tabs" :id="window.id" :key="'tab_' + window.id" :label="window.name"
|
||||
:is-removable="window.removable">
|
||||
</HoppSmartWindow>
|
||||
</HoppSmartWindows>
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HoppSmartWindows, HoppSmartWindow } from "../components/smart"
|
||||
import { ref } from "vue"
|
||||
|
||||
const selectedWindow = ref("window1")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"allowJs": true,
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
@@ -10,17 +11,34 @@
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"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/*"]
|
||||
"~/*": [
|
||||
"./src/*"
|
||||
],
|
||||
"@composables/*": [
|
||||
"./src/composables/*"
|
||||
],
|
||||
"@components/*": [
|
||||
"./src/components/*"
|
||||
],
|
||||
"@helpers/*": [
|
||||
"./src/helpers/*"
|
||||
],
|
||||
"@modules/*": [
|
||||
"./src/modules/*"
|
||||
],
|
||||
"@workers/*": [
|
||||
"./src/workers/*"
|
||||
],
|
||||
"@functional/*": [
|
||||
"./src/helpers/functional/*"
|
||||
]
|
||||
},
|
||||
"types": [
|
||||
"vite/client",
|
||||
@@ -30,5 +48,10 @@
|
||||
"vite-plugin-pwa/client"
|
||||
]
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,60 +1,40 @@
|
||||
import vue from "@vitejs/plugin-vue"
|
||||
import dts from "vite-plugin-dts"
|
||||
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({
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
dts({
|
||||
insertTypesEntry: true,
|
||||
skipDiagnostics: true,
|
||||
outputDir: ['dist']
|
||||
}),
|
||||
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"
|
||||
),
|
||||
},
|
||||
compiler: "vue3"
|
||||
}),
|
||||
], // to process SFC
|
||||
build: {
|
||||
sourcemap: true,
|
||||
minify: false,
|
||||
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`,
|
||||
formats: ["es"],
|
||||
fileName: (format, entry) => `${entry}.${format}.js`,
|
||||
},
|
||||
rollupOptions: {
|
||||
// external modules won't be bundled into HoppUI library
|
||||
external: ["vue"], // not every external has a global
|
||||
external: ["vue", "vue-router"],
|
||||
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
|
||||
emptyOutDir: true
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user