Tracking de l'application VApp (IHM du jeu)

This commit is contained in:
2025-05-11 18:04:12 +02:00
commit 89e9db9b62
17763 changed files with 3718499 additions and 0 deletions

View File

@ -0,0 +1,54 @@
.v-rating {
max-width: 100%;
display: inline-flex;
white-space: nowrap;
}
.v-rating--readonly {
pointer-events: none;
}
.v-rating__wrapper {
align-items: center;
display: inline-flex;
flex-direction: column;
}
.v-rating__wrapper--bottom {
flex-direction: column-reverse;
}
.v-rating__item {
display: inline-flex;
position: relative;
}
.v-rating__item label {
cursor: pointer;
}
.v-rating__item .v-btn--variant-plain {
opacity: 1;
}
.v-rating__item .v-btn {
transition-property: transform;
}
.v-rating__item .v-btn .v-icon {
transition: inherit;
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
.v-rating--hover .v-rating__item:hover:not(.v-rating__item--focused) .v-btn {
transform: scale(1.25);
}
.v-rating__item--half {
overflow: hidden;
position: absolute;
clip-path: polygon(0 0, 50% 0, 50% 100%, 0 100%);
z-index: 1;
}
.v-rating__item--half .v-btn__overlay, .v-rating__item--half:hover .v-btn__overlay {
opacity: 0;
}
.v-rating__hidden {
height: 0;
opacity: 0;
position: absolute;
width: 0;
}

View File

@ -0,0 +1,210 @@
import { createTextVNode as _createTextVNode, mergeProps as _mergeProps, createVNode as _createVNode, Fragment as _Fragment } from "vue";
// Styles
import "./VRating.css";
// Components
import { VBtn } from "../VBtn/index.mjs"; // Composables
import { makeComponentProps } from "../../composables/component.mjs";
import { makeDensityProps } from "../../composables/density.mjs";
import { IconValue } from "../../composables/icons.mjs";
import { useLocale } from "../../composables/locale.mjs";
import { useProxiedModel } from "../../composables/proxiedModel.mjs";
import { makeSizeProps } from "../../composables/size.mjs";
import { makeTagProps } from "../../composables/tag.mjs";
import { makeThemeProps, provideTheme } from "../../composables/theme.mjs"; // Utilities
import { computed, shallowRef } from 'vue';
import { clamp, createRange, genericComponent, getUid, propsFactory, useRender } from "../../util/index.mjs"; // Types
export const makeVRatingProps = propsFactory({
name: String,
itemAriaLabel: {
type: String,
default: '$vuetify.rating.ariaLabel.item'
},
activeColor: String,
color: String,
clearable: Boolean,
disabled: Boolean,
emptyIcon: {
type: IconValue,
default: '$ratingEmpty'
},
fullIcon: {
type: IconValue,
default: '$ratingFull'
},
halfIncrements: Boolean,
hover: Boolean,
length: {
type: [Number, String],
default: 5
},
readonly: Boolean,
modelValue: {
type: [Number, String],
default: 0
},
itemLabels: Array,
itemLabelPosition: {
type: String,
default: 'top',
validator: v => ['top', 'bottom'].includes(v)
},
ripple: Boolean,
...makeComponentProps(),
...makeDensityProps(),
...makeSizeProps(),
...makeTagProps(),
...makeThemeProps()
}, 'VRating');
export const VRating = genericComponent()({
name: 'VRating',
props: makeVRatingProps(),
emits: {
'update:modelValue': value => true
},
setup(props, _ref) {
let {
slots
} = _ref;
const {
t
} = useLocale();
const {
themeClasses
} = provideTheme(props);
const rating = useProxiedModel(props, 'modelValue');
const normalizedValue = computed(() => clamp(parseFloat(rating.value), 0, +props.length));
const range = computed(() => createRange(Number(props.length), 1));
const increments = computed(() => range.value.flatMap(v => props.halfIncrements ? [v - 0.5, v] : [v]));
const hoverIndex = shallowRef(-1);
const itemState = computed(() => increments.value.map(value => {
const isHovering = props.hover && hoverIndex.value > -1;
const isFilled = normalizedValue.value >= value;
const isHovered = hoverIndex.value >= value;
const isFullIcon = isHovering ? isHovered : isFilled;
const icon = isFullIcon ? props.fullIcon : props.emptyIcon;
const activeColor = props.activeColor ?? props.color;
const color = isFilled || isHovered ? activeColor : props.color;
return {
isFilled,
isHovered,
icon,
color
};
}));
const eventState = computed(() => [0, ...increments.value].map(value => {
function onMouseenter() {
hoverIndex.value = value;
}
function onMouseleave() {
hoverIndex.value = -1;
}
function onClick() {
if (props.disabled || props.readonly) return;
rating.value = normalizedValue.value === value && props.clearable ? 0 : value;
}
return {
onMouseenter: props.hover ? onMouseenter : undefined,
onMouseleave: props.hover ? onMouseleave : undefined,
onClick
};
}));
const name = computed(() => props.name ?? `v-rating-${getUid()}`);
function VRatingItem(_ref2) {
let {
value,
index,
showStar = true
} = _ref2;
const {
onMouseenter,
onMouseleave,
onClick
} = eventState.value[index + 1];
const id = `${name.value}-${String(value).replace('.', '-')}`;
const btnProps = {
color: itemState.value[index]?.color,
density: props.density,
disabled: props.disabled,
icon: itemState.value[index]?.icon,
ripple: props.ripple,
size: props.size,
variant: 'plain'
};
return _createVNode(_Fragment, null, [_createVNode("label", {
"for": id,
"class": {
'v-rating__item--half': props.halfIncrements && value % 1 > 0,
'v-rating__item--full': props.halfIncrements && value % 1 === 0
},
"onMouseenter": onMouseenter,
"onMouseleave": onMouseleave,
"onClick": onClick
}, [_createVNode("span", {
"class": "v-rating__hidden"
}, [t(props.itemAriaLabel, value, props.length)]), !showStar ? undefined : slots.item ? slots.item({
...itemState.value[index],
props: btnProps,
value,
index,
rating: normalizedValue.value
}) : _createVNode(VBtn, _mergeProps({
"aria-label": t(props.itemAriaLabel, value, props.length)
}, btnProps), null)]), _createVNode("input", {
"class": "v-rating__hidden",
"name": name.value,
"id": id,
"type": "radio",
"value": value,
"checked": normalizedValue.value === value,
"tabindex": -1,
"readonly": props.readonly,
"disabled": props.disabled
}, null)]);
}
function createLabel(labelProps) {
if (slots['item-label']) return slots['item-label'](labelProps);
if (labelProps.label) return _createVNode("span", null, [labelProps.label]);
return _createVNode("span", null, [_createTextVNode("\xA0")]);
}
useRender(() => {
const hasLabels = !!props.itemLabels?.length || slots['item-label'];
return _createVNode(props.tag, {
"class": ['v-rating', {
'v-rating--hover': props.hover,
'v-rating--readonly': props.readonly
}, themeClasses.value, props.class],
"style": props.style
}, {
default: () => [_createVNode(VRatingItem, {
"value": 0,
"index": -1,
"showStar": false
}, null), range.value.map((value, i) => _createVNode("div", {
"class": "v-rating__wrapper"
}, [hasLabels && props.itemLabelPosition === 'top' ? createLabel({
value,
index: i,
label: props.itemLabels?.[i]
}) : undefined, _createVNode("div", {
"class": "v-rating__item"
}, [props.halfIncrements ? _createVNode(_Fragment, null, [_createVNode(VRatingItem, {
"value": value - 0.5,
"index": i * 2
}, null), _createVNode(VRatingItem, {
"value": value,
"index": i * 2 + 1
}, null)]) : _createVNode(VRatingItem, {
"value": value,
"index": i
}, null)]), hasLabels && props.itemLabelPosition === 'bottom' ? createLabel({
value,
index: i,
label: props.itemLabels?.[i]
}) : undefined]))]
});
});
return {};
}
});
//# sourceMappingURL=VRating.mjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,57 @@
@use './variables' as *
// Block
.v-rating
max-width: 100%
display: inline-flex
white-space: $rating-white-space
&--readonly
pointer-events: none
// Element
.v-rating__wrapper
align-items: $rating-item-align-items
display: inline-flex
flex-direction: column
&--bottom
flex-direction: column-reverse
.v-rating__item
display: inline-flex
position: relative
label
cursor: pointer
.v-btn--variant-plain
opacity: $rating-item-button-opacity
.v-btn
transition-property: $rating-item-button-transition-property
.v-icon
transition: inherit
transition-timing-function: $rating-item-transition-timing-function
&:hover:not(.v-rating__item--focused)
.v-rating--hover &
.v-btn
transform: $rating-item-icon-transform
&--half
overflow: hidden
position: absolute
clip-path: polygon(0 0, 50% 0, 50% 100%, 0 100%)
z-index: 1
.v-btn__overlay,
&:hover .v-btn__overlay
opacity: 0
.v-rating__hidden
height: 0
opacity: 0
position: absolute
width: 0

View File

@ -0,0 +1,10 @@
@use '../../styles/settings';
// Defaults
$rating-item-focused-button-overlay-opacity: var(--v-hover-opacity) !default;
$rating-item-align-items: center !default;
$rating-item-button-opacity: 1 !default;
$rating-item-button-transition-property: transform !default;
$rating-item-icon-transform: scale(1.25) !default;
$rating-item-transition-timing-function: settings.$decelerated-easing !default;
$rating-white-space: nowrap !default;

View File

@ -0,0 +1,374 @@
import * as vue from 'vue';
import { ComponentPropsOptions, ExtractPropTypes, JSXComponent, PropType, Prop } from 'vue';
interface FilterPropsOptions<PropsOptions extends Readonly<ComponentPropsOptions>, Props = ExtractPropTypes<PropsOptions>> {
filterProps<T extends Partial<Props>, U extends Exclude<keyof Props, Exclude<keyof Props, keyof T>>>(props: T): Partial<Pick<T, U>>;
}
type Density = null | 'default' | 'comfortable' | 'compact';
type IconValue = string | (string | [path: string, opacity: number])[] | JSXComponent;
declare const IconValue: PropType<IconValue>;
type VRatingItemSlot = {
value: number;
index: number;
isFilled: boolean;
isHovered: boolean;
icon: IconValue;
color?: string;
props: Record<string, unknown>;
rating: number;
};
type VRatingItemLabelSlot = {
value: number;
index: number;
label?: string;
};
declare const VRating: {
new (...args: any[]): vue.CreateComponentPublicInstance<{
length: string | number;
style: vue.StyleValue;
disabled: boolean;
size: string | number;
readonly: boolean;
tag: string;
density: Density;
modelValue: string | number;
ripple: boolean;
clearable: boolean;
hover: boolean;
itemAriaLabel: string;
emptyIcon: IconValue;
fullIcon: IconValue;
halfIncrements: boolean;
itemLabelPosition: string;
} & {
name?: string | undefined;
color?: string | undefined;
class?: any;
theme?: string | undefined;
activeColor?: string | undefined;
itemLabels?: string[] | undefined;
} & {
$children?: {} | vue.VNodeChild | {
item?: ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
'item-label'?: ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
};
'v-slots'?: {
item?: false | ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
'item-label'?: false | ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:item"?: false | ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
"v-slot:item-label"?: false | ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
} & {
"onUpdate:modelValue"?: ((value: string | number) => any) | undefined;
}, {}, unknown, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
'update:modelValue': (value: number | string) => boolean;
}, vue.VNodeProps & vue.AllowedComponentProps & vue.ComponentCustomProps & {
length: string | number;
style: vue.StyleValue;
disabled: boolean;
size: string | number;
readonly: boolean;
tag: string;
density: Density;
modelValue: string | number;
ripple: boolean;
clearable: boolean;
hover: boolean;
itemAriaLabel: string;
emptyIcon: IconValue;
fullIcon: IconValue;
halfIncrements: boolean;
itemLabelPosition: string;
} & {
name?: string | undefined;
color?: string | undefined;
class?: any;
theme?: string | undefined;
activeColor?: string | undefined;
itemLabels?: string[] | undefined;
} & {
$children?: {} | vue.VNodeChild | {
item?: ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
'item-label'?: ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
};
'v-slots'?: {
item?: false | ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
'item-label'?: false | ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:item"?: false | ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
"v-slot:item-label"?: false | ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
} & {
"onUpdate:modelValue"?: ((value: string | number) => any) | undefined;
}, {
length: string | number;
style: vue.StyleValue;
disabled: boolean;
size: string | number;
readonly: boolean;
tag: string;
density: Density;
modelValue: string | number;
ripple: boolean;
clearable: boolean;
hover: boolean;
itemAriaLabel: string;
emptyIcon: IconValue;
fullIcon: IconValue;
halfIncrements: boolean;
itemLabelPosition: string;
}, true, {}, vue.SlotsType<Partial<{
item: (arg: VRatingItemSlot) => vue.VNode<vue.RendererNode, vue.RendererElement, {
[key: string]: any;
}>[];
'item-label': (arg: VRatingItemLabelSlot) => vue.VNode<vue.RendererNode, vue.RendererElement, {
[key: string]: any;
}>[];
}>>, {
P: {};
B: {};
D: {};
C: {};
M: {};
Defaults: {};
}, {
length: string | number;
style: vue.StyleValue;
disabled: boolean;
size: string | number;
readonly: boolean;
tag: string;
density: Density;
modelValue: string | number;
ripple: boolean;
clearable: boolean;
hover: boolean;
itemAriaLabel: string;
emptyIcon: IconValue;
fullIcon: IconValue;
halfIncrements: boolean;
itemLabelPosition: string;
} & {
name?: string | undefined;
color?: string | undefined;
class?: any;
theme?: string | undefined;
activeColor?: string | undefined;
itemLabels?: string[] | undefined;
} & {
$children?: {} | vue.VNodeChild | {
item?: ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
'item-label'?: ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
};
'v-slots'?: {
item?: false | ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
'item-label'?: false | ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:item"?: false | ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
"v-slot:item-label"?: false | ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
} & {
"onUpdate:modelValue"?: ((value: string | number) => any) | undefined;
}, {}, {}, {}, {}, {
length: string | number;
style: vue.StyleValue;
disabled: boolean;
size: string | number;
readonly: boolean;
tag: string;
density: Density;
modelValue: string | number;
ripple: boolean;
clearable: boolean;
hover: boolean;
itemAriaLabel: string;
emptyIcon: IconValue;
fullIcon: IconValue;
halfIncrements: boolean;
itemLabelPosition: string;
}>;
__isFragment?: undefined;
__isTeleport?: undefined;
__isSuspense?: undefined;
} & vue.ComponentOptionsBase<{
length: string | number;
style: vue.StyleValue;
disabled: boolean;
size: string | number;
readonly: boolean;
tag: string;
density: Density;
modelValue: string | number;
ripple: boolean;
clearable: boolean;
hover: boolean;
itemAriaLabel: string;
emptyIcon: IconValue;
fullIcon: IconValue;
halfIncrements: boolean;
itemLabelPosition: string;
} & {
name?: string | undefined;
color?: string | undefined;
class?: any;
theme?: string | undefined;
activeColor?: string | undefined;
itemLabels?: string[] | undefined;
} & {
$children?: {} | vue.VNodeChild | {
item?: ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
'item-label'?: ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
};
'v-slots'?: {
item?: false | ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
'item-label'?: false | ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:item"?: false | ((arg: VRatingItemSlot) => vue.VNodeChild) | undefined;
"v-slot:item-label"?: false | ((arg: VRatingItemLabelSlot) => vue.VNodeChild) | undefined;
} & {
"onUpdate:modelValue"?: ((value: string | number) => any) | undefined;
}, {}, unknown, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
'update:modelValue': (value: number | string) => boolean;
}, string, {
length: string | number;
style: vue.StyleValue;
disabled: boolean;
size: string | number;
readonly: boolean;
tag: string;
density: Density;
modelValue: string | number;
ripple: boolean;
clearable: boolean;
hover: boolean;
itemAriaLabel: string;
emptyIcon: IconValue;
fullIcon: IconValue;
halfIncrements: boolean;
itemLabelPosition: string;
}, {}, string, vue.SlotsType<Partial<{
item: (arg: VRatingItemSlot) => vue.VNode<vue.RendererNode, vue.RendererElement, {
[key: string]: any;
}>[];
'item-label': (arg: VRatingItemLabelSlot) => vue.VNode<vue.RendererNode, vue.RendererElement, {
[key: string]: any;
}>[];
}>>> & vue.VNodeProps & vue.AllowedComponentProps & vue.ComponentCustomProps & FilterPropsOptions<{
theme: StringConstructor;
tag: {
type: StringConstructor;
default: string;
};
size: {
type: (StringConstructor | NumberConstructor)[];
default: string;
};
density: {
type: vue.PropType<Density>;
default: string;
validator: (v: any) => boolean;
};
class: vue.PropType<any>;
style: {
type: vue.PropType<vue.StyleValue>;
default: null;
};
name: StringConstructor;
itemAriaLabel: {
type: StringConstructor;
default: string;
};
activeColor: StringConstructor;
color: StringConstructor;
clearable: BooleanConstructor;
disabled: BooleanConstructor;
emptyIcon: {
type: vue.PropType<IconValue>;
default: string;
};
fullIcon: {
type: vue.PropType<IconValue>;
default: string;
};
halfIncrements: BooleanConstructor;
hover: BooleanConstructor;
length: {
type: (StringConstructor | NumberConstructor)[];
default: number;
};
readonly: BooleanConstructor;
modelValue: {
type: (StringConstructor | NumberConstructor)[];
default: number;
};
itemLabels: Prop<string[]>;
itemLabelPosition: {
type: StringConstructor;
default: string;
validator: (v: any) => boolean;
};
ripple: BooleanConstructor;
}, vue.ExtractPropTypes<{
theme: StringConstructor;
tag: {
type: StringConstructor;
default: string;
};
size: {
type: (StringConstructor | NumberConstructor)[];
default: string;
};
density: {
type: vue.PropType<Density>;
default: string;
validator: (v: any) => boolean;
};
class: vue.PropType<any>;
style: {
type: vue.PropType<vue.StyleValue>;
default: null;
};
name: StringConstructor;
itemAriaLabel: {
type: StringConstructor;
default: string;
};
activeColor: StringConstructor;
color: StringConstructor;
clearable: BooleanConstructor;
disabled: BooleanConstructor;
emptyIcon: {
type: vue.PropType<IconValue>;
default: string;
};
fullIcon: {
type: vue.PropType<IconValue>;
default: string;
};
halfIncrements: BooleanConstructor;
hover: BooleanConstructor;
length: {
type: (StringConstructor | NumberConstructor)[];
default: number;
};
readonly: BooleanConstructor;
modelValue: {
type: (StringConstructor | NumberConstructor)[];
default: number;
};
itemLabels: Prop<string[]>;
itemLabelPosition: {
type: StringConstructor;
default: string;
validator: (v: any) => boolean;
};
ripple: BooleanConstructor;
}>>;
type VRating = InstanceType<typeof VRating>;
export { VRating };

View File

@ -0,0 +1,2 @@
export { VRating } from "./VRating.mjs";
//# sourceMappingURL=index.mjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.mjs","names":["VRating"],"sources":["../../../src/components/VRating/index.ts"],"sourcesContent":["export { VRating } from './VRating'\n"],"mappings":"SAASA,OAAO"}