routie dev init since i didn't adhere to any proper guidance up until now

This commit is contained in:
2026-04-29 22:27:29 -06:00
commit e1dabb71e2
15301 changed files with 3562618 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
@layer vuetify-components {
.v-pie {
display: grid;
align-items: center;
column-gap: 24px;
--v-pie-size: 250px;
}
.v-pie--legend-top {
grid-template-areas: "title" "legend" "content";
grid-template-columns: var(--v-pie-size);
}
.v-pie--legend-bottom {
grid-template-areas: "title" "content" "legend";
grid-template-columns: var(--v-pie-size);
}
.v-pie--legend-right {
grid-template-areas: "title ." "content legend";
}
.v-pie--legend-left {
grid-template-areas: ". title" "legend content";
}
.v-pie--legend-hidden {
grid-template-areas: "title" "content";
}
.v-pie__title {
grid-area: title;
text-align: center;
padding-bottom: 12px;
}
.v-pie__content {
grid-area: content;
position: relative;
width: var(--v-pie-size);
height: var(--v-pie-size);
}
}
@layer vuetify-overrides {
.v-pie__content .v-overlay__scrim,
.v-pie__content .v-overlay__content {
pointer-events: none;
}
}
@layer vuetify-final.trumps {
.v-pie__content {
background: none;
}
}
@layer vuetify-components {
.v-pie__segments {
border-radius: 50%;
}
.v-pie__content-underlay {
border-radius: 50%;
position: absolute;
inset: -8px;
pointer-events: none;
z-index: -1;
}
.v-pie__center-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
}
.v-pie__center-content > div {
pointer-events: auto;
}
.v-pie__legend {
grid-area: legend;
padding-block: 12px;
}
.v-pie__legend .v-avatar {
border: thin solid color-mix(in srgb, rgb(var(--v-theme-on-surface)) 20%, transparent);
}
.v-pie__legend .v-chip__content {
width: 100%;
}
.v-pie__legend .v-chip-group .v-chip:not(.v-chip--selected) {
opacity: 0.4;
}
.v-pie__legend__text {
font-size: 0.8125rem;
white-space: nowrap;
width: 100%;
}
.v-chip--density-compact .v-pie__legend__text {
font-size: 0.66rem;
}
.v-pie .v-chip.v-chip--density-comfortable .v-avatar--start {
margin-inline-start: -6px;
}
.v-pie .v-chip.v-chip--density-default .v-avatar--start {
margin-inline-start: -4px;
}
.v-pie-segment {
pointer-events: none;
position: absolute;
inset: 0;
}
.v-pie-segment .v-pie-segment__overlay {
pointer-events: auto;
opacity: 0;
}
.v-pie__tooltip-content .v-list-item {
padding-inline: 0;
min-width: 100px;
zoom: 0.88;
}
.v-pie__tooltip-content .v-list-item-subtitle {
opacity: 1;
}
.v-pie__tooltip-content .v-avatar {
border: thin solid color-mix(in srgb, rgb(var(--v-theme-on-surface-variant)) 20%, transparent);
}
}
+962
View File
@@ -0,0 +1,962 @@
import type { PropType, TransitionProps } from 'vue';
import type { PieItem, TextTemplate } from './types.js';
export type VPieSlots = {
center: {
total: number;
};
legend: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
};
'legend-text': {
item: PieItem;
total: number;
};
title: never;
tooltip: {
item: PieItem;
total: number;
};
};
export declare const makeVPieProps: <Defaults extends {
density?: unknown;
reveal?: unknown;
innerCut?: unknown;
hoverScale?: unknown;
gap?: unknown;
rounded?: unknown;
animation?: unknown;
hideSlice?: unknown;
title?: unknown;
bgColor?: unknown;
items?: unknown;
palette?: unknown;
itemKey?: unknown;
itemValue?: unknown;
itemTitle?: unknown;
size?: unknown;
rotate?: unknown;
gaugeCut?: unknown;
legend?: unknown;
tooltip?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
density: unknown extends Defaults["density"] ? {
type: PropType<import("../../composables/density.js").Density>;
default: string;
validator: (v: any) => boolean;
} : Omit<{
type: PropType<import("../../composables/density.js").Density>;
default: string;
validator: (v: any) => boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["density"] ? import("../../composables/density.js").Density : Defaults["density"] | import("../../composables/density.js").Density>;
default: unknown extends Defaults["density"] ? import("../../composables/density.js").Density : Defaults["density"] | NonNullable<import("../../composables/density.js").Density>;
};
reveal: unknown extends Defaults["reveal"] ? {
type: PropType<boolean | {
duration?: number;
}>;
default: boolean;
} : Omit<{
type: PropType<boolean | {
duration?: number;
}>;
default: boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["reveal"] ? boolean | {
duration?: number;
} : boolean | {
duration?: number;
} | Defaults["reveal"]>;
default: unknown extends Defaults["reveal"] ? boolean | {
duration?: number;
} : Defaults["reveal"] | NonNullable<boolean | {
duration?: number;
}>;
};
innerCut: unknown extends Defaults["innerCut"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["innerCut"] ? string | number : string | number | Defaults["innerCut"]>;
default: unknown extends Defaults["innerCut"] ? string | number : Defaults["innerCut"] | NonNullable<string | number>;
};
hoverScale: unknown extends Defaults["hoverScale"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["hoverScale"] ? string | number : string | number | Defaults["hoverScale"]>;
default: unknown extends Defaults["hoverScale"] ? string | number : Defaults["hoverScale"] | NonNullable<string | number>;
};
gap: unknown extends Defaults["gap"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["gap"] ? string | number : string | number | Defaults["gap"]>;
default: unknown extends Defaults["gap"] ? string | number : Defaults["gap"] | NonNullable<string | number>;
};
rounded: unknown extends Defaults["rounded"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["rounded"] ? string | number : string | number | Defaults["rounded"]>;
default: unknown extends Defaults["rounded"] ? string | number : Defaults["rounded"] | NonNullable<string | number>;
};
animation: unknown extends Defaults["animation"] ? {
type: PropType<boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
}>;
default: boolean;
} : Omit<{
type: PropType<boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
}>;
default: boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["animation"] ? boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
} : boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
} | Defaults["animation"]>;
default: unknown extends Defaults["animation"] ? boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
} : Defaults["animation"] | NonNullable<boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
}>;
};
hideSlice: unknown extends Defaults["hideSlice"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["hideSlice"] ? boolean : boolean | Defaults["hideSlice"]>;
default: unknown extends Defaults["hideSlice"] ? boolean : boolean | Defaults["hideSlice"];
};
title: unknown extends Defaults["title"] ? StringConstructor : {
type: PropType<unknown extends Defaults["title"] ? string : string | Defaults["title"]>;
default: unknown extends Defaults["title"] ? string : string | Defaults["title"];
};
bgColor: unknown extends Defaults["bgColor"] ? StringConstructor : {
type: PropType<unknown extends Defaults["bgColor"] ? string : string | Defaults["bgColor"]>;
default: unknown extends Defaults["bgColor"] ? string : string | Defaults["bgColor"];
};
items: unknown extends Defaults["items"] ? {
type: PropType<Record<string, any> | {
color?: string;
pattern?: string;
}[]>;
default: () => never[];
} : Omit<{
type: PropType<Record<string, any> | {
color?: string;
pattern?: string;
}[]>;
default: () => never[];
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["items"] ? {
color?: string;
pattern?: string;
}[] | Record<string, any> : {
color?: string;
pattern?: string;
}[] | Record<string, any> | Defaults["items"]>;
default: unknown extends Defaults["items"] ? {
color?: string;
pattern?: string;
}[] | Record<string, any> : Defaults["items"] | NonNullable<{
color?: string;
pattern?: string;
}[] | Record<string, any>>;
};
palette: unknown extends Defaults["palette"] ? {
type: PropType<({
color?: string;
pattern?: string;
} | string)[]>;
default: () => never[];
} : Omit<{
type: PropType<({
color?: string;
pattern?: string;
} | string)[]>;
default: () => never[];
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["palette"] ? (string | {
color?: string;
pattern?: string;
})[] : (string | {
color?: string;
pattern?: string;
})[] | Defaults["palette"]>;
default: unknown extends Defaults["palette"] ? (string | {
color?: string;
pattern?: string;
})[] : (string | {
color?: string;
pattern?: string;
})[] | Defaults["palette"];
};
itemKey: unknown extends Defaults["itemKey"] ? {
type: StringConstructor;
default: string;
} : Omit<{
type: StringConstructor;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["itemKey"] ? string : string | Defaults["itemKey"]>;
default: unknown extends Defaults["itemKey"] ? string : string | Defaults["itemKey"];
};
itemValue: unknown extends Defaults["itemValue"] ? {
type: StringConstructor;
default: string;
} : Omit<{
type: StringConstructor;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["itemValue"] ? string : string | Defaults["itemValue"]>;
default: unknown extends Defaults["itemValue"] ? string : string | Defaults["itemValue"];
};
itemTitle: unknown extends Defaults["itemTitle"] ? {
type: StringConstructor;
default: string;
} : Omit<{
type: StringConstructor;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["itemTitle"] ? string : string | Defaults["itemTitle"]>;
default: unknown extends Defaults["itemTitle"] ? string : string | Defaults["itemTitle"];
};
size: unknown extends Defaults["size"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["size"] ? string | number : string | number | Defaults["size"]>;
default: unknown extends Defaults["size"] ? string | number : Defaults["size"] | NonNullable<string | number>;
};
rotate: unknown extends Defaults["rotate"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["rotate"] ? string | number : string | number | Defaults["rotate"]>;
default: unknown extends Defaults["rotate"] ? string | number : Defaults["rotate"] | NonNullable<string | number>;
};
gaugeCut: unknown extends Defaults["gaugeCut"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["gaugeCut"] ? string | number : string | number | Defaults["gaugeCut"]>;
default: unknown extends Defaults["gaugeCut"] ? string | number : Defaults["gaugeCut"] | NonNullable<string | number>;
};
legend: unknown extends Defaults["legend"] ? {
type: PropType<boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
}>;
default: boolean;
} : Omit<{
type: PropType<boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
}>;
default: boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["legend"] ? boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
} : boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
} | Defaults["legend"]>;
default: unknown extends Defaults["legend"] ? boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
} : Defaults["legend"] | NonNullable<boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
}>;
};
tooltip: unknown extends Defaults["tooltip"] ? {
type: PropType<boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
}>;
default: boolean;
} : Omit<{
type: PropType<boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
}>;
default: boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["tooltip"] ? boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
} : boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
} | Defaults["tooltip"]>;
default: unknown extends Defaults["tooltip"] ? boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
} : Defaults["tooltip"] | NonNullable<boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
}>;
};
};
export declare const VPie: {
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<{
density: import("../../composables/density.js").Density;
reveal: boolean | {
duration?: number;
};
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
};
hideSlice: boolean;
items: {
color?: string;
pattern?: string;
}[] | Record<string, any>;
palette: (string | {
color?: string;
pattern?: string;
})[];
itemKey: string;
itemValue: string;
itemTitle: string;
size: string | number;
legend: boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
};
tooltip: boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
};
} & {
innerCut?: string | number | undefined;
gap?: string | number | undefined;
rounded?: string | number | undefined;
title?: string | undefined;
bgColor?: string | undefined;
rotate?: string | number | undefined;
gaugeCut?: string | number | undefined;
} & {
$children?: {
center?: ((arg: {
total: number;
}) => import("vue").VNodeChild) | undefined;
legend?: ((arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNodeChild) | undefined;
'legend-text'?: ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
title?: (() => import("vue").VNodeChild) | undefined;
tooltip?: ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | {} | import("vue").VNodeChild;
'v-slots'?: {
center?: false | ((arg: {
total: number;
}) => import("vue").VNodeChild) | undefined;
legend?: false | ((arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNodeChild) | undefined;
'legend-text'?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
title?: false | (() => import("vue").VNodeChild) | undefined;
tooltip?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:center"?: false | ((arg: {
total: number;
}) => import("vue").VNodeChild) | undefined;
"v-slot:legend"?: false | ((arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNodeChild) | undefined;
"v-slot:legend-text"?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
"v-slot:title"?: false | (() => import("vue").VNodeChild) | undefined;
"v-slot:tooltip"?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
}, () => JSX.Element, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, {
density: import("../../composables/density.js").Density;
reveal: boolean | {
duration?: number;
};
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
};
hideSlice: boolean;
items: {
color?: string;
pattern?: string;
}[] | Record<string, any>;
palette: (string | {
color?: string;
pattern?: string;
})[];
itemKey: string;
itemValue: string;
itemTitle: string;
size: string | number;
legend: boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
};
tooltip: boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
};
}, true, {}, import("vue").SlotsType<Partial<{
center: (arg: {
total: number;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
legend: (arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
'legend-text': (arg: {
item: PieItem;
total: number;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
title: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
tooltip: (arg: {
item: PieItem;
total: number;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
}>>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
P: {};
B: {};
D: {};
C: {};
M: {};
Defaults: {};
}, {
density: import("../../composables/density.js").Density;
reveal: boolean | {
duration?: number;
};
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
};
hideSlice: boolean;
items: {
color?: string;
pattern?: string;
}[] | Record<string, any>;
palette: (string | {
color?: string;
pattern?: string;
})[];
itemKey: string;
itemValue: string;
itemTitle: string;
size: string | number;
legend: boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
};
tooltip: boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
};
} & {
innerCut?: string | number | undefined;
gap?: string | number | undefined;
rounded?: string | number | undefined;
title?: string | undefined;
bgColor?: string | undefined;
rotate?: string | number | undefined;
gaugeCut?: string | number | undefined;
} & {
$children?: {
center?: ((arg: {
total: number;
}) => import("vue").VNodeChild) | undefined;
legend?: ((arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNodeChild) | undefined;
'legend-text'?: ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
title?: (() => import("vue").VNodeChild) | undefined;
tooltip?: ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | {} | import("vue").VNodeChild;
'v-slots'?: {
center?: false | ((arg: {
total: number;
}) => import("vue").VNodeChild) | undefined;
legend?: false | ((arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNodeChild) | undefined;
'legend-text'?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
title?: false | (() => import("vue").VNodeChild) | undefined;
tooltip?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:center"?: false | ((arg: {
total: number;
}) => import("vue").VNodeChild) | undefined;
"v-slot:legend"?: false | ((arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNodeChild) | undefined;
"v-slot:legend-text"?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
"v-slot:title"?: false | (() => import("vue").VNodeChild) | undefined;
"v-slot:tooltip"?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
}, () => JSX.Element, {}, {}, {}, {
density: import("../../composables/density.js").Density;
reveal: boolean | {
duration?: number;
};
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
};
hideSlice: boolean;
items: {
color?: string;
pattern?: string;
}[] | Record<string, any>;
palette: (string | {
color?: string;
pattern?: string;
})[];
itemKey: string;
itemValue: string;
itemTitle: string;
size: string | number;
legend: boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
};
tooltip: boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
};
}>;
__isFragment?: never;
__isTeleport?: never;
__isSuspense?: never;
} & import("vue").ComponentOptionsBase<{
density: import("../../composables/density.js").Density;
reveal: boolean | {
duration?: number;
};
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
};
hideSlice: boolean;
items: {
color?: string;
pattern?: string;
}[] | Record<string, any>;
palette: (string | {
color?: string;
pattern?: string;
})[];
itemKey: string;
itemValue: string;
itemTitle: string;
size: string | number;
legend: boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
};
tooltip: boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
};
} & {
innerCut?: string | number | undefined;
gap?: string | number | undefined;
rounded?: string | number | undefined;
title?: string | undefined;
bgColor?: string | undefined;
rotate?: string | number | undefined;
gaugeCut?: string | number | undefined;
} & {
$children?: {
center?: ((arg: {
total: number;
}) => import("vue").VNodeChild) | undefined;
legend?: ((arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNodeChild) | undefined;
'legend-text'?: ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
title?: (() => import("vue").VNodeChild) | undefined;
tooltip?: ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | {} | import("vue").VNodeChild;
'v-slots'?: {
center?: false | ((arg: {
total: number;
}) => import("vue").VNodeChild) | undefined;
legend?: false | ((arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNodeChild) | undefined;
'legend-text'?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
title?: false | (() => import("vue").VNodeChild) | undefined;
tooltip?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:center"?: false | ((arg: {
total: number;
}) => import("vue").VNodeChild) | undefined;
"v-slot:legend"?: false | ((arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNodeChild) | undefined;
"v-slot:legend-text"?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
"v-slot:title"?: false | (() => import("vue").VNodeChild) | undefined;
"v-slot:tooltip"?: false | ((arg: {
item: PieItem;
total: number;
}) => import("vue").VNodeChild) | undefined;
}, () => JSX.Element, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, {
density: import("../../composables/density.js").Density;
reveal: boolean | {
duration?: number;
};
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
};
hideSlice: boolean;
items: {
color?: string;
pattern?: string;
}[] | Record<string, any>;
palette: (string | {
color?: string;
pattern?: string;
})[];
itemKey: string;
itemValue: string;
itemTitle: string;
size: string | number;
legend: boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
};
tooltip: boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
};
}, {}, string, import("vue").SlotsType<Partial<{
center: (arg: {
total: number;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
legend: (arg: {
isActive: (item: PieItem) => boolean;
toggle: (item: PieItem) => void;
items: PieItem[];
total: number;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
'legend-text': (arg: {
item: PieItem;
total: number;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
title: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
tooltip: (arg: {
item: PieItem;
total: number;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
}>>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & import("../../util/index.js").FilterPropsOptions<{
density: {
type: PropType<import("../../composables/density.js").Density>;
default: string;
validator: (v: any) => boolean;
};
reveal: {
type: PropType<boolean | {
duration?: number;
}>;
default: boolean;
};
innerCut: (NumberConstructor | StringConstructor)[];
hoverScale: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
gap: (NumberConstructor | StringConstructor)[];
rounded: (NumberConstructor | StringConstructor)[];
animation: {
type: PropType<boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
}>;
default: boolean;
};
hideSlice: BooleanConstructor;
title: StringConstructor;
bgColor: StringConstructor;
items: {
type: PropType<Record<string, any> | {
color?: string;
pattern?: string;
}[]>;
default: () => never[];
};
palette: {
type: PropType<({
color?: string;
pattern?: string;
} | string)[]>;
default: () => never[];
};
itemKey: {
type: StringConstructor;
default: string;
};
itemValue: {
type: StringConstructor;
default: string;
};
itemTitle: {
type: StringConstructor;
default: string;
};
size: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
rotate: (NumberConstructor | StringConstructor)[];
gaugeCut: (NumberConstructor | StringConstructor)[];
legend: {
type: PropType<boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
}>;
default: boolean;
};
tooltip: {
type: PropType<boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
}>;
default: boolean;
};
}, import("vue").ExtractPropTypes<{
density: {
type: PropType<import("../../composables/density.js").Density>;
default: string;
validator: (v: any) => boolean;
};
reveal: {
type: PropType<boolean | {
duration?: number;
}>;
default: boolean;
};
innerCut: (NumberConstructor | StringConstructor)[];
hoverScale: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
gap: (NumberConstructor | StringConstructor)[];
rounded: (NumberConstructor | StringConstructor)[];
animation: {
type: PropType<boolean | {
duration?: number;
easing?: "easeInCubic" | "easeInOutCubic" | "easeInOutQuad" | "easeInOutQuart" | "easeInOutQuint" | "easeInQuad" | "easeInQuart" | "easeInQuint" | "easeOutCubic" | "easeOutQuad" | "easeOutQuart" | "easeOutQuint" | "instant" | "linear";
}>;
default: boolean;
};
hideSlice: BooleanConstructor;
title: StringConstructor;
bgColor: StringConstructor;
items: {
type: PropType<Record<string, any> | {
color?: string;
pattern?: string;
}[]>;
default: () => never[];
};
palette: {
type: PropType<({
color?: string;
pattern?: string;
} | string)[]>;
default: () => never[];
};
itemKey: {
type: StringConstructor;
default: string;
};
itemValue: {
type: StringConstructor;
default: string;
};
itemTitle: {
type: StringConstructor;
default: string;
};
size: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
rotate: (NumberConstructor | StringConstructor)[];
gaugeCut: (NumberConstructor | StringConstructor)[];
legend: {
type: PropType<boolean | {
position?: 'left' | 'top' | 'right' | 'bottom';
textFormat?: TextTemplate;
}>;
default: boolean;
};
tooltip: {
type: PropType<boolean | {
titleFormat?: TextTemplate;
subtitleFormat?: TextTemplate;
avatarSize?: number;
transition?: string | boolean | TransitionProps;
offset?: number;
}>;
default: boolean;
};
}>>;
export type VPie = InstanceType<typeof VPie>;
+333
View File
@@ -0,0 +1,333 @@
import { createElementVNode as _createElementVNode, createVNode as _createVNode, normalizeClass as _normalizeClass, normalizeStyle as _normalizeStyle, mergeProps as _mergeProps, withDirectives as _withDirectives } from "vue";
// Styles
import "./VPie.css";
// Components
import { makeVPieSegmentProps, VPieSegment } from "./VPieSegment.js";
import { VPieTooltip } from "./VPieTooltip.js";
import { VAvatar } from "../../components/VAvatar/index.js";
import { VChip } from "../../components/VChip/index.js";
import { VChipGroup } from "../../components/VChipGroup/index.js";
import { VDefaultsProvider } from "../../components/VDefaultsProvider/index.js"; // Composables
import { useColor } from "../../composables/color.js";
import { makeDensityProps } from "../../composables/density.js"; // Directives
import vClickOutside from "../../directives/click-outside/index.js"; // Utilities
import { computed, shallowRef, toRef, watch } from 'vue';
import { formatTextTemplate } from "./utils.js";
import { convertToUnit, genericComponent, pick, propsFactory } from "../../util/index.js"; // Types
export const makeVPieProps = propsFactory({
title: String,
bgColor: String,
items: {
type: Array,
default: () => []
},
palette: {
type: Array,
default: () => []
},
itemKey: {
type: String,
default: 'key'
},
itemValue: {
type: String,
default: 'value'
},
itemTitle: {
type: String,
default: 'title'
},
size: {
type: [Number, String],
default: 250
},
rotate: [Number, String],
gaugeCut: [Number, String],
legend: {
type: [Boolean, Object],
default: false
},
tooltip: {
type: [Boolean, Object],
default: false
},
...makeDensityProps(),
...pick(makeVPieSegmentProps(), ['animation', 'gap', 'rounded', 'innerCut', 'hoverScale', 'hideSlice', 'reveal'])
}, 'VPie');
export const VPie = genericComponent()({
name: 'VPie',
directives: {
vClickOutside
},
props: makeVPieProps(),
setup(props, {
slots
}) {
const legendConfig = computed(() => ({
visible: !!props.legend,
position: 'bottom',
textFormat: '[title]',
...(typeof props.legend === 'object' ? props.legend : {})
}));
const {
colorClasses,
colorStyles
} = useColor(() => ({
background: props.bgColor
}));
const textColorStyles = toRef(() => pick(colorStyles.value, ['color', 'caretColor']));
const legendAvatarSize = toRef(() => ({
default: 20,
comfortable: 18,
compact: 16
})[props.density ?? 'default']);
const legendDirection = toRef(() => ['left', 'right'].includes(legendConfig.value.position) ? 'vertical' : 'horizontal');
const legendMode = toRef(() => !legendConfig.value.visible ? 'hidden' : legendConfig.value.position);
const legendTextFormatFunction = toRef(() => item => {
return typeof legendConfig.value.textFormat === 'function' ? legendConfig.value.textFormat(item) : formatTextTemplate(legendConfig.value.textFormat, item);
});
const arcs = computed(() => {
// hidden items get (value: 0) to trigger disappearing animation
return props.items.filter(Boolean).map((item, index) => {
return {
key: item[props.itemKey],
color: item.color ?? colorFromPalette(index),
value: item[props.itemValue],
title: String(item[props.itemTitle]),
pattern: item.pattern ?? patternFromPalette(index),
raw: item
};
});
});
const visibleItemsKeys = shallowRef([]);
watch(() => arcs.value.length, () => {
// reset when number of items changes
visibleItemsKeys.value = arcs.value.map(a => a.key);
}, {
immediate: true
});
const visibleItems = computed(() => {
// hidden items get (value: 0) to trigger disappearing animation
return arcs.value.map(item => {
return isVisible(item) ? item : {
...item,
value: 0
};
});
});
const total = computed(() => visibleItems.value.reduce((sum, item) => sum + item.value, 0));
const gaugeCut = toRef(() => Number(props.gaugeCut ?? 0));
const gaugeOffset = computed(() => (1 - Math.cos(Math.PI * Math.min(90, gaugeCut.value / 2) / 180)) / 2);
const rotateDeg = computed(() => `${gaugeCut.value ? 180 + gaugeCut.value / 2 : props.rotate ?? 0}deg`);
function arcOffset(index) {
return visibleItems.value.slice(0, index).reduce((acc, s) => acc + (total.value > 0 ? s.value / total.value : 0) * (360 - gaugeCut.value), 0);
}
function arcSize(v) {
return v / total.value * (100 - gaugeCut.value / 3.6);
}
function colorFromPalette(index) {
if (props.palette.length === 0) return undefined;
const paletteItem = props.palette[index % props.palette.length];
return typeof paletteItem === 'object' ? paletteItem.color : paletteItem;
}
function patternFromPalette(index) {
if (props.palette.length === 0) return undefined;
const paletteItem = props.palette[index % props.palette.length];
return typeof paletteItem === 'object' ? paletteItem.pattern : undefined;
}
function isVisible(item) {
return visibleItemsKeys.value.includes(item.key);
}
function toggle(item) {
if (isVisible(item)) {
visibleItemsKeys.value = visibleItemsKeys.value.filter(x => x !== item.key);
} else {
visibleItemsKeys.value = [...visibleItemsKeys.value, item.key];
}
}
const activeItemKey = shallowRef(null);
const tooltipItem = shallowRef(null);
const tooltipVisible = shallowRef(false);
const tooltipTarget = shallowRef([0, 0]);
let mouseLeaveTimeout = null;
function setItemActive(item, active) {
activeItemKey.value = active ? item.key : null;
if (props.tooltip) {
setTooltip(item, active);
}
}
function setTooltip(item, active) {
clearTimeout(mouseLeaveTimeout);
if (active) {
tooltipVisible.value = true;
tooltipItem.value = item;
} else {
mouseLeaveTimeout = setTimeout(() => {
tooltipVisible.value = false;
// intentionally reusing timeout here
mouseLeaveTimeout = setTimeout(() => {
tooltipItem.value = null;
}, 500);
}, 100);
}
}
let frame = -1;
function onSvgMousemove({
clientX,
clientY
}) {
cancelAnimationFrame(frame);
frame = requestAnimationFrame(() => {
tooltipTarget.value = [clientX, clientY];
});
}
function onSvgTouchstart({
touches
}) {
if (!touches) return;
const {
clientX,
clientY
} = touches[0];
tooltipTarget.value = [clientX, clientY];
}
function onSvgClickOutside() {
activeItemKey.value = null;
tooltipVisible.value = false;
}
return () => {
const segmentProps = pick(props, ['animation', 'gap', 'rounded', 'hideSlice', 'reveal', 'innerCut', 'hoverScale']);
const defaultTooltipTransition = {
name: 'fade-transition',
duration: 150
};
const tooltipProps = {
item: tooltipItem.value,
modelValue: tooltipVisible.value,
titleFormat: typeof props.tooltip === 'object' ? props.tooltip.titleFormat : '[title]',
subtitleFormat: typeof props.tooltip === 'object' ? props.tooltip.subtitleFormat : '[value]',
transition: typeof props.tooltip === 'object' ? props.tooltip.transition : defaultTooltipTransition,
offset: typeof props.tooltip === 'object' ? props.tooltip.offset : 16,
target: tooltipTarget.value
};
const legendDefaults = {
VChipGroup: {
direction: legendDirection.value
},
VChip: {
density: props.density
},
VAvatar: {
size: legendAvatarSize.value
}
};
const tooltipDefaults = {
VAvatar: {
size: typeof props.tooltip === 'object' ? props.tooltip.avatarSize ?? 28 : 28
}
};
const avatarSlot = ({
item
}) => _createVNode(VAvatar, {
"color": item.color,
"start": true
}, {
default: () => [item.pattern && _createElementVNode("svg", {
"height": "40",
"width": "40"
}, [_createElementVNode("rect", {
"width": "40",
"height": "40",
"fill": item.pattern
}, null)])]
});
return _createElementVNode("div", {
"class": _normalizeClass(['v-pie', `v-pie--legend-${legendMode.value}`]),
"style": {
'--v-pie-size': convertToUnit(props.size)
}
}, [slots.title?.() ?? (props.title && _createElementVNode("div", {
"class": "v-pie__title"
}, [props.title])), _createElementVNode("div", {
"class": _normalizeClass(['v-pie__content', colorClasses.value]),
"style": _normalizeStyle([{
transform: `rotate(${rotateDeg.value})`,
marginBottom: `calc(-1 * ${convertToUnit(props.size)} * ${gaugeOffset.value})`
}, textColorStyles.value])
}, [_createElementVNode("div", {
"class": _normalizeClass(['v-pie__content-underlay', colorClasses.value]),
"style": _normalizeStyle(colorStyles.value)
}, null), _withDirectives(_createElementVNode("svg", {
"xmlns": "http://www.w3.org/2000/svg",
"viewBox": "0 0 100 100",
"class": "v-pie__segments",
"onMousemove": onSvgMousemove,
"onTouchstart": onSvgTouchstart
}, [arcs.value.map((item, index) => _createVNode(VPieSegment, _mergeProps(segmentProps, {
"key": item.key,
"active": activeItemKey.value === item.key,
"color": item.color,
"value": isVisible(item) ? arcSize(item.value) : 0,
"rotate": arcOffset(index),
"pattern": item.pattern,
"onUpdate:active": val => setItemActive(item, val),
"onTouchend": () => setItemActive(item, true)
}), null))]), [[vClickOutside, {
handler: onSvgClickOutside
}]]), _createElementVNode("div", {
"class": "v-pie__center-content",
"style": {
transform: `translate(-50%, -50%)
rotate(-${rotateDeg.value})
translateY(calc(-100% * ${gaugeOffset.value}))`
}
}, [_createElementVNode("div", null, [slots.center?.({
total: total.value
})])])]), legendConfig.value.visible && _createVNode(VDefaultsProvider, {
"key": "legend",
"defaults": legendDefaults
}, {
default: () => [_createElementVNode("div", {
"class": "v-pie__legend"
}, [slots.legend?.({
isActive: isVisible,
toggle,
items: arcs.value,
total: total.value
}) ?? _createVNode(VChipGroup, {
"column": true,
"multiple": true,
"modelValue": visibleItemsKeys.value,
"onUpdate:modelValue": $event => visibleItemsKeys.value = $event
}, {
default: () => [arcs.value.map(item => _createVNode(VChip, {
"value": item.key
}, {
prepend: () => avatarSlot({
item
}),
default: () => _createElementVNode("div", {
"class": "v-pie__legend__text"
}, [slots['legend-text']?.({
item,
total: total.value
}) ?? legendTextFormatFunction.value(item)])
}))]
})])]
}), !!props.tooltip && _createVNode(VDefaultsProvider, {
"defaults": tooltipDefaults
}, {
default: () => [_createVNode(VPieTooltip, tooltipProps, {
default: slots.tooltip ? slotProps => slots.tooltip?.({
...slotProps,
total: total.value
}) : undefined,
prepend: avatarSlot
})]
})]);
};
}
});
//# sourceMappingURL=VPie.js.map
File diff suppressed because one or more lines are too long
+112
View File
@@ -0,0 +1,112 @@
@use '../../styles/tools'
@use './variables' as *
@include tools.layer('components')
.v-pie
display: grid
align-items: center
column-gap: 24px
--v-pie-size: 250px
&--legend
&-top
grid-template-areas: 'title' 'legend' 'content'
grid-template-columns: var(--v-pie-size)
&-bottom
grid-template-areas: 'title' 'content' 'legend'
grid-template-columns: var(--v-pie-size)
&-right
grid-template-areas: 'title .' 'content legend'
&-left
grid-template-areas: '. title' 'legend content'
&-hidden
grid-template-areas: 'title' 'content'
&__title
grid-area: title
text-align: center
padding-bottom: $pie-title-padding-bottom
&__content
grid-area: content
position: relative
width: var(--v-pie-size)
height: var(--v-pie-size)
@include tools.layer('overrides')
.v-overlay__scrim,
.v-overlay__content
pointer-events: none
@include tools.layer('trumps')
// expected to get bg-* class for text color
// actual background is applied to underlay
background: none
&__segments
border-radius: 50%
&__content-underlay
border-radius: 50%
position: absolute
inset: $pie-underlay-inset
pointer-events: none
z-index: -1
&__center-content
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%)
pointer-events: none
> div
pointer-events: auto
&__legend
grid-area: legend
padding-block: $pie-legend-padding-block
.v-avatar
border: $pie-legend-avatar-border
.v-chip__content
width: 100%
.v-chip-group .v-chip:not(.v-chip--selected)
opacity: $pie-legend-chip-disabled-opacity
&__text
font-size: $pie-legend-chip-default-font-size
white-space: nowrap
width: 100%
.v-chip--density-compact &
font-size: $pie-legend-chip-compact-font-size
.v-chip.v-chip--density-comfortable .v-avatar--start
margin-inline-start: -6px
.v-chip.v-chip--density-default .v-avatar--start
margin-inline-start: -4px
&-segment
pointer-events: none
position: absolute
inset: 0
.v-pie-segment__overlay
pointer-events: auto
opacity: 0
&__tooltip-content
.v-list-item
padding-inline: 0
min-width: $pie-tooltip-min-width
zoom: 0.88
.v-list-item-subtitle
opacity: 1
.v-avatar
border: $pie-tooltip-avatar-border
+337
View File
@@ -0,0 +1,337 @@
import { easingPatterns } from '../../util/index.js';
import type { PropType } from 'vue';
export declare const makeVPieSegmentProps: <Defaults extends {
reveal?: unknown;
active?: unknown;
rotate?: unknown;
value?: unknown;
color?: unknown;
innerCut?: unknown;
hoverScale?: unknown;
gap?: unknown;
rounded?: unknown;
animation?: unknown;
pattern?: unknown;
hideSlice?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
reveal: unknown extends Defaults["reveal"] ? {
type: PropType<boolean | {
duration?: number;
}>;
default: boolean;
} : Omit<{
type: PropType<boolean | {
duration?: number;
}>;
default: boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["reveal"] ? boolean | {
duration?: number;
} : boolean | {
duration?: number;
} | Defaults["reveal"]>;
default: unknown extends Defaults["reveal"] ? boolean | {
duration?: number;
} : Defaults["reveal"] | NonNullable<boolean | {
duration?: number;
}>;
};
active: unknown extends Defaults["active"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["active"] ? boolean : boolean | Defaults["active"]>;
default: unknown extends Defaults["active"] ? boolean : boolean | Defaults["active"];
};
rotate: unknown extends Defaults["rotate"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["rotate"] ? string | number : string | number | Defaults["rotate"]>;
default: unknown extends Defaults["rotate"] ? string | number : Defaults["rotate"] | NonNullable<string | number>;
};
value: unknown extends Defaults["value"] ? {
type: NumberConstructor;
default: number;
} : Omit<{
type: NumberConstructor;
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["value"] ? number : number | Defaults["value"]>;
default: unknown extends Defaults["value"] ? number : number | Defaults["value"];
};
color: unknown extends Defaults["color"] ? StringConstructor : {
type: PropType<unknown extends Defaults["color"] ? string : string | Defaults["color"]>;
default: unknown extends Defaults["color"] ? string : string | Defaults["color"];
};
innerCut: unknown extends Defaults["innerCut"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["innerCut"] ? string | number : string | number | Defaults["innerCut"]>;
default: unknown extends Defaults["innerCut"] ? string | number : Defaults["innerCut"] | NonNullable<string | number>;
};
hoverScale: unknown extends Defaults["hoverScale"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["hoverScale"] ? string | number : string | number | Defaults["hoverScale"]>;
default: unknown extends Defaults["hoverScale"] ? string | number : Defaults["hoverScale"] | NonNullable<string | number>;
};
gap: unknown extends Defaults["gap"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["gap"] ? string | number : string | number | Defaults["gap"]>;
default: unknown extends Defaults["gap"] ? string | number : Defaults["gap"] | NonNullable<string | number>;
};
rounded: unknown extends Defaults["rounded"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["rounded"] ? string | number : string | number | Defaults["rounded"]>;
default: unknown extends Defaults["rounded"] ? string | number : Defaults["rounded"] | NonNullable<string | number>;
};
animation: unknown extends Defaults["animation"] ? {
type: PropType<boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
}>;
default: boolean;
} : Omit<{
type: PropType<boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
}>;
default: boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["animation"] ? boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
} : boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
} | Defaults["animation"]>;
default: unknown extends Defaults["animation"] ? boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
} : Defaults["animation"] | NonNullable<boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
}>;
};
pattern: unknown extends Defaults["pattern"] ? StringConstructor : {
type: PropType<unknown extends Defaults["pattern"] ? string : string | Defaults["pattern"]>;
default: unknown extends Defaults["pattern"] ? string : string | Defaults["pattern"];
};
hideSlice: unknown extends Defaults["hideSlice"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["hideSlice"] ? boolean : boolean | Defaults["hideSlice"]>;
default: unknown extends Defaults["hideSlice"] ? boolean : boolean | Defaults["hideSlice"];
};
};
export declare const VPieSegment: {
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<{
reveal: boolean | {
duration?: number;
};
active: boolean;
value: number;
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
};
hideSlice: boolean;
} & {
rotate?: string | number | undefined;
color?: string | undefined;
innerCut?: string | number | undefined;
gap?: string | number | undefined;
rounded?: string | number | undefined;
pattern?: string | undefined;
} & {
$children?: {
default?: (() => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
'v-slots'?: {
default?: false | (() => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
} & {
"onUpdate:active"?: ((val: boolean) => any) | undefined;
}, () => JSX.Element, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
'update:active': (val: boolean) => true;
}, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, {
reveal: boolean | {
duration?: number;
};
active: boolean;
value: number;
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
};
hideSlice: boolean;
}, true, {}, import("vue").SlotsType<Partial<{
default: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
}>>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
P: {};
B: {};
D: {};
C: {};
M: {};
Defaults: {};
}, {
reveal: boolean | {
duration?: number;
};
active: boolean;
value: number;
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
};
hideSlice: boolean;
} & {
rotate?: string | number | undefined;
color?: string | undefined;
innerCut?: string | number | undefined;
gap?: string | number | undefined;
rounded?: string | number | undefined;
pattern?: string | undefined;
} & {
$children?: {
default?: (() => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
'v-slots'?: {
default?: false | (() => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
} & {
"onUpdate:active"?: ((val: boolean) => any) | undefined;
}, () => JSX.Element, {}, {}, {}, {
reveal: boolean | {
duration?: number;
};
active: boolean;
value: number;
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
};
hideSlice: boolean;
}>;
__isFragment?: never;
__isTeleport?: never;
__isSuspense?: never;
} & import("vue").ComponentOptionsBase<{
reveal: boolean | {
duration?: number;
};
active: boolean;
value: number;
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
};
hideSlice: boolean;
} & {
rotate?: string | number | undefined;
color?: string | undefined;
innerCut?: string | number | undefined;
gap?: string | number | undefined;
rounded?: string | number | undefined;
pattern?: string | undefined;
} & {
$children?: {
default?: (() => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
'v-slots'?: {
default?: false | (() => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
} & {
"onUpdate:active"?: ((val: boolean) => any) | undefined;
}, () => JSX.Element, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
'update:active': (val: boolean) => true;
}, string, {
reveal: boolean | {
duration?: number;
};
active: boolean;
value: number;
hoverScale: string | number;
animation: boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
};
hideSlice: boolean;
}, {}, string, import("vue").SlotsType<Partial<{
default: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
}>>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & import("../../util/index.js").FilterPropsOptions<{
reveal: {
type: PropType<boolean | {
duration?: number;
}>;
default: boolean;
};
active: BooleanConstructor;
rotate: (NumberConstructor | StringConstructor)[];
value: {
type: NumberConstructor;
default: number;
};
color: StringConstructor;
innerCut: (NumberConstructor | StringConstructor)[];
hoverScale: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
gap: (NumberConstructor | StringConstructor)[];
rounded: (NumberConstructor | StringConstructor)[];
animation: {
type: PropType<boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
}>;
default: boolean;
};
pattern: StringConstructor;
hideSlice: BooleanConstructor;
}, import("vue").ExtractPropTypes<{
reveal: {
type: PropType<boolean | {
duration?: number;
}>;
default: boolean;
};
active: BooleanConstructor;
rotate: (NumberConstructor | StringConstructor)[];
value: {
type: NumberConstructor;
default: number;
};
color: StringConstructor;
innerCut: (NumberConstructor | StringConstructor)[];
hoverScale: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
gap: (NumberConstructor | StringConstructor)[];
rounded: (NumberConstructor | StringConstructor)[];
animation: {
type: PropType<boolean | {
duration?: number;
easing?: keyof typeof easingPatterns;
}>;
default: boolean;
};
pattern: StringConstructor;
hideSlice: BooleanConstructor;
}>>;
export type VPieSegment = InstanceType<typeof VPieSegment>;
+108
View File
@@ -0,0 +1,108 @@
import { createElementVNode as _createElementVNode } from "vue";
// Composables
import { useProxiedModel } from "../../composables/proxiedModel.js";
import { makeRevealProps, useReveal } from "../../composables/reveal.js"; // Utilities
import { computed, toRef } from 'vue';
import { useInnerSlicePath, useOuterSlicePath, usePieArc } from "./utils.js";
import { easingPatterns, genericComponent, propsFactory, useTransition } from "../../util/index.js"; // Types
export const makeVPieSegmentProps = propsFactory({
active: Boolean,
rotate: [Number, String],
value: {
type: Number,
default: 0
},
color: String,
innerCut: [Number, String],
hoverScale: {
type: [Number, String],
default: 0.05
},
gap: [Number, String],
rounded: [Number, String],
animation: {
type: [Boolean, Object],
default: false
},
pattern: String,
hideSlice: Boolean,
...makeRevealProps()
}, 'VPieSegment');
export const VPieSegment = genericComponent()({
name: 'VPieSegment',
props: makeVPieSegmentProps(),
emits: {
'update:active': val => true
},
setup(props) {
const isActive = useProxiedModel(props, 'active');
const {
state: revealState,
duration: revealDuration
} = useReveal(props);
const transitionConfig = computed(() => {
const defaultEasing = 'easeInOutCubic';
const defaultDuration = 400;
const easingName = typeof props.animation === 'object' ? props.animation.easing ?? defaultEasing : defaultEasing;
return {
duration: ['initial', 'pending'].includes(revealState.value) ? revealDuration.value : typeof props.animation === 'object' ? props.animation.duration : props.animation ? defaultDuration : 0,
transition: easingPatterns[easingName]
};
});
const {
hoverZoomRatio,
normalizedValue,
normalizedInnerCut,
outerX,
outerY,
arcWidth
} = usePieArc(props, isActive);
const arcSize = toRef(() => revealState.value === 'initial' ? 0 : normalizedValue.value);
const currentArcSize = useTransition(arcSize, transitionConfig);
const angle = toRef(() => revealState.value === 'initial' ? 0 : Number(props.rotate ?? 0) + Number(props.gap ?? 0) / 2);
const currentAngle = useTransition(angle, transitionConfig);
const arcRadius = toRef(() => 50 * (isActive.value ? 1 : 1 - hoverZoomRatio.value));
const currentArcRadius = useTransition(arcRadius, transitionConfig);
const currentArcWidth = useTransition(arcWidth, transitionConfig);
const outerSlicePath = useOuterSlicePath({
angle: currentAngle,
radius: currentArcRadius,
size: currentArcSize,
width: currentArcWidth,
rounded: () => Number(props.rounded ?? 0)
});
const innerSlicePath = useInnerSlicePath({
angle: currentAngle,
radius: () => currentArcRadius.value - currentArcWidth.value,
size: currentArcSize
});
const overlayPath = toRef(() => `M 50 0 A 50 50 0 ${normalizedValue.value > 50 ? 1 : 0} 1 ${outerX.value} ${outerY.value} L 50 50`);
return () => _createElementVNode("g", {
"class": "v-pie-segment",
"style": {
color: props.color
}
}, [_createElementVNode("path", {
"key": "outer-slice",
"fill": "currentColor",
"shape-rendering": "geometricPrecision",
"d": outerSlicePath.value
}, null), props.pattern && _createElementVNode("path", {
"key": "pattern-overlay",
"shape-rendering": "geometricPrecision",
"fill": props.pattern,
"d": outerSlicePath.value
}, null), !props.hideSlice && normalizedInnerCut.value > 0 && _createElementVNode("path", {
"key": "inner-slice",
"fill": "oklch(from currentColor l c h / calc(alpha / 2))",
"d": innerSlicePath.value
}, null), ['disabled', 'done'].includes(revealState.value) && _createElementVNode("path", {
"transform": `rotate(${currentAngle.value} 50 50)`,
"class": "v-pie-segment__overlay",
"d": overlayPath.value,
"onMouseenter": () => isActive.value = true,
"onMouseleave": () => isActive.value = false
}, null)]);
}
});
//# sourceMappingURL=VPieSegment.js.map
File diff suppressed because one or more lines are too long
+297
View File
@@ -0,0 +1,297 @@
import type { PropType } from 'vue';
import type { PieItem, TextTemplate } from './types.js';
export type VPieTooltipSlots = {
default: {
item: PieItem;
};
prepend: {
item: PieItem;
};
};
export declare const makeVPieTooltipProps: <Defaults extends {
offset?: unknown;
transition?: unknown;
modelValue?: unknown;
target?: unknown;
item?: unknown;
titleFormat?: unknown;
subtitleFormat?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
offset: unknown extends Defaults["offset"] ? {
type: PropType<string | number | number[] | undefined>;
default: NonNullable<string | number | number[] | undefined>;
} : Omit<{
type: PropType<string | number | number[] | undefined>;
default: NonNullable<string | number | number[] | undefined>;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["offset"] ? string | number | number[] | undefined : string | number | number[] | Defaults["offset"] | undefined>;
default: unknown extends Defaults["offset"] ? string | number | number[] | undefined : Defaults["offset"] | NonNullable<string | number | number[] | undefined>;
};
transition: unknown extends Defaults["transition"] ? import("vue").Prop<string | boolean | (import("vue").TransitionProps & {
component?: import("vue").Component;
}) | null> : {
type: PropType<unknown extends Defaults["transition"] ? string | boolean | (import("vue").TransitionProps & {
component?: import("vue").Component;
}) | null : string | boolean | Defaults["transition"] | (import("vue").TransitionProps & {
component?: import("vue").Component;
}) | null>;
default: unknown extends Defaults["transition"] ? string | boolean | (import("vue").TransitionProps & {
component?: import("vue").Component;
}) | null : Defaults["transition"] | NonNullable<string | boolean | (import("vue").TransitionProps & {
component?: import("vue").Component;
}) | null>;
};
modelValue: unknown extends Defaults["modelValue"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["modelValue"] ? boolean : boolean | Defaults["modelValue"]>;
default: unknown extends Defaults["modelValue"] ? boolean : boolean | Defaults["modelValue"];
};
target: unknown extends Defaults["target"] ? PropType<[x: number, y: number]> : {
type: PropType<unknown extends Defaults["target"] ? [x: number, y: number] : [x: number, y: number] | Defaults["target"]>;
default: unknown extends Defaults["target"] ? [x: number, y: number] : [x: number, y: number] | Defaults["target"];
};
item: unknown extends Defaults["item"] ? {
type: PropType<PieItem | null>;
default: null;
} : Omit<{
type: PropType<PieItem | null>;
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["item"] ? PieItem | null : PieItem | Defaults["item"] | null>;
default: unknown extends Defaults["item"] ? PieItem | null : PieItem | Defaults["item"];
};
titleFormat: unknown extends Defaults["titleFormat"] ? {
type: PropType<TextTemplate>;
default: string;
} : Omit<{
type: PropType<TextTemplate>;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["titleFormat"] ? TextTemplate : Defaults["titleFormat"] | TextTemplate>;
default: unknown extends Defaults["titleFormat"] ? TextTemplate : Defaults["titleFormat"] | NonNullable<TextTemplate>;
};
subtitleFormat: unknown extends Defaults["subtitleFormat"] ? {
type: PropType<TextTemplate>;
default: string;
} : Omit<{
type: PropType<TextTemplate>;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["subtitleFormat"] ? TextTemplate : Defaults["subtitleFormat"] | TextTemplate>;
default: unknown extends Defaults["subtitleFormat"] ? TextTemplate : Defaults["subtitleFormat"] | NonNullable<TextTemplate>;
};
};
export declare const VPieTooltip: {
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<{
offset: string | number | number[];
modelValue: boolean;
item: PieItem | null;
titleFormat: TextTemplate;
subtitleFormat: TextTemplate;
} & {
transition?: string | boolean | (import("vue").TransitionProps & {
component?: import("vue").Component;
}) | null | undefined;
target?: [x: number, y: number] | undefined;
} & {
$children?: {
default?: ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
prepend?: ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | import("vue").VNodeChild;
'v-slots'?: {
default?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
prepend?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:default"?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
"v-slot:prepend"?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
}, () => JSX.Element, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, {
offset: string | number | number[] | undefined;
modelValue: boolean;
item: PieItem | null;
titleFormat: TextTemplate;
subtitleFormat: TextTemplate;
}, true, {}, import("vue").SlotsType<Partial<{
default: (arg: {
item: PieItem;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
prepend: (arg: {
item: PieItem;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
}>>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
P: {};
B: {};
D: {};
C: {};
M: {};
Defaults: {};
}, {
offset: string | number | number[];
modelValue: boolean;
item: PieItem | null;
titleFormat: TextTemplate;
subtitleFormat: TextTemplate;
} & {
transition?: string | boolean | (import("vue").TransitionProps & {
component?: import("vue").Component;
}) | null | undefined;
target?: [x: number, y: number] | undefined;
} & {
$children?: {
default?: ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
prepend?: ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | import("vue").VNodeChild;
'v-slots'?: {
default?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
prepend?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:default"?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
"v-slot:prepend"?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
}, () => JSX.Element, {}, {}, {}, {
offset: string | number | number[] | undefined;
modelValue: boolean;
item: PieItem | null;
titleFormat: TextTemplate;
subtitleFormat: TextTemplate;
}>;
__isFragment?: never;
__isTeleport?: never;
__isSuspense?: never;
} & import("vue").ComponentOptionsBase<{
offset: string | number | number[];
modelValue: boolean;
item: PieItem | null;
titleFormat: TextTemplate;
subtitleFormat: TextTemplate;
} & {
transition?: string | boolean | (import("vue").TransitionProps & {
component?: import("vue").Component;
}) | null | undefined;
target?: [x: number, y: number] | undefined;
} & {
$children?: {
default?: ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
prepend?: ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | import("vue").VNodeChild;
'v-slots'?: {
default?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
prepend?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:default"?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
"v-slot:prepend"?: false | ((arg: {
item: PieItem;
}) => import("vue").VNodeChild) | undefined;
}, () => JSX.Element, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, {
offset: string | number | number[] | undefined;
modelValue: boolean;
item: PieItem | null;
titleFormat: TextTemplate;
subtitleFormat: TextTemplate;
}, {}, string, import("vue").SlotsType<Partial<{
default: (arg: {
item: PieItem;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
prepend: (arg: {
item: PieItem;
}) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
}>>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & import("../../util/index.js").FilterPropsOptions<{
offset: {
type: PropType<string | number | number[] | undefined>;
default: NonNullable<string | number | number[] | undefined>;
};
transition: import("vue").Prop<string | boolean | (import("vue").TransitionProps & {
component?: import("vue").Component;
}) | null>;
modelValue: BooleanConstructor;
target: PropType<[x: number, y: number]>;
item: {
type: PropType<PieItem | null>;
default: null;
};
titleFormat: {
type: PropType<TextTemplate>;
default: string;
};
subtitleFormat: {
type: PropType<TextTemplate>;
default: string;
};
}, import("vue").ExtractPropTypes<{
offset: {
type: PropType<string | number | number[] | undefined>;
default: NonNullable<string | number | number[] | undefined>;
};
transition: import("vue").Prop<string | boolean | (import("vue").TransitionProps & {
component?: import("vue").Component;
}) | null>;
modelValue: BooleanConstructor;
target: PropType<[x: number, y: number]>;
item: {
type: PropType<PieItem | null>;
default: null;
};
titleFormat: {
type: PropType<TextTemplate>;
default: string;
};
subtitleFormat: {
type: PropType<TextTemplate>;
default: string;
};
}>>;
export type VPieTooltip = InstanceType<typeof VPieTooltip>;
+65
View File
@@ -0,0 +1,65 @@
import { createVNode as _createVNode } from "vue";
// Components
import { VListItem } from "../../components/VList/VListItem.js";
import { makeVTooltipProps, VTooltip } from "../../components/VTooltip/VTooltip.js"; // Composables
import { makeTransitionProps, MaybeTransition } from "../../composables/transition.js"; // Utilities
import { toRef } from 'vue';
import { formatTextTemplate } from "./utils.js";
import { genericComponent, pick, propsFactory } from "../../util/index.js"; // Types
export const makeVPieTooltipProps = propsFactory({
modelValue: Boolean,
target: Object,
item: {
type: Object,
default: null
},
titleFormat: {
type: [String, Function],
default: '[title]'
},
subtitleFormat: {
type: [String, Function],
default: '[value]'
},
...makeTransitionProps(),
...pick(makeVTooltipProps(), ['offset'])
}, 'VPieTooltip');
export const VPieTooltip = genericComponent()({
name: 'VPieTooltip',
props: makeVPieTooltipProps(),
setup(props, {
slots
}) {
const tooltipTitleFormatFunction = toRef(() => segment => {
return typeof props.titleFormat === 'function' ? props.titleFormat(segment) : formatTextTemplate(props.titleFormat, segment);
});
const tooltipSubtitleFormatFunction = toRef(() => segment => {
return typeof props.subtitleFormat === 'function' ? props.subtitleFormat(segment) : formatTextTemplate(props.subtitleFormat, segment);
});
return () => _createVNode(VTooltip, {
"offset": props.offset,
"modelValue": props.modelValue,
"target": props.target,
"contentClass": "v-pie__tooltip-content"
}, {
default: () => [!!props.item && (slots.default?.({
item: props.item
}) ?? _createVNode(MaybeTransition, {
"transition": props.transition,
"mode": "out-in"
}, {
default: () => [_createVNode(VListItem, {
"key": props.item.key,
"density": "compact",
"title": tooltipTitleFormatFunction.value(props.item),
"subtitle": tooltipSubtitleFormatFunction.value(props.item)
}, {
prepend: slots.prepend ? () => slots.prepend({
item: props.item
}) : undefined
})]
}))]
});
}
});
//# sourceMappingURL=VPieTooltip.js.map
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
@use '../../styles/settings';
@use '../../styles/tools';
$pie-underlay-inset: -8px !default;
$pie-title-padding-bottom: 12px !default;
$pie-legend-padding-block: 12px !default;
$pie-legend-chip-default-font-size: 0.8125rem !default;
$pie-legend-chip-compact-font-size: 0.66rem !default;
$pie-legend-chip-disabled-opacity: .4 !default;
$pie-legend-avatar-border: thin solid tools.theme-color('on-surface', .2) !default;
$pie-tooltip-min-width: 100px !default;
$pie-tooltip-avatar-border: thin solid tools.theme-color('on-surface-variant', .2) !default;
+3
View File
@@ -0,0 +1,3 @@
export { VPie } from './VPie.js';
export { VPieSegment } from './VPieSegment.js';
export { VPieTooltip } from './VPieTooltip.js';
+4
View File
@@ -0,0 +1,4 @@
export { VPie } from "./VPie.js";
export { VPieSegment } from "./VPieSegment.js";
export { VPieTooltip } from "./VPieTooltip.js";
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["VPie","VPieSegment","VPieTooltip"],"sources":["../../../src/labs/VPie/index.ts"],"sourcesContent":["export { VPie } from './VPie'\nexport { VPieSegment } from './VPieSegment'\nexport { VPieTooltip } from './VPieTooltip'\n"],"mappings":"SAASA,IAAI;AAAA,SACJC,WAAW;AAAA,SACXC,WAAW","ignoreList":[]}
+17
View File
@@ -0,0 +1,17 @@
export interface PieItem {
key: string | number | symbol;
color: string;
value: number;
title: string;
pattern?: string;
isActive: boolean;
raw?: Record<string, any>;
}
export interface PieSegmentProps {
gap?: number | string;
hoverScale?: number | string;
innerCut?: number | string;
rounded?: number | string;
value: number;
}
export type TextTemplate = string | ((v: PieItem) => string);
+2
View File
@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=types.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"types.js","names":[],"sources":["../../../src/labs/VPie/types.ts"],"sourcesContent":["export interface PieItem {\n key: string | number | symbol\n color: string\n value: number\n title: string\n pattern?: string\n isActive: boolean\n raw?: Record<string, any>\n}\n\nexport interface PieSegmentProps {\n gap?: number | string\n hoverScale?: number | string\n innerCut?: number | string\n rounded?: number | string\n value: number\n}\n\nexport type TextTemplate = string | ((v: PieItem) => string)\n"],"mappings":"","ignoreList":[]}
+23
View File
@@ -0,0 +1,23 @@
import type { MaybeRefOrGetter, Ref } from 'vue';
import type { PieItem, PieSegmentProps } from './types.js';
export declare function formatTextTemplate(template: string, item?: PieItem): string | undefined;
export declare function usePieArc(props: PieSegmentProps, isHovering: Ref<boolean>): {
hoverZoomRatio: Readonly<Ref<number, number>>;
normalizedValue: Readonly<Ref<number, number>>;
normalizedInnerCut: Readonly<Ref<number, number>>;
outerX: Readonly<Ref<number, number>>;
outerY: Readonly<Ref<number, number>>;
arcWidth: import("vue").ComputedRef<number>;
};
export declare function useOuterSlicePath({ angle, radius, size, width, rounded }: {
angle: MaybeRefOrGetter<number>;
radius: MaybeRefOrGetter<number>;
size: MaybeRefOrGetter<number>;
width: MaybeRefOrGetter<number>;
rounded: MaybeRefOrGetter<number>;
}): import("vue").ComputedRef<string>;
export declare function useInnerSlicePath({ angle, radius, size }: {
angle: MaybeRefOrGetter<number>;
radius: MaybeRefOrGetter<number>;
size: MaybeRefOrGetter<number>;
}): import("vue").ComputedRef<string>;
+47
View File
@@ -0,0 +1,47 @@
// Utilities
import { computed, toRef, toValue } from 'vue';
import { clamp } from "../../util/index.js";
import { roundedArc, simpleArc } from "../../util/svg-arc-corners.js"; // Types
export function formatTextTemplate(template, item) {
return item ? template.replaceAll('[title]', item.title).replaceAll('[value]', String(item.value)) : undefined;
}
export function usePieArc(props, isHovering) {
const hoverZoomRatio = toRef(() => clamp(Number(props.hoverScale ?? 0), 0, 0.25));
const normalizedValue = toRef(() => clamp(props.value - 100 * Number(props.gap ?? 0) / 360, 0.01, 99.99));
const normalizedInnerCut = toRef(() => {
const min = Number(props.rounded ?? 0) > 0 ? 0.2 : 0;
return clamp(Number(props.innerCut ?? 0) / 100, min, 1);
});
const radians = computed(() => (360 * (-normalizedValue.value / 100) + 90) * (Math.PI / 180));
const arcWidth = computed(() => 50 * (1 - normalizedInnerCut.value) * (isHovering.value ? 1 : 1 - hoverZoomRatio.value));
const outerX = toRef(() => 50 + 50 * Math.cos(radians.value));
const outerY = toRef(() => 50 - 50 * Math.sin(radians.value));
return {
hoverZoomRatio,
normalizedValue,
normalizedInnerCut,
outerX,
outerY,
arcWidth
};
}
export function useOuterSlicePath({
angle,
radius,
size,
width,
rounded
}) {
return computed(() => roundedArc([50, 50], toValue(radius), toValue(angle), toValue(angle) + 360 * toValue(size) / 100,
// angle end,
toValue(width), toValue(rounded)));
}
export function useInnerSlicePath({
angle,
radius,
size
}) {
return computed(() => simpleArc([50, 50], toValue(radius), toValue(angle), toValue(angle) + 360 * toValue(size) / 100 // angle end,
));
}
//# sourceMappingURL=utils.js.map
File diff suppressed because one or more lines are too long