@agnos-ui/core
Version:
Framework-agnostic headless component library.
182 lines (181 loc) • 5.76 kB
JavaScript
import { computed, writable, readable } from "@amadeus-it-group/tansu";
import { INVALID_VALUE } from "./types.js";
import { n as createAttributesDirective } from "./dom-gfxqXJpK.js";
import { e as typeString, g as typeFunction, c as typeBoolean, a as typeNumber, k as clamp, l as isNumber } from "./writables-CgpOQ4hA.js";
import { noop } from "./utils/func.js";
import { writablesForProps, bindableProp, stateStores, true$ } from "./utils/stores.js";
import { createWidgetFactory } from "./utils/widget.js";
const defaultConfig = {
rating: 0,
tabindex: 0,
maxRating: 10,
disabled: false,
readonly: false,
resettable: true,
ariaValueTextFn: (rating, maxRating) => `${rating} out of ${maxRating}`,
onHover: noop,
onLeave: noop,
onRatingChange: noop,
className: "",
ariaLabel: "Rating",
ariaLabelledBy: ""
};
function getRatingDefaultConfig() {
return { ...defaultConfig };
}
const configValidator = {
rating: typeNumber,
tabindex: typeNumber,
maxRating: { normalizeValue: (value) => isNumber(value) ? Math.max(0, value) : INVALID_VALUE },
disabled: typeBoolean,
readonly: typeBoolean,
resettable: typeBoolean,
ariaValueTextFn: typeFunction,
onHover: typeFunction,
onLeave: typeFunction,
onRatingChange: typeFunction,
className: typeString,
ariaLabel: typeString,
ariaLabelledBy: typeString
};
const createRating = createWidgetFactory("rating", (config) => {
const [
{
// dirty inputs that need adjustment:
rating$: _dirtyRating$,
tabindex$: _dirtyTabindex$,
ariaValueTextFn$,
onHover$,
onLeave$,
onRatingChange$,
...stateProps
},
patch
] = writablesForProps(defaultConfig, config, configValidator);
const { ariaLabel$, ariaLabelledBy$, className$, disabled$, maxRating$, readonly$, resettable$ } = stateProps;
const tabindex$ = computed(() => disabled$() ? -1 : _dirtyTabindex$());
const rating$ = bindableProp(_dirtyRating$, onRatingChange$, (dirtyRating) => clamp(dirtyRating, maxRating$(), 0));
const _hoveredRating$ = writable(0);
const interactive$ = computed(() => !disabled$() && !readonly$());
const visibleRating$ = computed(() => {
const hoveredRating = _hoveredRating$();
return hoveredRating !== 0 ? hoveredRating : rating$();
});
const ariaValueText$ = computed(() => ariaValueTextFn$()(visibleRating$(), maxRating$()));
const stars$ = computed(() => {
const visibleRating = visibleRating$();
return Array.from({ length: maxRating$() }, (_v, i) => ({
fill: Math.round(Math.max(Math.min(visibleRating - i, 1), 0) * 100),
index: i
}));
});
const widget = {
...stateStores({
ariaValueText$,
interactive$,
rating$,
stars$,
tabindex$,
visibleRating$,
...stateProps
}),
patch,
directives: {
containerDirective: createAttributesDirective(() => ({
events: {
keydown: (event) => {
if (interactive$()) {
const { key } = event;
switch (key) {
case "ArrowLeft":
case "ArrowDown":
rating$.update((rating) => rating - 1);
break;
case "ArrowRight":
case "ArrowUp":
rating$.update((rating) => rating + 1);
break;
case "Home":
case "PageDown":
rating$.set(0);
break;
case "End":
case "PageUp":
rating$.set(maxRating$());
break;
default:
return;
}
event.preventDefault();
event.stopPropagation();
}
},
mouseleave: () => {
if (interactive$()) {
widget.api.leave();
}
}
},
attributes: {
role: readable("slider"),
class: className$,
"aria-valuemin": readable(0),
tabindex: tabindex$,
"aria-valuemax": maxRating$,
"aria-valuenow": visibleRating$,
"aria-valuetext": ariaValueText$,
"aria-readonly": computed(() => readonly$() ? "true" : void 0),
"aria-disabled": computed(() => disabled$() ? "true" : void 0),
"aria-label": ariaLabel$,
"aria-labelledby": computed(() => ariaLabelledBy$() || void 0)
},
classNames: {
"au-rating": true$
}
})),
starDirective: createAttributesDirective((starContext$) => {
return {
events: {
mouseenter: () => {
const index = starContext$().index + 1;
if (interactive$() && index > 0 && index <= maxRating$()) {
_hoveredRating$.set(index);
onHover$()(index);
}
},
click: () => {
const index = starContext$().index + 1;
if (interactive$() && index > 0 && index <= maxRating$()) {
rating$.update((rating) => rating === index && resettable$() ? 0 : index);
}
}
},
styles: {
cursor: computed(() => interactive$() ? "pointer" : "default")
},
classNames: {
"au-rating-star": true$
}
};
})
},
api: {
setRating(index) {
rating$.set(index);
},
setHoveredRating(index) {
onHover$()(index);
_hoveredRating$.set(index);
},
leave() {
onLeave$()(visibleRating$());
_hoveredRating$.set(0);
}
}
};
return widget;
});
export {
createRating as c,
getRatingDefaultConfig as g
};