mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-20 14:56:17 -04:00
feat(ui-lib): demo pages for c-lib components
This commit is contained in:
parent
e88c1d5f2c
commit
92bd83536f
14 changed files with 294 additions and 248 deletions
5
components.d.ts
vendored
5
components.d.ts
vendored
|
@ -21,16 +21,21 @@ declare module '@vue/runtime-core' {
|
||||||
Bip39Generator: typeof import('./src/tools/bip39-generator/bip39-generator.vue')['default']
|
Bip39Generator: typeof import('./src/tools/bip39-generator/bip39-generator.vue')['default']
|
||||||
CaseConverter: typeof import('./src/tools/case-converter/case-converter.vue')['default']
|
CaseConverter: typeof import('./src/tools/case-converter/case-converter.vue')['default']
|
||||||
CButton: typeof import('./src/ui/c-button/c-button.vue')['default']
|
CButton: typeof import('./src/ui/c-button/c-button.vue')['default']
|
||||||
|
'CButton.demo': typeof import('./src/ui/c-button/c-button.demo.vue')['default']
|
||||||
CCard: typeof import('./src/ui/c-card/c-card.vue')['default']
|
CCard: typeof import('./src/ui/c-card/c-card.vue')['default']
|
||||||
|
'CCard.demo': typeof import('./src/ui/c-card/c-card.demo.vue')['default']
|
||||||
ChmodCalculator: typeof import('./src/tools/chmod-calculator/chmod-calculator.vue')['default']
|
ChmodCalculator: typeof import('./src/tools/chmod-calculator/chmod-calculator.vue')['default']
|
||||||
Chronometer: typeof import('./src/tools/chronometer/chronometer.vue')['default']
|
Chronometer: typeof import('./src/tools/chronometer/chronometer.vue')['default']
|
||||||
CLink: typeof import('./src/ui/c-link/c-link.vue')['default']
|
CLink: typeof import('./src/ui/c-link/c-link.vue')['default']
|
||||||
|
'CLink.demo': typeof import('./src/ui/c-link/c-link.demo.vue')['default']
|
||||||
CollapsibleToolMenu: typeof import('./src/components/CollapsibleToolMenu.vue')['default']
|
CollapsibleToolMenu: typeof import('./src/components/CollapsibleToolMenu.vue')['default']
|
||||||
ColorConverter: typeof import('./src/tools/color-converter/color-converter.vue')['default']
|
ColorConverter: typeof import('./src/tools/color-converter/color-converter.vue')['default']
|
||||||
ColoredCard: typeof import('./src/components/ColoredCard.vue')['default']
|
ColoredCard: typeof import('./src/components/ColoredCard.vue')['default']
|
||||||
CopyableIpLike: typeof import('./src/tools/ipv4-subnet-calculator/copyable-ip-like.vue')['default']
|
CopyableIpLike: typeof import('./src/tools/ipv4-subnet-calculator/copyable-ip-like.vue')['default']
|
||||||
CrontabGenerator: typeof import('./src/tools/crontab-generator/crontab-generator.vue')['default']
|
CrontabGenerator: typeof import('./src/tools/crontab-generator/crontab-generator.vue')['default']
|
||||||
DateTimeConverter: typeof import('./src/tools/date-time-converter/date-time-converter.vue')['default']
|
DateTimeConverter: typeof import('./src/tools/date-time-converter/date-time-converter.vue')['default']
|
||||||
|
'Demo.routes': typeof import('./src/ui/demo/demo.routes.vue')['default']
|
||||||
|
DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default']
|
||||||
DeviceInformation: typeof import('./src/tools/device-information/device-information.vue')['default']
|
DeviceInformation: typeof import('./src/tools/device-information/device-information.vue')['default']
|
||||||
DiffViewer: typeof import('./src/tools/json-diff/diff-viewer/diff-viewer.vue')['default']
|
DiffViewer: typeof import('./src/tools/json-diff/diff-viewer/diff-viewer.vue')['default']
|
||||||
DockerRunToDockerComposeConverter: typeof import('./src/tools/docker-run-to-docker-compose-converter/docker-run-to-docker-compose-converter.vue')['default']
|
DockerRunToDockerComposeConverter: typeof import('./src/tools/docker-run-to-docker-compose-converter/docker-run-to-docker-compose-converter.vue')['default']
|
||||||
|
|
|
@ -23,9 +23,9 @@ export const config = figue({
|
||||||
env: {
|
env: {
|
||||||
doc: 'Application current env',
|
doc: 'Application current env',
|
||||||
format: 'enum',
|
format: 'enum',
|
||||||
values: ['production', 'development', 'test'],
|
values: ['production', 'development', 'preview', 'test'],
|
||||||
default: 'development',
|
default: 'development',
|
||||||
env: 'MODE',
|
env: 'VITE_VERCEL_ENV',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plausible: {
|
plausible: {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import HomePage from './pages/Home.page.vue';
|
||||||
import NotFound from './pages/404.page.vue';
|
import NotFound from './pages/404.page.vue';
|
||||||
import { tools } from './tools';
|
import { tools } from './tools';
|
||||||
import { config } from './config';
|
import { config } from './config';
|
||||||
|
import { routes as demoRoutes } from './ui/demo/demo.routes';
|
||||||
|
|
||||||
const toolsRoutes = tools.map(({ path, name, component, ...config }) => ({
|
const toolsRoutes = tools.map(({ path, name, component, ...config }) => ({
|
||||||
path,
|
path,
|
||||||
|
@ -32,6 +33,7 @@ const router = createRouter({
|
||||||
},
|
},
|
||||||
...toolsRoutes,
|
...toolsRoutes,
|
||||||
...toolsRedirectRoutes,
|
...toolsRedirectRoutes,
|
||||||
|
...(config.app.env === 'development' ? demoRoutes : []),
|
||||||
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
|
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
29
src/ui/c-button/c-button.demo.vue
Normal file
29
src/ui/c-button/c-button.demo.vue
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<div v-for="buttonVariant of buttonVariants" :key="buttonVariant">
|
||||||
|
<h2>{{ _.capitalize(buttonVariant) }}</h2>
|
||||||
|
|
||||||
|
<c-button v-for="buttonType of buttonTypes" :key="buttonType" :variant="buttonVariant" :type="buttonType" mx-1>
|
||||||
|
Button
|
||||||
|
</c-button>
|
||||||
|
|
||||||
|
<c-button
|
||||||
|
v-for="buttonType of buttonTypes"
|
||||||
|
:key="buttonType"
|
||||||
|
:variant="buttonVariant"
|
||||||
|
:type="buttonType"
|
||||||
|
circle
|
||||||
|
mx-1
|
||||||
|
>
|
||||||
|
A
|
||||||
|
</c-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
const buttonVariants = ['basic', 'text'];
|
||||||
|
const buttonTypes = ['default', 'primary'];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
|
@ -1,240 +1,76 @@
|
||||||
|
import { darken, lighten } from '../color/color.models';
|
||||||
import { defineThemes } from '../theme/theme.models';
|
import { defineThemes } from '../theme/theme.models';
|
||||||
import { appThemes } from '../theme/themes';
|
import { appThemes } from '../theme/themes';
|
||||||
|
|
||||||
export const { useTheme } = defineThemes({
|
const createState = ({
|
||||||
dark: {
|
textColor,
|
||||||
basic: {
|
backgroundColor,
|
||||||
default: {
|
hoverBackground,
|
||||||
textColor: appThemes.dark.text.baseColor,
|
hoveredTextColor = textColor,
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.08)',
|
pressedBackground,
|
||||||
|
pressedTextColor = textColor,
|
||||||
hover: {
|
}: {
|
||||||
textColor: appThemes.dark.text.baseColor,
|
textColor: string;
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.12)',
|
backgroundColor: string;
|
||||||
},
|
hoverBackground: string;
|
||||||
|
hoveredTextColor?: string;
|
||||||
pressed: {
|
pressedBackground: string;
|
||||||
textColor: appThemes.dark.text.baseColor,
|
pressedTextColor?: string;
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.24)',
|
}) => ({
|
||||||
},
|
textColor,
|
||||||
|
backgroundColor,
|
||||||
outline: {
|
hover: { textColor: hoveredTextColor, backgroundColor: hoverBackground },
|
||||||
color: appThemes.dark.primary.color,
|
pressed: { textColor: pressedTextColor, backgroundColor: pressedBackground },
|
||||||
},
|
});
|
||||||
},
|
|
||||||
|
const createTheme = ({ style }: { style: 'light' | 'dark' }) => {
|
||||||
primary: {
|
const theme = appThemes[style];
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.dark.primary.color,
|
return {
|
||||||
|
basic: {
|
||||||
hover: {
|
default: createState({
|
||||||
textColor: appThemes.dark.text.baseColor,
|
textColor: theme.text.baseColor,
|
||||||
backgroundColor: appThemes.dark.primary.colorHover,
|
backgroundColor: theme.default.color,
|
||||||
},
|
hoverBackground: theme.default.colorHover,
|
||||||
|
pressedBackground: theme.default.colorPressed,
|
||||||
pressed: {
|
}),
|
||||||
textColor: appThemes.dark.text.baseColor,
|
primary: createState({
|
||||||
backgroundColor: appThemes.dark.primary.colorPressed,
|
textColor: theme.primary.color,
|
||||||
},
|
backgroundColor: theme.primary.colorFaded,
|
||||||
|
hoverBackground: lighten(theme.primary.colorFaded, 30),
|
||||||
outline: {
|
pressedBackground: darken(theme.primary.colorFaded, 30),
|
||||||
color: appThemes.dark.primary.color,
|
}),
|
||||||
},
|
warning: createState({
|
||||||
},
|
textColor: theme.text.baseColor,
|
||||||
|
backgroundColor: theme.warning.color,
|
||||||
warning: {
|
hoverBackground: theme.warning.colorHover,
|
||||||
textColor: appThemes.dark.text.baseColor,
|
pressedBackground: theme.warning.colorPressed,
|
||||||
backgroundColor: appThemes.dark.warning.color,
|
}),
|
||||||
|
},
|
||||||
hover: {
|
text: {
|
||||||
textColor: appThemes.dark.text.baseColor,
|
default: createState({
|
||||||
backgroundColor: appThemes.dark.warning.colorHover,
|
textColor: theme.text.baseColor,
|
||||||
},
|
backgroundColor: 'transparent',
|
||||||
|
hoverBackground: theme.default.colorHover,
|
||||||
pressed: {
|
pressedBackground: theme.default.colorPressed,
|
||||||
textColor: appThemes.dark.text.baseColor,
|
}),
|
||||||
backgroundColor: appThemes.dark.warning.colorPressed,
|
primary: createState({
|
||||||
},
|
textColor: theme.primary.color,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
outline: {
|
hoverBackground: theme.primary.colorFaded,
|
||||||
color: appThemes.dark.warning.color,
|
pressedBackground: darken(theme.primary.colorFaded, 30),
|
||||||
},
|
}),
|
||||||
},
|
warning: createState({
|
||||||
},
|
textColor: theme.text.baseColor,
|
||||||
|
backgroundColor: theme.warning.color,
|
||||||
text: {
|
hoverBackground: theme.warning.colorHover,
|
||||||
default: {
|
pressedBackground: theme.warning.colorPressed,
|
||||||
textColor: appThemes.dark.text.baseColor,
|
}),
|
||||||
backgroundColor: 'transparent',
|
},
|
||||||
|
};
|
||||||
hover: {
|
};
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.12)',
|
export const { useTheme } = defineThemes({
|
||||||
},
|
dark: createTheme({ style: 'dark' }),
|
||||||
|
light: createTheme({ style: 'light' }),
|
||||||
pressed: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.82)',
|
|
||||||
},
|
|
||||||
|
|
||||||
outline: {
|
|
||||||
color: appThemes.dark.primary.color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
primary: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.dark.primary.color,
|
|
||||||
|
|
||||||
hover: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.dark.primary.colorHover,
|
|
||||||
},
|
|
||||||
|
|
||||||
pressed: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.dark.primary.colorPressed,
|
|
||||||
},
|
|
||||||
|
|
||||||
outline: {
|
|
||||||
color: appThemes.dark.primary.color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
warning: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.dark.warning.color,
|
|
||||||
|
|
||||||
hover: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.dark.warning.colorHover,
|
|
||||||
},
|
|
||||||
|
|
||||||
pressed: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.dark.warning.colorPressed,
|
|
||||||
},
|
|
||||||
|
|
||||||
outline: {
|
|
||||||
color: appThemes.dark.warning.color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
light: {
|
|
||||||
basic: {
|
|
||||||
default: {
|
|
||||||
textColor: appThemes.light.text.baseColor,
|
|
||||||
backgroundColor: 'rgba(46, 51, 56, 0.05)',
|
|
||||||
|
|
||||||
hover: {
|
|
||||||
textColor: appThemes.light.text.baseColor,
|
|
||||||
backgroundColor: 'rgba(46, 51, 56, 0.09)',
|
|
||||||
},
|
|
||||||
|
|
||||||
pressed: {
|
|
||||||
textColor: appThemes.light.text.baseColor,
|
|
||||||
backgroundColor: 'rgba(46, 51, 56, 0.22)',
|
|
||||||
},
|
|
||||||
|
|
||||||
outline: {
|
|
||||||
color: appThemes.light.primary.color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
primary: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.light.primary.color,
|
|
||||||
|
|
||||||
hover: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.light.primary.colorHover,
|
|
||||||
},
|
|
||||||
|
|
||||||
pressed: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.light.primary.colorPressed,
|
|
||||||
},
|
|
||||||
|
|
||||||
outline: {
|
|
||||||
color: appThemes.light.primary.color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
warning: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.light.warning.color,
|
|
||||||
|
|
||||||
hover: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.light.warning.colorHover,
|
|
||||||
},
|
|
||||||
|
|
||||||
pressed: {
|
|
||||||
textColor: appThemes.dark.text.baseColor,
|
|
||||||
backgroundColor: appThemes.light.warning.colorPressed,
|
|
||||||
},
|
|
||||||
|
|
||||||
outline: {
|
|
||||||
color: appThemes.light.warning.color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
default: {
|
|
||||||
textColor: appThemes.light.text.baseColor,
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
|
|
||||||
hover: {
|
|
||||||
textColor: appThemes.light.text.baseColor,
|
|
||||||
backgroundColor: 'rgba(46, 51, 56, 0.09)',
|
|
||||||
},
|
|
||||||
|
|
||||||
pressed: {
|
|
||||||
textColor: appThemes.light.text.baseColor,
|
|
||||||
backgroundColor: 'rgba(46, 51, 56, 0.13)',
|
|
||||||
},
|
|
||||||
|
|
||||||
outline: {
|
|
||||||
color: appThemes.light.primary.color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
primary: {
|
|
||||||
textColor: appThemes.light.primary.color,
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
|
|
||||||
hover: {
|
|
||||||
textColor: appThemes.light.primary.colorHover,
|
|
||||||
backgroundColor: 'rgba(46, 51, 56, 0.09)',
|
|
||||||
},
|
|
||||||
|
|
||||||
pressed: {
|
|
||||||
textColor: appThemes.light.primary.colorPressed,
|
|
||||||
backgroundColor: 'rgba(46, 51, 56, 0.13)',
|
|
||||||
},
|
|
||||||
|
|
||||||
outline: {
|
|
||||||
color: appThemes.light.primary.color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
warning: {
|
|
||||||
textColor: appThemes.light.warning.color,
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
|
|
||||||
hover: {
|
|
||||||
textColor: appThemes.light.warning.colorHover,
|
|
||||||
backgroundColor: 'rgba(46, 51, 56, 0.09)',
|
|
||||||
},
|
|
||||||
|
|
||||||
pressed: {
|
|
||||||
textColor: appThemes.light.warning.colorPressed,
|
|
||||||
backgroundColor: 'rgba(46, 51, 56, 0.13)',
|
|
||||||
},
|
|
||||||
|
|
||||||
outline: {
|
|
||||||
color: appThemes.light.warning.color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { RouteLocationRaw } from 'vue-router';
|
import type { RouteLocationRaw } from 'vue-router';
|
||||||
import { useTheme } from './c-button.theme';
|
import { useTheme } from './c-button.theme';
|
||||||
|
import { useAppTheme } from '../theme/themes';
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -56,11 +57,11 @@ const tag = computed(() => {
|
||||||
}
|
}
|
||||||
return 'button';
|
return 'button';
|
||||||
});
|
});
|
||||||
|
const appTheme = useAppTheme();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.c-button {
|
.c-button {
|
||||||
margin: 0;
|
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
|
@ -103,7 +104,7 @@ const tag = computed(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: 2px solid v-bind('variantTheme.outline.color');
|
outline: 1px solid v-bind('appTheme.primary.color');
|
||||||
}
|
}
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
|
|
13
src/ui/c-card/c-card.demo.vue
Normal file
13
src/ui/c-card/c-card.demo.vue
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Default</h2>
|
||||||
|
|
||||||
|
<c-card title="Title">
|
||||||
|
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Repudiandae ipsa reiciendis facilis officia nulla.
|
||||||
|
Laboriosam cumque molestias excepturi doloribus nulla nemo quod ratione rerum possimus. Excepturi nihil possimus
|
||||||
|
error itaque.
|
||||||
|
</c-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup></script>
|
12
src/ui/c-link/c-link.demo.vue
Normal file
12
src/ui/c-link/c-link.demo.vue
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Default</h2>
|
||||||
|
<c-link mx-1> Link </c-link>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import CLink from './c-link.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
|
@ -16,7 +16,15 @@ const props = defineProps<{
|
||||||
const { href, to } = toRefs(props);
|
const { href, to } = toRefs(props);
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const tag = computed(() => (href?.value ? 'a' : RouterLink));
|
const tag = computed(() => {
|
||||||
|
if (href?.value) {
|
||||||
|
return 'a';
|
||||||
|
}
|
||||||
|
if (to?.value) {
|
||||||
|
return RouterLink;
|
||||||
|
}
|
||||||
|
return 'span';
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
40
src/ui/color/color.models.test.ts
Normal file
40
src/ui/color/color.models.test.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import { describe, test, expect } from 'vitest';
|
||||||
|
import { darken, lighten, setOpacity } from './color.models';
|
||||||
|
|
||||||
|
describe('color models', () => {
|
||||||
|
describe('lighten', () => {
|
||||||
|
test('lightens a color', () => {
|
||||||
|
expect(lighten('#000000', 10)).toBe('#0a0a0a');
|
||||||
|
expect(lighten('#000000', 20)).toBe('#141414');
|
||||||
|
expect(lighten('#ffffff', 30)).toBe('#ffffff');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('lightens a color with alpha', () => {
|
||||||
|
expect(lighten('#00000080', 10)).toBe('#0a0a0a80');
|
||||||
|
expect(lighten('#00000080', 20)).toBe('#14141480');
|
||||||
|
expect(lighten('#ffffff80', 30)).toBe('#ffffff80');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('darken', () => {
|
||||||
|
test('darkens a color', () => {
|
||||||
|
expect(darken('#ffffff', 10)).toBe('#f5f5f5');
|
||||||
|
expect(darken('#ffffff', 20)).toBe('#ebebeb');
|
||||||
|
expect(darken('#000000', 30)).toBe('#000000');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('darkens a color with alpha', () => {
|
||||||
|
expect(darken('#ffffff80', 10)).toBe('#f5f5f580');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setOpacity', () => {
|
||||||
|
test('sets the opacity of a color', () => {
|
||||||
|
expect(setOpacity('#000000', 0.5)).toBe('#00000080');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sets the opacity of a color with alpha', () => {
|
||||||
|
expect(setOpacity('#00000000', 0.5)).toBe('#00000080');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
33
src/ui/color/color.models.ts
Normal file
33
src/ui/color/color.models.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
export { lighten, darken, setOpacity };
|
||||||
|
|
||||||
|
const clampHex = (value: number) => Math.max(0, Math.min(255, Math.round(value)));
|
||||||
|
|
||||||
|
function lighten(color: string, amount: number): string {
|
||||||
|
const alpha = color.length === 9 ? color.slice(7) : '';
|
||||||
|
const num = parseInt(color.slice(1, 7), 16);
|
||||||
|
|
||||||
|
const r = clampHex(((num >> 16) & 255) + amount);
|
||||||
|
const g = clampHex(((num >> 8) & 255) + amount);
|
||||||
|
const b = clampHex((num & 255) + amount);
|
||||||
|
|
||||||
|
return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}${alpha}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function darken(color: string, amount: number): string {
|
||||||
|
return lighten(color, -amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOpacity(color: string, opacity: number): string {
|
||||||
|
const alpha = clampHex(Math.round(opacity * 255))
|
||||||
|
.toString(16)
|
||||||
|
.padStart(2, '0');
|
||||||
|
|
||||||
|
if (color.length === 7) {
|
||||||
|
return `${color}${alpha}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color.length === 9) {
|
||||||
|
return `${color.slice(0, 7)}${alpha}`;
|
||||||
|
}
|
||||||
|
throw new Error('Invalid hex color');
|
||||||
|
}
|
33
src/ui/demo/demo-wrapper.vue
Normal file
33
src/ui/demo/demo-wrapper.vue
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<template>
|
||||||
|
<div mt-2 w-full p-8>
|
||||||
|
<h1>c-lib components</h1>
|
||||||
|
|
||||||
|
<div flex>
|
||||||
|
<div w-30 b-r b-gray b-op-10 b-r-solid pr-4>
|
||||||
|
<c-button
|
||||||
|
v-for="{ name } of demoRoutes"
|
||||||
|
:key="name"
|
||||||
|
variant="text"
|
||||||
|
:to="{ name }"
|
||||||
|
w-full
|
||||||
|
important:justify-start
|
||||||
|
:type="route.name === name ? 'primary' : 'default'"
|
||||||
|
>
|
||||||
|
{{ name }}
|
||||||
|
</c-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div flex-1 pl-4>
|
||||||
|
<router-view />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { demoRoutes } from './demo.routes';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
25
src/ui/demo/demo.routes.ts
Normal file
25
src/ui/demo/demo.routes.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import type { RouteRecordRaw } from 'vue-router';
|
||||||
|
|
||||||
|
const demoPages = import.meta.glob('../*/*.demo.vue');
|
||||||
|
|
||||||
|
export const demoRoutes = Object.keys(demoPages).map((path) => {
|
||||||
|
const [, , fileName] = path.split('/');
|
||||||
|
const name = fileName.split('.').shift();
|
||||||
|
|
||||||
|
console.log(path);
|
||||||
|
|
||||||
|
return {
|
||||||
|
path: name,
|
||||||
|
name,
|
||||||
|
component: () => import(/* @vite-ignore */ path),
|
||||||
|
} as RouteRecordRaw;
|
||||||
|
});
|
||||||
|
|
||||||
|
export const routes = [
|
||||||
|
{
|
||||||
|
path: '/c-lib',
|
||||||
|
name: 'c-lib',
|
||||||
|
children: demoRoutes,
|
||||||
|
component: () => import('./demo-wrapper.vue'),
|
||||||
|
},
|
||||||
|
];
|
|
@ -3,16 +3,20 @@ import { defineThemes } from './theme.models';
|
||||||
export const { themes: appThemes, useTheme: useAppTheme } = defineThemes({
|
export const { themes: appThemes, useTheme: useAppTheme } = defineThemes({
|
||||||
light: {
|
light: {
|
||||||
text: {
|
text: {
|
||||||
baseColor: 'rgb(51, 54, 57)',
|
baseColor: '#333639',
|
||||||
mutedColor: 'rgba(118, 124, 130)',
|
mutedColor: '#767c82',
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
color: 'rgba(46, 51, 56, 0.05)',
|
||||||
|
colorHover: 'rgba(46, 51, 56, 0.09)',
|
||||||
|
colorPressed: 'rgba(46, 51, 56, 0.22)',
|
||||||
},
|
},
|
||||||
|
|
||||||
primary: {
|
primary: {
|
||||||
color: '#18a058',
|
color: '#18a058',
|
||||||
colorHover: '#1ea54c',
|
colorHover: '#1ea54c',
|
||||||
colorPressed: '#0C7A43',
|
colorPressed: '#0C7A43',
|
||||||
|
colorFaded: '#18a0582f',
|
||||||
},
|
},
|
||||||
|
|
||||||
warning: {
|
warning: {
|
||||||
color: '#f59e0b',
|
color: '#f59e0b',
|
||||||
colorHover: '#f59e0b',
|
colorHover: '#f59e0b',
|
||||||
|
@ -33,14 +37,19 @@ export const { themes: appThemes, useTheme: useAppTheme } = defineThemes({
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
text: {
|
text: {
|
||||||
baseColor: 'rgba(255, 255, 255, 0.82)',
|
baseColor: '#ffffffd1',
|
||||||
mutedColor: 'rgba(255, 255, 255, 0.5)',
|
mutedColor: '#ffffff80',
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
color: 'rgba(255, 255, 255, 0.08)',
|
||||||
|
colorHover: 'rgba(255, 255, 255, 0.12)',
|
||||||
|
colorPressed: 'rgba(255, 255, 255, 0.24)',
|
||||||
},
|
},
|
||||||
|
|
||||||
primary: {
|
primary: {
|
||||||
color: '#1ea54c',
|
color: '#1ea54c',
|
||||||
colorHover: '#36AD6A',
|
colorHover: '#36AD6A',
|
||||||
colorPressed: '#0C7A43',
|
colorPressed: '#0C7A43',
|
||||||
|
colorFaded: '#18a0582f',
|
||||||
},
|
},
|
||||||
warning: {
|
warning: {
|
||||||
color: '#f59e0b',
|
color: '#f59e0b',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue