@feugene/granularity 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/config-BTCOJO5z2.js.map +1 -0
- package/dist/chunks/config-B_qi4Fma.js.map +1 -0
- package/dist/chunks/config-Baj7Wvx-.js.map +1 -0
- package/dist/chunks/{config-BKvX0q10.js → config-C5mO5DYZ.js} +10 -1
- package/dist/chunks/config-C5mO5DYZ.js.map +1 -0
- package/dist/chunks/config-CIcynHGr.js +96 -0
- package/dist/chunks/config-CIcynHGr.js.map +1 -0
- package/dist/chunks/{config-BsuDM3Hb.js → config-CKULiuvc.js} +15 -1
- package/dist/chunks/config-CKULiuvc.js.map +1 -0
- package/dist/chunks/{config-jyZq8XKL.js → config-DCwQBMmJ.js} +12 -3
- package/dist/chunks/config-DCwQBMmJ.js.map +1 -0
- package/dist/chunks/config-QaIc_gRa.js.map +1 -0
- package/dist/chunks/config-eXB87DOi.js.map +1 -0
- package/dist/chunks/copy-DChChcq-.js +29 -0
- package/dist/chunks/copy-DChChcq-.js.map +1 -0
- package/dist/chunks/{trending-up-Bf9AQmoq.js → deltaTone-B5OoS1vo.js} +19 -1
- package/dist/chunks/deltaTone-B5OoS1vo.js.map +1 -0
- package/dist/chunks/{en-CwAr3C_x.js → en-DCCFP4qu.js} +12 -2
- package/dist/chunks/{en-CwAr3C_x.js.map → en-DCCFP4qu.js.map} +1 -1
- package/dist/chunks/{es-TR4g2I4A.js → es-CT34HBVM.js} +12 -2
- package/dist/chunks/{es-TR4g2I4A.js.map → es-CT34HBVM.js.map} +1 -1
- package/dist/chunks/{es-Do1q9_SF.js → es-DdJsxlUr.js} +3 -3
- package/dist/chunks/{es-Do1q9_SF.js.map → es-DdJsxlUr.js.map} +1 -1
- package/dist/chunks/{generated-Do60Aq2I.js → generated-CiCrGDQO.js} +49 -0
- package/dist/chunks/{generated-Do60Aq2I.js.map → generated-CiCrGDQO.js.map} +1 -1
- package/dist/chunks/{granular-provider-BW2uopTG.js → granular-provider-CQKhl5C_.js} +10 -8
- package/dist/chunks/granular-provider-CQKhl5C_.js.map +1 -0
- package/dist/chunks/{ru-Bm-zWJ3F.js → ru-CLiAMwrx.js} +12 -2
- package/dist/chunks/{ru-Bm-zWJ3F.js.map → ru-CLiAMwrx.js.map} +1 -1
- package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-CW3zY1ee.js → GrCodeBlock-BmXCLgLS.js} +4 -30
- package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-CW3zY1ee.js.map → GrCodeBlock-BmXCLgLS.js.map} +1 -1
- package/dist/components/GrCodeBlock/index.js +2 -2
- package/dist/components/GrDelta/chunks/{GrDelta-BMmpYz8K.js → GrDelta-DFvxNpmN.js} +0 -0
- package/dist/components/GrDelta/chunks/GrDelta-DFvxNpmN.js.map +1 -0
- package/dist/components/GrDelta/index.js +3 -2
- package/dist/components/GrDescriptionList/chunks/{GrDescriptionList-pXh1LZEe.js → GrDescriptionList-2zFXzX83.js} +15 -4
- package/dist/components/GrDescriptionList/chunks/GrDescriptionList-2zFXzX83.js.map +1 -0
- package/dist/components/GrDescriptionList/index.js +2 -2
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-LOaFSCyd.js → GrDropdownMenu-DyS6dWDp.js} +2 -2
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-LOaFSCyd.js.map → GrDropdownMenu-DyS6dWDp.js.map} +1 -1
- package/dist/components/GrDropdownMenu/index.js +2 -2
- package/dist/components/GrFilePreview/chunks/{GrFilePreview-rbE3zL9w.js → GrFilePreview-D0Bt-0nn.js} +1 -1
- package/dist/components/GrFilePreview/chunks/{GrFilePreview-rbE3zL9w.js.map → GrFilePreview-D0Bt-0nn.js.map} +1 -1
- package/dist/components/GrFilePreview/index.js +2 -2
- package/dist/components/GrJsonViewer/chunks/GrJsonViewer-DFUppRNb.js +389 -0
- package/dist/components/GrJsonViewer/chunks/GrJsonViewer-DFUppRNb.js.map +1 -0
- package/dist/components/GrJsonViewer/index.js +3 -0
- package/dist/components/GrList/chunks/{GrList-BUzFRa8-.js → GrList-BRYhpqIe.js} +3 -3
- package/dist/components/GrList/chunks/GrList-BRYhpqIe.js.map +1 -0
- package/dist/components/GrList/index.js +2 -2
- package/dist/components/GrList/styles.css +1 -1
- package/dist/components/GrRadio/index.js +1 -1
- package/dist/components/GrRadioGroup/index.js +1 -1
- package/dist/components/GrRating/chunks/{GrRating-BiAVT9H7.js → GrRating-BSEtaibx.js} +1 -1
- package/dist/components/GrRating/chunks/{GrRating-BiAVT9H7.js.map → GrRating-BSEtaibx.js.map} +1 -1
- package/dist/components/GrRating/index.js +2 -2
- package/dist/components/GrStatistic/chunks/{GrStatistic-DkzWUAw1.js → GrStatistic-C7wQECeS.js} +20 -4
- package/dist/components/GrStatistic/chunks/GrStatistic-C7wQECeS.js.map +1 -0
- package/dist/components/GrStatistic/index.js +1 -1
- package/dist/components/GrTabPanels/index.js +1 -1
- package/dist/granular-provider-node.js +1 -1
- package/dist/granular-provider.js +1 -1
- package/dist/i18n/all.js +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/index.js +21 -18
- package/dist/theme.js +1 -1
- package/dist/tokens.js +1 -1
- package/dist/types/components/GrDelta/index.d.ts +1 -0
- package/dist/types/components/GrDescriptionList/GrDescriptionList.vue.d.ts +6 -2
- package/dist/types/components/GrDescriptionList/grDescriptionListStyles.d.ts +12 -5
- package/dist/types/components/GrDropdownMenu/GrDropdownMenu.vue.d.ts +1 -1
- package/dist/types/components/GrDropdownMenu/grDropdownMenuStyles.d.ts +10 -1
- package/dist/types/components/GrFilePreview/index.d.ts +1 -0
- package/dist/types/components/GrInput/GrInput.vue.d.ts +1 -1
- package/dist/types/components/GrJsonViewer/GrJsonViewer.vue.d.ts +129 -0
- package/dist/types/components/GrJsonViewer/config.d.ts +1 -0
- package/dist/types/components/GrJsonViewer/defaults.d.ts +23 -0
- package/dist/types/components/GrJsonViewer/grJsonViewerStyles.d.ts +57 -0
- package/dist/types/components/GrJsonViewer/index.d.ts +9 -0
- package/dist/types/components/GrJsonViewer/jsonToNodes.d.ts +47 -0
- package/dist/types/components/GrJsonViewer/safelist.d.ts +1 -0
- package/dist/types/components/GrList/grListStyles.d.ts +13 -0
- package/dist/types/components/GrNumberInput/GrNumberInput.vue.d.ts +1 -1
- package/dist/types/components/GrPromptDialog/GrPromptDialog.vue.d.ts +1 -1
- package/dist/types/components/GrStatistic/GrStatistic.vue.d.ts +12 -2
- package/dist/types/components/GrStatistic/defaults.d.ts +6 -0
- package/dist/types/granular-provider/shared.d.ts +1 -0
- package/dist/types/i18n/messages/en.d.ts +18 -0
- package/dist/types/i18n/messages/es.d.ts +18 -0
- package/dist/types/i18n/messages/ru.d.ts +18 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/internal/granularityFormat.d.ts +26 -0
- package/dist/web-types.json +136 -6
- package/package.json +5 -1
- package/dist/chunks/config-BKvX0q10.js.map +0 -1
- package/dist/chunks/config-BTCOJO5z.js.map +0 -1
- package/dist/chunks/config-B_qi4Fma2.js.map +0 -1
- package/dist/chunks/config-Baj7Wvx-2.js.map +0 -1
- package/dist/chunks/config-BsuDM3Hb.js.map +0 -1
- package/dist/chunks/config-QaIc_gRa2.js.map +0 -1
- package/dist/chunks/config-eXB87DOi2.js.map +0 -1
- package/dist/chunks/config-jyZq8XKL.js.map +0 -1
- package/dist/chunks/granular-provider-BW2uopTG.js.map +0 -1
- package/dist/chunks/trending-up-Bf9AQmoq.js.map +0 -1
- package/dist/components/GrDelta/chunks/GrDelta-BMmpYz8K.js.map +0 -1
- package/dist/components/GrDescriptionList/chunks/GrDescriptionList-pXh1LZEe.js.map +0 -1
- package/dist/components/GrList/chunks/GrList-BUzFRa8-.js.map +0 -1
- package/dist/components/GrStatistic/chunks/GrStatistic-DkzWUAw1.js.map +0 -1
- /package/dist/chunks/{config-BTCOJO5z.js → config-BTCOJO5z2.js} +0 -0
- /package/dist/chunks/{config-B_qi4Fma2.js → config-B_qi4Fma.js} +0 -0
- /package/dist/chunks/{config-Baj7Wvx-2.js → config-Baj7Wvx-.js} +0 -0
- /package/dist/chunks/{config-QaIc_gRa2.js → config-QaIc_gRa.js} +0 -0
- /package/dist/chunks/{config-eXB87DOi2.js → config-eXB87DOi.js} +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { t as GrRadio_default } from "./chunks/GrRadio-BdhknbO8.js";
|
|
2
|
-
import { n as grRadioSafelist, t as grRadioConfig } from "../../chunks/config-
|
|
2
|
+
import { n as grRadioSafelist, t as grRadioConfig } from "../../chunks/config-BTCOJO5z2.js";
|
|
3
3
|
export { GrRadio_default as GrRadio, GrRadio_default as default, grRadioConfig, grRadioSafelist };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { t as GrRadioGroup_default } from "./chunks/GrRadioGroup-BVmjKXcv.js";
|
|
2
|
-
import { t as grRadioGroupConfig } from "../../chunks/config-
|
|
2
|
+
import { t as grRadioGroupConfig } from "../../chunks/config-QaIc_gRa.js";
|
|
3
3
|
export { GrRadioGroup_default as GrRadioGroup, GrRadioGroup_default as default, grRadioGroupConfig };
|
|
@@ -3,7 +3,7 @@ import { n as useGranularityTranslations } from "../../../chunks/granularityI18n
|
|
|
3
3
|
import { n as useGrFormFieldContext } from "../../../chunks/context-DdNIxa1w.js";
|
|
4
4
|
import { useGrFormControl } from "../../../composables/useGrFormControl.js";
|
|
5
5
|
import { n as iconTag, t as iconClass } from "../../../chunks/icon-Dag2tIMs.js";
|
|
6
|
-
import { a as ratingSymbolClass, i as ratingRootClass, o as ratingTextSizeBySize, r as ratingFillClassByTone, s as ratingVoidClass } from "../../../chunks/config-Baj7Wvx
|
|
6
|
+
import { a as ratingSymbolClass, i as ratingRootClass, o as ratingTextSizeBySize, r as ratingFillClassByTone, s as ratingVoidClass } from "../../../chunks/config-Baj7Wvx-.js";
|
|
7
7
|
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref } from "vue";
|
|
8
8
|
//#region src/components/GrRating/GrRating.vue?vue&type=script&setup=true&lang.ts
|
|
9
9
|
var _hoisted_1 = ["name", "value"];
|
package/dist/components/GrRating/chunks/{GrRating-BiAVT9H7.js.map → GrRating-BSEtaibx.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrRating-BiAVT9H7.js","names":["$slots"],"sources":["../../../../src/components/GrRating/GrRating.vue","../../../../src/components/GrRating/GrRating.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, type Component } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { iconClass, iconTag } from '../shared/icon'\n\nimport {\n ratingFillClassByTone,\n ratingRootClass,\n ratingSymbolClass,\n ratingTextSizeBySize,\n ratingVoidClass,\n type GrRatingSize,\n type GrRatingTone,\n} from './grRatingStyles'\n\nexport type {\n GrRatingSize,\n GrRatingTone,\n} from './grRatingStyles'\n\n/**\n * Публичный GR-примитив «Rating» — шкала оценки символами (по умолчанию звёзды).\n *\n * Интерактивный режим реализует WAI-ARIA slider pattern (`role=\"slider\"`,\n * `aria-valuemin/max/now/valuetext`, стрелки / Home / End), режим только для\n * чтения — `role=\"img\"` с текстовой подписью, чтобы скринридер озвучил оценку\n * одной фразой, а не набором элементов.\n *\n * Символ по умолчанию рисуется инлайновым SVG (звезда с `fill=\"currentColor\"`) —\n * иконочные шрифты-маски `i-lucide-star` дают только контур. Свой символ\n * задаётся пропом `icon` (Vue-компонент или класс иконки) либо слотом `#symbol`.\n */\nexport interface GrRatingProps {\n /** Текущая оценка. Дробная (`3.5`) поддерживается при `allowHalf`. */\n modelValue: number\n /** Количество символов шкалы. */\n max?: number\n size?: GrRatingSize\n /** Тон заливки; точечно перекрывается переменной `--gr-rating-color`. */\n tone?: GrRatingTone\n /** Половинчатые оценки: клик по левой половине символа даёт `.5`. */\n allowHalf?: boolean\n /** Только показ: без ввода и фокуса. */\n readonly?: boolean\n disabled?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n /** Обязательное поле (`aria-required`). */\n required?: boolean\n /** Повторный клик по текущей оценке сбрасывает её в `0`. */\n clearable?: boolean\n /**\n * Символ вместо встроенной звезды: Vue-компонент либо класс иконки вашей\n * UnoCSS-сборки (`'i-lucide-heart'` — тогда нужен ваш `presetIcons`,\n * см. `docs/installation.md`).\n */\n icon?: string | Component\n /** Показывать числовую подпись справа от шкалы. */\n showText?: boolean\n /** Формат подписи. По умолчанию — само значение. Сильнее `texts`. */\n formatText?: (value: number) => string\n /**\n * Подписи по делениям: «3 из 5, нормально» вместо «3 из 5». Уходят и в\n * видимый текст, и в `aria-valuetext` — ради этого рейтинг и существует.\n * Массив короче `max` оставляет верхние деления без подписи.\n */\n texts?: string[]\n /**\n * Компактный вид: рисуются только заполненные символы. Осмысленно вместе с\n * `readonly` — в списках и таблицах пять звёзд в каждой строке съедают ширину.\n */\n compact?: boolean\n ariaLabel?: string\n /** Имя для нативной формы: hidden input со значением; `0` — «не выбрано», input не рендерится. */\n name?: string\n}\n\nexport interface GrRatingEmits {\n (e: 'update:modelValue', value: number): void\n /** Оценка зафиксирована (клик / клавиша). */\n (e: 'change', value: number): void\n /** Значение под курсором; `null` — курсор ушёл со шкалы. */\n (e: 'hoverChange', value: number | null): void\n /** Оценка снята повторным кликом; только при `clearable`. */\n (e: 'clear'): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(\n defineProps<GrRatingProps>(),\n {\n max: 5,\n size: undefined,\n tone: 'warning',\n allowHalf: false,\n readonly: false,\n disabled: false,\n invalid: false,\n required: false,\n clearable: false,\n icon: undefined,\n showText: false,\n formatText: undefined,\n texts: undefined,\n compact: false,\n ariaLabel: undefined,\n name: undefined,\n },\n)\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentSize(() => props.size, {\n component: 'GrRating',\n supported: ['xs', 'sm', 'md', 'lg'],\n})\n\nconst emit = defineEmits<GrRatingEmits>()\ndefineSlots<{\n /** Свой символ вместо звезды. `filled` — закрашенная половина символа. */\n symbol?: (props: { index: number, filled: boolean }) => any\n /** Подпись рядом с оценкой. */\n text?: (props: { value: number }) => any\n}>()\n\n\nconst { t } = useGranularityTranslations()\n\n// Контекст `GrFormField`: id/aria-describedby/invalid/required как fallback.\nconst field = useGrFormFieldContext()\nconst resolvedId = computed(() => field?.id.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid, required: isRequired, readonly: isReadonly } = useGrFormControl(() => props)\nconst describedBy = computed(() => field?.describedById.value)\n\nconst rootEl = ref<HTMLElement | null>(null)\n\nfunction focus(): void {\n rootEl.value?.querySelector<HTMLElement>('[data-gr-rating-scale]')?.focus()\n}\n\nfunction blur(): void {\n rootEl.value?.querySelector<HTMLElement>('[data-gr-rating-scale]')?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n/** Ввод возможен: не readonly и не disabled. */\nconst interactive = computed(() => !isReadonly.value && !isDisabled.value)\n\n/**\n * `aria-readonly`, `aria-invalid` и `aria-required` вешаются только в\n * slider-режиме: на `role=\"img\"` они не разрешены и дают critical в axe.\n *\n * Роль контрола (`slider`) сохраняется и в `disabled` — отключённый слайдер это\n * штатный ARIA-паттерн. А вот `readonly` — это уже не контрол, а картинка с\n * подписью: на `role=\"img\"` атрибуты `aria-value*`/`aria-disabled` запрещены\n * (axe: `aria-allowed-attr`), поэтому там их не выводим вовсе.\n */\nconst asSlider = computed(() => !props.readonly)\nconst step = computed(() => (props.allowHalf ? 0.5 : 1))\n\n// Значение под курсором имеет приоритет над моделью — это «предпросмотр» оценки.\nconst hoverValue = ref<number | null>(null)\nconst displayValue = computed(() => hoverValue.value ?? clamp(props.modelValue))\n\nfunction clamp(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.min(props.max, Math.max(0, value))\n}\n\n/** Доля заливки символа с индексом `index` (0..1). */\nfunction fillRatio(index: number): number {\n return Math.min(1, Math.max(0, displayValue.value - index))\n}\n\nconst symbols = computed(() => {\n // Компактный вид показывает только заполненную часть шкалы; половинка\n // считается символом — иначе «2.5» потеряло бы половину звезды.\n const length = props.compact ? Math.ceil(clamp(props.modelValue)) : props.max\n return Array.from({ length }, (_, index) => index)\n})\n\n/** Подпись деления под текущим значением: половинки округляются вверх. */\nconst currentLabel = computed(() => {\n if (!props.texts?.length || displayValue.value <= 0) return undefined\n return props.texts[Math.ceil(displayValue.value) - 1]\n})\n\nconst valueText = computed(() => {\n const params = { value: displayValue.value, max: props.max }\n\n // Порядок слов задаёт локаль, а не конкатенация в коде.\n return currentLabel.value\n ? t('gr.rating.valueTextWithLabel', '{value} of {max}, {label}', { ...params, label: currentLabel.value })\n : t('gr.rating.valueText', '{value} of {max}', params)\n})\n\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.rating.label', 'Rating'))\n\nconst text = computed(() => {\n if (props.formatText) return props.formatText(displayValue.value)\n return currentLabel.value ?? String(displayValue.value)\n})\n\n/** Значение, соответствующее позиции курсора внутри символа `index`. */\nfunction valueAt(index: number, event: MouseEvent): number {\n if (!props.allowHalf) return index + 1\n const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()\n return rect.width > 0 && event.clientX - rect.left < rect.width / 2 ? index + 0.5 : index + 1\n}\n\nfunction onScaleBlur(event: FocusEvent): void {\n resetHover()\n emit('blur', event)\n}\n\nfunction commit(value: number): void {\n const next = clamp(value)\n if (next !== props.modelValue) emit('update:modelValue', next)\n emit('change', next)\n}\n\nfunction onSymbolClick(index: number, event: MouseEvent): void {\n if (!interactive.value) return\n const next = valueAt(index, event)\n const cleared = props.clearable && next === props.modelValue\n\n commit(cleared ? 0 : next)\n if (cleared) emit('clear')\n}\n\nfunction onSymbolMouseMove(index: number, event: MouseEvent): void {\n if (!interactive.value) {\n // Режим сменился под курсором — оставлять подсветку от прошлого состояния нельзя.\n resetHover()\n return\n }\n const next = valueAt(index, event)\n if (next === hoverValue.value) return\n hoverValue.value = next\n emit('hoverChange', next)\n}\n\nfunction resetHover(): void {\n if (hoverValue.value === null) return\n hoverValue.value = null\n emit('hoverChange', null)\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (!interactive.value) return\n const current = clamp(props.modelValue)\n let next: number | null = null\n\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = current + step.value\n break\n case 'ArrowLeft':\n case 'ArrowDown':\n next = current - step.value\n break\n case 'Home':\n next = 0\n break\n case 'End':\n next = props.max\n break\n default:\n return\n }\n\n event.preventDefault()\n commit(next)\n}\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n data-gr-rating\n class=\"inline-flex items-center gap-2\"\n >\n <!-- Нативная форма: роль-виджет не labelable и в submit не попадает. -->\n <input\n v-if=\"name && modelValue > 0\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"String(modelValue)\"\n >\n <div\n :id=\"resolvedId\"\n data-gr-rating-scale\n data-testid=\"gr-rating-scale\"\n :class=\"ratingRootClass({ size: resolvedSize, disabled, interactive })\"\n :role=\"asSlider ? 'slider' : 'img'\"\n :tabindex=\"asSlider ? (disabled ? -1 : 0) : undefined\"\n :aria-label=\"asSlider ? resolvedAriaLabel : `${resolvedAriaLabel}: ${valueText}`\"\n :aria-valuemin=\"asSlider ? 0 : undefined\"\n :aria-valuemax=\"asSlider ? max : undefined\"\n :aria-valuenow=\"asSlider ? displayValue : undefined\"\n :aria-valuetext=\"asSlider ? valueText : undefined\"\n :aria-orientation=\"asSlider ? 'horizontal' : undefined\"\n :aria-disabled=\"asSlider && disabled ? 'true' : undefined\"\n :aria-invalid=\"asSlider && isInvalid ? 'true' : undefined\"\n :aria-describedby=\"asSlider ? describedBy : undefined\"\n :aria-required=\"asSlider && isRequired ? 'true' : undefined\"\n :aria-readonly=\"asSlider && isReadonly ? 'true' : undefined\"\n @keydown=\"onKeydown\"\n @mouseleave=\"resetHover\"\n @focus=\"emit('focus', $event)\"\n @blur=\"onScaleBlur\"\n >\n <span\n v-for=\"index in symbols\"\n :key=\"index\"\n data-gr-rating-symbol\n :data-testid=\"`gr-rating-symbol-${index}`\"\n :class=\"ratingSymbolClass(resolvedSize)\"\n @click=\"onSymbolClick(index, $event)\"\n @mousemove=\"onSymbolMouseMove(index, $event)\"\n >\n <!-- Нижний слой — «пустой» символ, поверх него обрезанный по ширине «залитый». -->\n <span class=\"block h-full w-full\" :class=\"ratingVoidClass\" aria-hidden=\"true\">\n <slot name=\"symbol\" :index=\"index\" :filled=\"false\">\n <component :is=\"iconTag(icon)\" v-if=\"icon\" class=\"block h-full w-full\" :class=\"iconClass(icon)\" />\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"block h-full w-full\">\n <path d=\"M12 2.5l2.9 6.1 6.6.9-4.8 4.7 1.2 6.6L12 17.7 6.1 20.8l1.2-6.6L2.5 9.5l6.6-.9z\" />\n </svg>\n </slot>\n </span>\n\n <span\n data-gr-rating-fill\n class=\"pointer-events-none absolute inset-y-0 left-0 overflow-hidden\"\n :class=\"ratingFillClassByTone[tone]\"\n :style=\"{ width: `${fillRatio(index) * 100}%` }\"\n aria-hidden=\"true\"\n >\n <span :class=\"ratingSymbolClass(resolvedSize)\">\n <slot name=\"symbol\" :index=\"index\" :filled=\"true\">\n <component :is=\"iconTag(icon)\" v-if=\"icon\" class=\"block h-full w-full\" :class=\"iconClass(icon)\" />\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"block h-full w-full\">\n <path d=\"M12 2.5l2.9 6.1 6.6.9-4.8 4.7 1.2 6.6L12 17.7 6.1 20.8l1.2-6.6L2.5 9.5l6.6-.9z\" />\n </svg>\n </slot>\n </span>\n </span>\n </span>\n </div>\n\n <span\n v-if=\"showText || $slots.text\"\n data-gr-rating-text\n class=\"text-[var(--gr-muted-fg)] tabular-nums\"\n :class=\"ratingTextSizeBySize[resolvedSize]\"\n >\n <slot name=\"text\" :value=\"displayValue\">{{ text }}</slot>\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, type Component } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { iconClass, iconTag } from '../shared/icon'\n\nimport {\n ratingFillClassByTone,\n ratingRootClass,\n ratingSymbolClass,\n ratingTextSizeBySize,\n ratingVoidClass,\n type GrRatingSize,\n type GrRatingTone,\n} from './grRatingStyles'\n\nexport type {\n GrRatingSize,\n GrRatingTone,\n} from './grRatingStyles'\n\n/**\n * Публичный GR-примитив «Rating» — шкала оценки символами (по умолчанию звёзды).\n *\n * Интерактивный режим реализует WAI-ARIA slider pattern (`role=\"slider\"`,\n * `aria-valuemin/max/now/valuetext`, стрелки / Home / End), режим только для\n * чтения — `role=\"img\"` с текстовой подписью, чтобы скринридер озвучил оценку\n * одной фразой, а не набором элементов.\n *\n * Символ по умолчанию рисуется инлайновым SVG (звезда с `fill=\"currentColor\"`) —\n * иконочные шрифты-маски `i-lucide-star` дают только контур. Свой символ\n * задаётся пропом `icon` (Vue-компонент или класс иконки) либо слотом `#symbol`.\n */\nexport interface GrRatingProps {\n /** Текущая оценка. Дробная (`3.5`) поддерживается при `allowHalf`. */\n modelValue: number\n /** Количество символов шкалы. */\n max?: number\n size?: GrRatingSize\n /** Тон заливки; точечно перекрывается переменной `--gr-rating-color`. */\n tone?: GrRatingTone\n /** Половинчатые оценки: клик по левой половине символа даёт `.5`. */\n allowHalf?: boolean\n /** Только показ: без ввода и фокуса. */\n readonly?: boolean\n disabled?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n /** Обязательное поле (`aria-required`). */\n required?: boolean\n /** Повторный клик по текущей оценке сбрасывает её в `0`. */\n clearable?: boolean\n /**\n * Символ вместо встроенной звезды: Vue-компонент либо класс иконки вашей\n * UnoCSS-сборки (`'i-lucide-heart'` — тогда нужен ваш `presetIcons`,\n * см. `docs/installation.md`).\n */\n icon?: string | Component\n /** Показывать числовую подпись справа от шкалы. */\n showText?: boolean\n /** Формат подписи. По умолчанию — само значение. Сильнее `texts`. */\n formatText?: (value: number) => string\n /**\n * Подписи по делениям: «3 из 5, нормально» вместо «3 из 5». Уходят и в\n * видимый текст, и в `aria-valuetext` — ради этого рейтинг и существует.\n * Массив короче `max` оставляет верхние деления без подписи.\n */\n texts?: string[]\n /**\n * Компактный вид: рисуются только заполненные символы. Осмысленно вместе с\n * `readonly` — в списках и таблицах пять звёзд в каждой строке съедают ширину.\n */\n compact?: boolean\n ariaLabel?: string\n /** Имя для нативной формы: hidden input со значением; `0` — «не выбрано», input не рендерится. */\n name?: string\n}\n\nexport interface GrRatingEmits {\n (e: 'update:modelValue', value: number): void\n /** Оценка зафиксирована (клик / клавиша). */\n (e: 'change', value: number): void\n /** Значение под курсором; `null` — курсор ушёл со шкалы. */\n (e: 'hoverChange', value: number | null): void\n /** Оценка снята повторным кликом; только при `clearable`. */\n (e: 'clear'): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(\n defineProps<GrRatingProps>(),\n {\n max: 5,\n size: undefined,\n tone: 'warning',\n allowHalf: false,\n readonly: false,\n disabled: false,\n invalid: false,\n required: false,\n clearable: false,\n icon: undefined,\n showText: false,\n formatText: undefined,\n texts: undefined,\n compact: false,\n ariaLabel: undefined,\n name: undefined,\n },\n)\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentSize(() => props.size, {\n component: 'GrRating',\n supported: ['xs', 'sm', 'md', 'lg'],\n})\n\nconst emit = defineEmits<GrRatingEmits>()\ndefineSlots<{\n /** Свой символ вместо звезды. `filled` — закрашенная половина символа. */\n symbol?: (props: { index: number, filled: boolean }) => any\n /** Подпись рядом с оценкой. */\n text?: (props: { value: number }) => any\n}>()\n\n\nconst { t } = useGranularityTranslations()\n\n// Контекст `GrFormField`: id/aria-describedby/invalid/required как fallback.\nconst field = useGrFormFieldContext()\nconst resolvedId = computed(() => field?.id.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid, required: isRequired, readonly: isReadonly } = useGrFormControl(() => props)\nconst describedBy = computed(() => field?.describedById.value)\n\nconst rootEl = ref<HTMLElement | null>(null)\n\nfunction focus(): void {\n rootEl.value?.querySelector<HTMLElement>('[data-gr-rating-scale]')?.focus()\n}\n\nfunction blur(): void {\n rootEl.value?.querySelector<HTMLElement>('[data-gr-rating-scale]')?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n/** Ввод возможен: не readonly и не disabled. */\nconst interactive = computed(() => !isReadonly.value && !isDisabled.value)\n\n/**\n * `aria-readonly`, `aria-invalid` и `aria-required` вешаются только в\n * slider-режиме: на `role=\"img\"` они не разрешены и дают critical в axe.\n *\n * Роль контрола (`slider`) сохраняется и в `disabled` — отключённый слайдер это\n * штатный ARIA-паттерн. А вот `readonly` — это уже не контрол, а картинка с\n * подписью: на `role=\"img\"` атрибуты `aria-value*`/`aria-disabled` запрещены\n * (axe: `aria-allowed-attr`), поэтому там их не выводим вовсе.\n */\nconst asSlider = computed(() => !props.readonly)\nconst step = computed(() => (props.allowHalf ? 0.5 : 1))\n\n// Значение под курсором имеет приоритет над моделью — это «предпросмотр» оценки.\nconst hoverValue = ref<number | null>(null)\nconst displayValue = computed(() => hoverValue.value ?? clamp(props.modelValue))\n\nfunction clamp(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.min(props.max, Math.max(0, value))\n}\n\n/** Доля заливки символа с индексом `index` (0..1). */\nfunction fillRatio(index: number): number {\n return Math.min(1, Math.max(0, displayValue.value - index))\n}\n\nconst symbols = computed(() => {\n // Компактный вид показывает только заполненную часть шкалы; половинка\n // считается символом — иначе «2.5» потеряло бы половину звезды.\n const length = props.compact ? Math.ceil(clamp(props.modelValue)) : props.max\n return Array.from({ length }, (_, index) => index)\n})\n\n/** Подпись деления под текущим значением: половинки округляются вверх. */\nconst currentLabel = computed(() => {\n if (!props.texts?.length || displayValue.value <= 0) return undefined\n return props.texts[Math.ceil(displayValue.value) - 1]\n})\n\nconst valueText = computed(() => {\n const params = { value: displayValue.value, max: props.max }\n\n // Порядок слов задаёт локаль, а не конкатенация в коде.\n return currentLabel.value\n ? t('gr.rating.valueTextWithLabel', '{value} of {max}, {label}', { ...params, label: currentLabel.value })\n : t('gr.rating.valueText', '{value} of {max}', params)\n})\n\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.rating.label', 'Rating'))\n\nconst text = computed(() => {\n if (props.formatText) return props.formatText(displayValue.value)\n return currentLabel.value ?? String(displayValue.value)\n})\n\n/** Значение, соответствующее позиции курсора внутри символа `index`. */\nfunction valueAt(index: number, event: MouseEvent): number {\n if (!props.allowHalf) return index + 1\n const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()\n return rect.width > 0 && event.clientX - rect.left < rect.width / 2 ? index + 0.5 : index + 1\n}\n\nfunction onScaleBlur(event: FocusEvent): void {\n resetHover()\n emit('blur', event)\n}\n\nfunction commit(value: number): void {\n const next = clamp(value)\n if (next !== props.modelValue) emit('update:modelValue', next)\n emit('change', next)\n}\n\nfunction onSymbolClick(index: number, event: MouseEvent): void {\n if (!interactive.value) return\n const next = valueAt(index, event)\n const cleared = props.clearable && next === props.modelValue\n\n commit(cleared ? 0 : next)\n if (cleared) emit('clear')\n}\n\nfunction onSymbolMouseMove(index: number, event: MouseEvent): void {\n if (!interactive.value) {\n // Режим сменился под курсором — оставлять подсветку от прошлого состояния нельзя.\n resetHover()\n return\n }\n const next = valueAt(index, event)\n if (next === hoverValue.value) return\n hoverValue.value = next\n emit('hoverChange', next)\n}\n\nfunction resetHover(): void {\n if (hoverValue.value === null) return\n hoverValue.value = null\n emit('hoverChange', null)\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (!interactive.value) return\n const current = clamp(props.modelValue)\n let next: number | null = null\n\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = current + step.value\n break\n case 'ArrowLeft':\n case 'ArrowDown':\n next = current - step.value\n break\n case 'Home':\n next = 0\n break\n case 'End':\n next = props.max\n break\n default:\n return\n }\n\n event.preventDefault()\n commit(next)\n}\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n data-gr-rating\n class=\"inline-flex items-center gap-2\"\n >\n <!-- Нативная форма: роль-виджет не labelable и в submit не попадает. -->\n <input\n v-if=\"name && modelValue > 0\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"String(modelValue)\"\n >\n <div\n :id=\"resolvedId\"\n data-gr-rating-scale\n data-testid=\"gr-rating-scale\"\n :class=\"ratingRootClass({ size: resolvedSize, disabled, interactive })\"\n :role=\"asSlider ? 'slider' : 'img'\"\n :tabindex=\"asSlider ? (disabled ? -1 : 0) : undefined\"\n :aria-label=\"asSlider ? resolvedAriaLabel : `${resolvedAriaLabel}: ${valueText}`\"\n :aria-valuemin=\"asSlider ? 0 : undefined\"\n :aria-valuemax=\"asSlider ? max : undefined\"\n :aria-valuenow=\"asSlider ? displayValue : undefined\"\n :aria-valuetext=\"asSlider ? valueText : undefined\"\n :aria-orientation=\"asSlider ? 'horizontal' : undefined\"\n :aria-disabled=\"asSlider && disabled ? 'true' : undefined\"\n :aria-invalid=\"asSlider && isInvalid ? 'true' : undefined\"\n :aria-describedby=\"asSlider ? describedBy : undefined\"\n :aria-required=\"asSlider && isRequired ? 'true' : undefined\"\n :aria-readonly=\"asSlider && isReadonly ? 'true' : undefined\"\n @keydown=\"onKeydown\"\n @mouseleave=\"resetHover\"\n @focus=\"emit('focus', $event)\"\n @blur=\"onScaleBlur\"\n >\n <span\n v-for=\"index in symbols\"\n :key=\"index\"\n data-gr-rating-symbol\n :data-testid=\"`gr-rating-symbol-${index}`\"\n :class=\"ratingSymbolClass(resolvedSize)\"\n @click=\"onSymbolClick(index, $event)\"\n @mousemove=\"onSymbolMouseMove(index, $event)\"\n >\n <!-- Нижний слой — «пустой» символ, поверх него обрезанный по ширине «залитый». -->\n <span class=\"block h-full w-full\" :class=\"ratingVoidClass\" aria-hidden=\"true\">\n <slot name=\"symbol\" :index=\"index\" :filled=\"false\">\n <component :is=\"iconTag(icon)\" v-if=\"icon\" class=\"block h-full w-full\" :class=\"iconClass(icon)\" />\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"block h-full w-full\">\n <path d=\"M12 2.5l2.9 6.1 6.6.9-4.8 4.7 1.2 6.6L12 17.7 6.1 20.8l1.2-6.6L2.5 9.5l6.6-.9z\" />\n </svg>\n </slot>\n </span>\n\n <span\n data-gr-rating-fill\n class=\"pointer-events-none absolute inset-y-0 left-0 overflow-hidden\"\n :class=\"ratingFillClassByTone[tone]\"\n :style=\"{ width: `${fillRatio(index) * 100}%` }\"\n aria-hidden=\"true\"\n >\n <span :class=\"ratingSymbolClass(resolvedSize)\">\n <slot name=\"symbol\" :index=\"index\" :filled=\"true\">\n <component :is=\"iconTag(icon)\" v-if=\"icon\" class=\"block h-full w-full\" :class=\"iconClass(icon)\" />\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"block h-full w-full\">\n <path d=\"M12 2.5l2.9 6.1 6.6.9-4.8 4.7 1.2 6.6L12 17.7 6.1 20.8l1.2-6.6L2.5 9.5l6.6-.9z\" />\n </svg>\n </slot>\n </span>\n </span>\n </span>\n </div>\n\n <span\n v-if=\"showText || $slots.text\"\n data-gr-rating-text\n class=\"text-[var(--gr-muted-fg)] tabular-nums\"\n :class=\"ratingTextSizeBySize[resolvedSize]\"\n >\n <slot name=\"text\" :value=\"displayValue\">{{ text }}</slot>\n </span>\n </div>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GrRating-BSEtaibx.js","names":["$slots"],"sources":["../../../../src/components/GrRating/GrRating.vue","../../../../src/components/GrRating/GrRating.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, type Component } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { iconClass, iconTag } from '../shared/icon'\n\nimport {\n ratingFillClassByTone,\n ratingRootClass,\n ratingSymbolClass,\n ratingTextSizeBySize,\n ratingVoidClass,\n type GrRatingSize,\n type GrRatingTone,\n} from './grRatingStyles'\n\nexport type {\n GrRatingSize,\n GrRatingTone,\n} from './grRatingStyles'\n\n/**\n * Публичный GR-примитив «Rating» — шкала оценки символами (по умолчанию звёзды).\n *\n * Интерактивный режим реализует WAI-ARIA slider pattern (`role=\"slider\"`,\n * `aria-valuemin/max/now/valuetext`, стрелки / Home / End), режим только для\n * чтения — `role=\"img\"` с текстовой подписью, чтобы скринридер озвучил оценку\n * одной фразой, а не набором элементов.\n *\n * Символ по умолчанию рисуется инлайновым SVG (звезда с `fill=\"currentColor\"`) —\n * иконочные шрифты-маски `i-lucide-star` дают только контур. Свой символ\n * задаётся пропом `icon` (Vue-компонент или класс иконки) либо слотом `#symbol`.\n */\nexport interface GrRatingProps {\n /** Текущая оценка. Дробная (`3.5`) поддерживается при `allowHalf`. */\n modelValue: number\n /** Количество символов шкалы. */\n max?: number\n size?: GrRatingSize\n /** Тон заливки; точечно перекрывается переменной `--gr-rating-color`. */\n tone?: GrRatingTone\n /** Половинчатые оценки: клик по левой половине символа даёт `.5`. */\n allowHalf?: boolean\n /** Только показ: без ввода и фокуса. */\n readonly?: boolean\n disabled?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n /** Обязательное поле (`aria-required`). */\n required?: boolean\n /** Повторный клик по текущей оценке сбрасывает её в `0`. */\n clearable?: boolean\n /**\n * Символ вместо встроенной звезды: Vue-компонент либо класс иконки вашей\n * UnoCSS-сборки (`'i-lucide-heart'` — тогда нужен ваш `presetIcons`,\n * см. `docs/installation.md`).\n */\n icon?: string | Component\n /** Показывать числовую подпись справа от шкалы. */\n showText?: boolean\n /** Формат подписи. По умолчанию — само значение. Сильнее `texts`. */\n formatText?: (value: number) => string\n /**\n * Подписи по делениям: «3 из 5, нормально» вместо «3 из 5». Уходят и в\n * видимый текст, и в `aria-valuetext` — ради этого рейтинг и существует.\n * Массив короче `max` оставляет верхние деления без подписи.\n */\n texts?: string[]\n /**\n * Компактный вид: рисуются только заполненные символы. Осмысленно вместе с\n * `readonly` — в списках и таблицах пять звёзд в каждой строке съедают ширину.\n */\n compact?: boolean\n ariaLabel?: string\n /** Имя для нативной формы: hidden input со значением; `0` — «не выбрано», input не рендерится. */\n name?: string\n}\n\nexport interface GrRatingEmits {\n (e: 'update:modelValue', value: number): void\n /** Оценка зафиксирована (клик / клавиша). */\n (e: 'change', value: number): void\n /** Значение под курсором; `null` — курсор ушёл со шкалы. */\n (e: 'hoverChange', value: number | null): void\n /** Оценка снята повторным кликом; только при `clearable`. */\n (e: 'clear'): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(\n defineProps<GrRatingProps>(),\n {\n max: 5,\n size: undefined,\n tone: 'warning',\n allowHalf: false,\n readonly: false,\n disabled: false,\n invalid: false,\n required: false,\n clearable: false,\n icon: undefined,\n showText: false,\n formatText: undefined,\n texts: undefined,\n compact: false,\n ariaLabel: undefined,\n name: undefined,\n },\n)\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentSize(() => props.size, {\n component: 'GrRating',\n supported: ['xs', 'sm', 'md', 'lg'],\n})\n\nconst emit = defineEmits<GrRatingEmits>()\ndefineSlots<{\n /** Свой символ вместо звезды. `filled` — закрашенная половина символа. */\n symbol?: (props: { index: number, filled: boolean }) => any\n /** Подпись рядом с оценкой. */\n text?: (props: { value: number }) => any\n}>()\n\n\nconst { t } = useGranularityTranslations()\n\n// Контекст `GrFormField`: id/aria-describedby/invalid/required как fallback.\nconst field = useGrFormFieldContext()\nconst resolvedId = computed(() => field?.id.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid, required: isRequired, readonly: isReadonly } = useGrFormControl(() => props)\nconst describedBy = computed(() => field?.describedById.value)\n\nconst rootEl = ref<HTMLElement | null>(null)\n\nfunction focus(): void {\n rootEl.value?.querySelector<HTMLElement>('[data-gr-rating-scale]')?.focus()\n}\n\nfunction blur(): void {\n rootEl.value?.querySelector<HTMLElement>('[data-gr-rating-scale]')?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n/** Ввод возможен: не readonly и не disabled. */\nconst interactive = computed(() => !isReadonly.value && !isDisabled.value)\n\n/**\n * `aria-readonly`, `aria-invalid` и `aria-required` вешаются только в\n * slider-режиме: на `role=\"img\"` они не разрешены и дают critical в axe.\n *\n * Роль контрола (`slider`) сохраняется и в `disabled` — отключённый слайдер это\n * штатный ARIA-паттерн. А вот `readonly` — это уже не контрол, а картинка с\n * подписью: на `role=\"img\"` атрибуты `aria-value*`/`aria-disabled` запрещены\n * (axe: `aria-allowed-attr`), поэтому там их не выводим вовсе.\n */\nconst asSlider = computed(() => !props.readonly)\nconst step = computed(() => (props.allowHalf ? 0.5 : 1))\n\n// Значение под курсором имеет приоритет над моделью — это «предпросмотр» оценки.\nconst hoverValue = ref<number | null>(null)\nconst displayValue = computed(() => hoverValue.value ?? clamp(props.modelValue))\n\nfunction clamp(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.min(props.max, Math.max(0, value))\n}\n\n/** Доля заливки символа с индексом `index` (0..1). */\nfunction fillRatio(index: number): number {\n return Math.min(1, Math.max(0, displayValue.value - index))\n}\n\nconst symbols = computed(() => {\n // Компактный вид показывает только заполненную часть шкалы; половинка\n // считается символом — иначе «2.5» потеряло бы половину звезды.\n const length = props.compact ? Math.ceil(clamp(props.modelValue)) : props.max\n return Array.from({ length }, (_, index) => index)\n})\n\n/** Подпись деления под текущим значением: половинки округляются вверх. */\nconst currentLabel = computed(() => {\n if (!props.texts?.length || displayValue.value <= 0) return undefined\n return props.texts[Math.ceil(displayValue.value) - 1]\n})\n\nconst valueText = computed(() => {\n const params = { value: displayValue.value, max: props.max }\n\n // Порядок слов задаёт локаль, а не конкатенация в коде.\n return currentLabel.value\n ? t('gr.rating.valueTextWithLabel', '{value} of {max}, {label}', { ...params, label: currentLabel.value })\n : t('gr.rating.valueText', '{value} of {max}', params)\n})\n\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.rating.label', 'Rating'))\n\nconst text = computed(() => {\n if (props.formatText) return props.formatText(displayValue.value)\n return currentLabel.value ?? String(displayValue.value)\n})\n\n/** Значение, соответствующее позиции курсора внутри символа `index`. */\nfunction valueAt(index: number, event: MouseEvent): number {\n if (!props.allowHalf) return index + 1\n const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()\n return rect.width > 0 && event.clientX - rect.left < rect.width / 2 ? index + 0.5 : index + 1\n}\n\nfunction onScaleBlur(event: FocusEvent): void {\n resetHover()\n emit('blur', event)\n}\n\nfunction commit(value: number): void {\n const next = clamp(value)\n if (next !== props.modelValue) emit('update:modelValue', next)\n emit('change', next)\n}\n\nfunction onSymbolClick(index: number, event: MouseEvent): void {\n if (!interactive.value) return\n const next = valueAt(index, event)\n const cleared = props.clearable && next === props.modelValue\n\n commit(cleared ? 0 : next)\n if (cleared) emit('clear')\n}\n\nfunction onSymbolMouseMove(index: number, event: MouseEvent): void {\n if (!interactive.value) {\n // Режим сменился под курсором — оставлять подсветку от прошлого состояния нельзя.\n resetHover()\n return\n }\n const next = valueAt(index, event)\n if (next === hoverValue.value) return\n hoverValue.value = next\n emit('hoverChange', next)\n}\n\nfunction resetHover(): void {\n if (hoverValue.value === null) return\n hoverValue.value = null\n emit('hoverChange', null)\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (!interactive.value) return\n const current = clamp(props.modelValue)\n let next: number | null = null\n\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = current + step.value\n break\n case 'ArrowLeft':\n case 'ArrowDown':\n next = current - step.value\n break\n case 'Home':\n next = 0\n break\n case 'End':\n next = props.max\n break\n default:\n return\n }\n\n event.preventDefault()\n commit(next)\n}\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n data-gr-rating\n class=\"inline-flex items-center gap-2\"\n >\n <!-- Нативная форма: роль-виджет не labelable и в submit не попадает. -->\n <input\n v-if=\"name && modelValue > 0\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"String(modelValue)\"\n >\n <div\n :id=\"resolvedId\"\n data-gr-rating-scale\n data-testid=\"gr-rating-scale\"\n :class=\"ratingRootClass({ size: resolvedSize, disabled, interactive })\"\n :role=\"asSlider ? 'slider' : 'img'\"\n :tabindex=\"asSlider ? (disabled ? -1 : 0) : undefined\"\n :aria-label=\"asSlider ? resolvedAriaLabel : `${resolvedAriaLabel}: ${valueText}`\"\n :aria-valuemin=\"asSlider ? 0 : undefined\"\n :aria-valuemax=\"asSlider ? max : undefined\"\n :aria-valuenow=\"asSlider ? displayValue : undefined\"\n :aria-valuetext=\"asSlider ? valueText : undefined\"\n :aria-orientation=\"asSlider ? 'horizontal' : undefined\"\n :aria-disabled=\"asSlider && disabled ? 'true' : undefined\"\n :aria-invalid=\"asSlider && isInvalid ? 'true' : undefined\"\n :aria-describedby=\"asSlider ? describedBy : undefined\"\n :aria-required=\"asSlider && isRequired ? 'true' : undefined\"\n :aria-readonly=\"asSlider && isReadonly ? 'true' : undefined\"\n @keydown=\"onKeydown\"\n @mouseleave=\"resetHover\"\n @focus=\"emit('focus', $event)\"\n @blur=\"onScaleBlur\"\n >\n <span\n v-for=\"index in symbols\"\n :key=\"index\"\n data-gr-rating-symbol\n :data-testid=\"`gr-rating-symbol-${index}`\"\n :class=\"ratingSymbolClass(resolvedSize)\"\n @click=\"onSymbolClick(index, $event)\"\n @mousemove=\"onSymbolMouseMove(index, $event)\"\n >\n <!-- Нижний слой — «пустой» символ, поверх него обрезанный по ширине «залитый». -->\n <span class=\"block h-full w-full\" :class=\"ratingVoidClass\" aria-hidden=\"true\">\n <slot name=\"symbol\" :index=\"index\" :filled=\"false\">\n <component :is=\"iconTag(icon)\" v-if=\"icon\" class=\"block h-full w-full\" :class=\"iconClass(icon)\" />\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"block h-full w-full\">\n <path d=\"M12 2.5l2.9 6.1 6.6.9-4.8 4.7 1.2 6.6L12 17.7 6.1 20.8l1.2-6.6L2.5 9.5l6.6-.9z\" />\n </svg>\n </slot>\n </span>\n\n <span\n data-gr-rating-fill\n class=\"pointer-events-none absolute inset-y-0 left-0 overflow-hidden\"\n :class=\"ratingFillClassByTone[tone]\"\n :style=\"{ width: `${fillRatio(index) * 100}%` }\"\n aria-hidden=\"true\"\n >\n <span :class=\"ratingSymbolClass(resolvedSize)\">\n <slot name=\"symbol\" :index=\"index\" :filled=\"true\">\n <component :is=\"iconTag(icon)\" v-if=\"icon\" class=\"block h-full w-full\" :class=\"iconClass(icon)\" />\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"block h-full w-full\">\n <path d=\"M12 2.5l2.9 6.1 6.6.9-4.8 4.7 1.2 6.6L12 17.7 6.1 20.8l1.2-6.6L2.5 9.5l6.6-.9z\" />\n </svg>\n </slot>\n </span>\n </span>\n </span>\n </div>\n\n <span\n v-if=\"showText || $slots.text\"\n data-gr-rating-text\n class=\"text-[var(--gr-muted-fg)] tabular-nums\"\n :class=\"ratingTextSizeBySize[resolvedSize]\"\n >\n <slot name=\"text\" :value=\"displayValue\">{{ text }}</slot>\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, type Component } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { iconClass, iconTag } from '../shared/icon'\n\nimport {\n ratingFillClassByTone,\n ratingRootClass,\n ratingSymbolClass,\n ratingTextSizeBySize,\n ratingVoidClass,\n type GrRatingSize,\n type GrRatingTone,\n} from './grRatingStyles'\n\nexport type {\n GrRatingSize,\n GrRatingTone,\n} from './grRatingStyles'\n\n/**\n * Публичный GR-примитив «Rating» — шкала оценки символами (по умолчанию звёзды).\n *\n * Интерактивный режим реализует WAI-ARIA slider pattern (`role=\"slider\"`,\n * `aria-valuemin/max/now/valuetext`, стрелки / Home / End), режим только для\n * чтения — `role=\"img\"` с текстовой подписью, чтобы скринридер озвучил оценку\n * одной фразой, а не набором элементов.\n *\n * Символ по умолчанию рисуется инлайновым SVG (звезда с `fill=\"currentColor\"`) —\n * иконочные шрифты-маски `i-lucide-star` дают только контур. Свой символ\n * задаётся пропом `icon` (Vue-компонент или класс иконки) либо слотом `#symbol`.\n */\nexport interface GrRatingProps {\n /** Текущая оценка. Дробная (`3.5`) поддерживается при `allowHalf`. */\n modelValue: number\n /** Количество символов шкалы. */\n max?: number\n size?: GrRatingSize\n /** Тон заливки; точечно перекрывается переменной `--gr-rating-color`. */\n tone?: GrRatingTone\n /** Половинчатые оценки: клик по левой половине символа даёт `.5`. */\n allowHalf?: boolean\n /** Только показ: без ввода и фокуса. */\n readonly?: boolean\n disabled?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n /** Обязательное поле (`aria-required`). */\n required?: boolean\n /** Повторный клик по текущей оценке сбрасывает её в `0`. */\n clearable?: boolean\n /**\n * Символ вместо встроенной звезды: Vue-компонент либо класс иконки вашей\n * UnoCSS-сборки (`'i-lucide-heart'` — тогда нужен ваш `presetIcons`,\n * см. `docs/installation.md`).\n */\n icon?: string | Component\n /** Показывать числовую подпись справа от шкалы. */\n showText?: boolean\n /** Формат подписи. По умолчанию — само значение. Сильнее `texts`. */\n formatText?: (value: number) => string\n /**\n * Подписи по делениям: «3 из 5, нормально» вместо «3 из 5». Уходят и в\n * видимый текст, и в `aria-valuetext` — ради этого рейтинг и существует.\n * Массив короче `max` оставляет верхние деления без подписи.\n */\n texts?: string[]\n /**\n * Компактный вид: рисуются только заполненные символы. Осмысленно вместе с\n * `readonly` — в списках и таблицах пять звёзд в каждой строке съедают ширину.\n */\n compact?: boolean\n ariaLabel?: string\n /** Имя для нативной формы: hidden input со значением; `0` — «не выбрано», input не рендерится. */\n name?: string\n}\n\nexport interface GrRatingEmits {\n (e: 'update:modelValue', value: number): void\n /** Оценка зафиксирована (клик / клавиша). */\n (e: 'change', value: number): void\n /** Значение под курсором; `null` — курсор ушёл со шкалы. */\n (e: 'hoverChange', value: number | null): void\n /** Оценка снята повторным кликом; только при `clearable`. */\n (e: 'clear'): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(\n defineProps<GrRatingProps>(),\n {\n max: 5,\n size: undefined,\n tone: 'warning',\n allowHalf: false,\n readonly: false,\n disabled: false,\n invalid: false,\n required: false,\n clearable: false,\n icon: undefined,\n showText: false,\n formatText: undefined,\n texts: undefined,\n compact: false,\n ariaLabel: undefined,\n name: undefined,\n },\n)\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentSize(() => props.size, {\n component: 'GrRating',\n supported: ['xs', 'sm', 'md', 'lg'],\n})\n\nconst emit = defineEmits<GrRatingEmits>()\ndefineSlots<{\n /** Свой символ вместо звезды. `filled` — закрашенная половина символа. */\n symbol?: (props: { index: number, filled: boolean }) => any\n /** Подпись рядом с оценкой. */\n text?: (props: { value: number }) => any\n}>()\n\n\nconst { t } = useGranularityTranslations()\n\n// Контекст `GrFormField`: id/aria-describedby/invalid/required как fallback.\nconst field = useGrFormFieldContext()\nconst resolvedId = computed(() => field?.id.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid, required: isRequired, readonly: isReadonly } = useGrFormControl(() => props)\nconst describedBy = computed(() => field?.describedById.value)\n\nconst rootEl = ref<HTMLElement | null>(null)\n\nfunction focus(): void {\n rootEl.value?.querySelector<HTMLElement>('[data-gr-rating-scale]')?.focus()\n}\n\nfunction blur(): void {\n rootEl.value?.querySelector<HTMLElement>('[data-gr-rating-scale]')?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n/** Ввод возможен: не readonly и не disabled. */\nconst interactive = computed(() => !isReadonly.value && !isDisabled.value)\n\n/**\n * `aria-readonly`, `aria-invalid` и `aria-required` вешаются только в\n * slider-режиме: на `role=\"img\"` они не разрешены и дают critical в axe.\n *\n * Роль контрола (`slider`) сохраняется и в `disabled` — отключённый слайдер это\n * штатный ARIA-паттерн. А вот `readonly` — это уже не контрол, а картинка с\n * подписью: на `role=\"img\"` атрибуты `aria-value*`/`aria-disabled` запрещены\n * (axe: `aria-allowed-attr`), поэтому там их не выводим вовсе.\n */\nconst asSlider = computed(() => !props.readonly)\nconst step = computed(() => (props.allowHalf ? 0.5 : 1))\n\n// Значение под курсором имеет приоритет над моделью — это «предпросмотр» оценки.\nconst hoverValue = ref<number | null>(null)\nconst displayValue = computed(() => hoverValue.value ?? clamp(props.modelValue))\n\nfunction clamp(value: number): number {\n if (!Number.isFinite(value)) return 0\n return Math.min(props.max, Math.max(0, value))\n}\n\n/** Доля заливки символа с индексом `index` (0..1). */\nfunction fillRatio(index: number): number {\n return Math.min(1, Math.max(0, displayValue.value - index))\n}\n\nconst symbols = computed(() => {\n // Компактный вид показывает только заполненную часть шкалы; половинка\n // считается символом — иначе «2.5» потеряло бы половину звезды.\n const length = props.compact ? Math.ceil(clamp(props.modelValue)) : props.max\n return Array.from({ length }, (_, index) => index)\n})\n\n/** Подпись деления под текущим значением: половинки округляются вверх. */\nconst currentLabel = computed(() => {\n if (!props.texts?.length || displayValue.value <= 0) return undefined\n return props.texts[Math.ceil(displayValue.value) - 1]\n})\n\nconst valueText = computed(() => {\n const params = { value: displayValue.value, max: props.max }\n\n // Порядок слов задаёт локаль, а не конкатенация в коде.\n return currentLabel.value\n ? t('gr.rating.valueTextWithLabel', '{value} of {max}, {label}', { ...params, label: currentLabel.value })\n : t('gr.rating.valueText', '{value} of {max}', params)\n})\n\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.rating.label', 'Rating'))\n\nconst text = computed(() => {\n if (props.formatText) return props.formatText(displayValue.value)\n return currentLabel.value ?? String(displayValue.value)\n})\n\n/** Значение, соответствующее позиции курсора внутри символа `index`. */\nfunction valueAt(index: number, event: MouseEvent): number {\n if (!props.allowHalf) return index + 1\n const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()\n return rect.width > 0 && event.clientX - rect.left < rect.width / 2 ? index + 0.5 : index + 1\n}\n\nfunction onScaleBlur(event: FocusEvent): void {\n resetHover()\n emit('blur', event)\n}\n\nfunction commit(value: number): void {\n const next = clamp(value)\n if (next !== props.modelValue) emit('update:modelValue', next)\n emit('change', next)\n}\n\nfunction onSymbolClick(index: number, event: MouseEvent): void {\n if (!interactive.value) return\n const next = valueAt(index, event)\n const cleared = props.clearable && next === props.modelValue\n\n commit(cleared ? 0 : next)\n if (cleared) emit('clear')\n}\n\nfunction onSymbolMouseMove(index: number, event: MouseEvent): void {\n if (!interactive.value) {\n // Режим сменился под курсором — оставлять подсветку от прошлого состояния нельзя.\n resetHover()\n return\n }\n const next = valueAt(index, event)\n if (next === hoverValue.value) return\n hoverValue.value = next\n emit('hoverChange', next)\n}\n\nfunction resetHover(): void {\n if (hoverValue.value === null) return\n hoverValue.value = null\n emit('hoverChange', null)\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (!interactive.value) return\n const current = clamp(props.modelValue)\n let next: number | null = null\n\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = current + step.value\n break\n case 'ArrowLeft':\n case 'ArrowDown':\n next = current - step.value\n break\n case 'Home':\n next = 0\n break\n case 'End':\n next = props.max\n break\n default:\n return\n }\n\n event.preventDefault()\n commit(next)\n}\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n data-gr-rating\n class=\"inline-flex items-center gap-2\"\n >\n <!-- Нативная форма: роль-виджет не labelable и в submit не попадает. -->\n <input\n v-if=\"name && modelValue > 0\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"String(modelValue)\"\n >\n <div\n :id=\"resolvedId\"\n data-gr-rating-scale\n data-testid=\"gr-rating-scale\"\n :class=\"ratingRootClass({ size: resolvedSize, disabled, interactive })\"\n :role=\"asSlider ? 'slider' : 'img'\"\n :tabindex=\"asSlider ? (disabled ? -1 : 0) : undefined\"\n :aria-label=\"asSlider ? resolvedAriaLabel : `${resolvedAriaLabel}: ${valueText}`\"\n :aria-valuemin=\"asSlider ? 0 : undefined\"\n :aria-valuemax=\"asSlider ? max : undefined\"\n :aria-valuenow=\"asSlider ? displayValue : undefined\"\n :aria-valuetext=\"asSlider ? valueText : undefined\"\n :aria-orientation=\"asSlider ? 'horizontal' : undefined\"\n :aria-disabled=\"asSlider && disabled ? 'true' : undefined\"\n :aria-invalid=\"asSlider && isInvalid ? 'true' : undefined\"\n :aria-describedby=\"asSlider ? describedBy : undefined\"\n :aria-required=\"asSlider && isRequired ? 'true' : undefined\"\n :aria-readonly=\"asSlider && isReadonly ? 'true' : undefined\"\n @keydown=\"onKeydown\"\n @mouseleave=\"resetHover\"\n @focus=\"emit('focus', $event)\"\n @blur=\"onScaleBlur\"\n >\n <span\n v-for=\"index in symbols\"\n :key=\"index\"\n data-gr-rating-symbol\n :data-testid=\"`gr-rating-symbol-${index}`\"\n :class=\"ratingSymbolClass(resolvedSize)\"\n @click=\"onSymbolClick(index, $event)\"\n @mousemove=\"onSymbolMouseMove(index, $event)\"\n >\n <!-- Нижний слой — «пустой» символ, поверх него обрезанный по ширине «залитый». -->\n <span class=\"block h-full w-full\" :class=\"ratingVoidClass\" aria-hidden=\"true\">\n <slot name=\"symbol\" :index=\"index\" :filled=\"false\">\n <component :is=\"iconTag(icon)\" v-if=\"icon\" class=\"block h-full w-full\" :class=\"iconClass(icon)\" />\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"block h-full w-full\">\n <path d=\"M12 2.5l2.9 6.1 6.6.9-4.8 4.7 1.2 6.6L12 17.7 6.1 20.8l1.2-6.6L2.5 9.5l6.6-.9z\" />\n </svg>\n </slot>\n </span>\n\n <span\n data-gr-rating-fill\n class=\"pointer-events-none absolute inset-y-0 left-0 overflow-hidden\"\n :class=\"ratingFillClassByTone[tone]\"\n :style=\"{ width: `${fillRatio(index) * 100}%` }\"\n aria-hidden=\"true\"\n >\n <span :class=\"ratingSymbolClass(resolvedSize)\">\n <slot name=\"symbol\" :index=\"index\" :filled=\"true\">\n <component :is=\"iconTag(icon)\" v-if=\"icon\" class=\"block h-full w-full\" :class=\"iconClass(icon)\" />\n <svg v-else viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"block h-full w-full\">\n <path d=\"M12 2.5l2.9 6.1 6.6.9-4.8 4.7 1.2 6.6L12 17.7 6.1 20.8l1.2-6.6L2.5 9.5l6.6-.9z\" />\n </svg>\n </slot>\n </span>\n </span>\n </span>\n </div>\n\n <span\n v-if=\"showText || $slots.text\"\n data-gr-rating-text\n class=\"text-[var(--gr-muted-fg)] tabular-nums\"\n :class=\"ratingTextSizeBySize[resolvedSize]\"\n >\n <slot name=\"text\" :value=\"displayValue\">{{ text }}</slot>\n </span>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as grRatingSafelist, t as grRatingConfig } from "../../chunks/config-Baj7Wvx
|
|
2
|
-
import { t as GrRating_default } from "./chunks/GrRating-
|
|
1
|
+
import { n as grRatingSafelist, t as grRatingConfig } from "../../chunks/config-Baj7Wvx-.js";
|
|
2
|
+
import { t as GrRating_default } from "./chunks/GrRating-BSEtaibx.js";
|
|
3
3
|
export { GrRating_default as GrRating, GrRating_default as default, grRatingConfig, grRatingSafelist };
|
package/dist/components/GrStatistic/chunks/{GrStatistic-DkzWUAw1.js → GrStatistic-C7wQECeS.js}
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as useGrComponentSize } from "../../../chunks/context-CTbuwcYs.js";
|
|
1
|
+
import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
|
|
2
2
|
import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
|
|
3
3
|
import { t as GrSkeleton_default } from "../../GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js";
|
|
4
4
|
import { n as iconTag, t as iconClass } from "../../../chunks/icon-Dag2tIMs.js";
|
|
5
5
|
import { t as minus_default } from "../../../chunks/minus-oxdbHF33.js";
|
|
6
|
-
import {
|
|
6
|
+
import { i as trending_down_default, n as deltaTone, r as trending_up_default } from "../../../chunks/deltaTone-B5OoS1vo.js";
|
|
7
7
|
import { a as statisticRootClass, c as statisticTrendClassByTrend, i as statisticPlaceholderHeightBySize, l as statisticTrendSizeBySize, o as statisticTitleClass, r as statisticAffixSizeBySize, s as statisticTitleSizeBySize, u as statisticValueClass } from "../../../chunks/config-Be9k9bOf.js";
|
|
8
8
|
import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, markRaw, normalizeClass, onBeforeUnmount, onMounted, openBlock, ref, renderSlot, resolveDynamicComponent, toDisplayString, unref, useSlots, watch, withCtx } from "vue";
|
|
9
9
|
//#region src/components/GrStatistic/countUp.ts
|
|
@@ -118,7 +118,8 @@ var GrStatistic_default = /* @__PURE__ */ defineComponent({
|
|
|
118
118
|
suffix: { default: void 0 },
|
|
119
119
|
icon: { default: void 0 },
|
|
120
120
|
size: { default: void 0 },
|
|
121
|
-
tone: { default:
|
|
121
|
+
tone: { default: void 0 },
|
|
122
|
+
polarity: { default: void 0 },
|
|
122
123
|
trend: { default: void 0 },
|
|
123
124
|
trendText: { default: void 0 },
|
|
124
125
|
loading: {
|
|
@@ -237,6 +238,21 @@ var GrStatistic_default = /* @__PURE__ */ defineComponent({
|
|
|
237
238
|
watch(() => props.value, (next, prev) => startIfNumeric(prev, next));
|
|
238
239
|
onBeforeUnmount(stopCounting);
|
|
239
240
|
const resolvedSize = useGrComponentSize(() => props.size, { component: "GrStatistic" });
|
|
241
|
+
const resolvedPolarity = useGrComponentProp("GrStatistic", "polarity", () => props.polarity, "none");
|
|
242
|
+
/**
|
|
243
|
+
* Тон значения: явный проп → выведенный из знака → нейтральный.
|
|
244
|
+
*
|
|
245
|
+
* Отдельной ветки «полярность не задана» нет намеренно: `deltaTone(x, 'none')`
|
|
246
|
+
* нейтрален при любом значении, то есть `'none'` и есть прежнее поведение.
|
|
247
|
+
*
|
|
248
|
+
* Знак берётся у самого пропа, а не у кадра перебора: `frameValue` стартует с
|
|
249
|
+
* нуля, и цвет плитки мигал бы нейтральным на каждой анимации.
|
|
250
|
+
*/
|
|
251
|
+
const resolvedTone = computed(() => {
|
|
252
|
+
if (props.tone !== void 0) return props.tone;
|
|
253
|
+
const numeric = toNumber(props.value);
|
|
254
|
+
return numeric === null ? "neutral" : deltaTone(numeric, resolvedPolarity.value);
|
|
255
|
+
});
|
|
240
256
|
const trendIconByTrend = {
|
|
241
257
|
up: trending_up_default,
|
|
242
258
|
down: trending_down_default,
|
|
@@ -296,7 +312,7 @@ var GrStatistic_default = /* @__PURE__ */ defineComponent({
|
|
|
296
312
|
"data-gr-statistic-number": "",
|
|
297
313
|
class: normalizeClass(unref(statisticValueClass)({
|
|
298
314
|
size: unref(resolvedSize),
|
|
299
|
-
tone:
|
|
315
|
+
tone: resolvedTone.value
|
|
300
316
|
})),
|
|
301
317
|
"aria-hidden": isCounting.value ? "true" : void 0
|
|
302
318
|
}, [renderSlot(_ctx.$slots, "default", {}, () => [createTextVNode(toDisplayString(formatted.value), 1)])], 10, _hoisted_4),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GrStatistic-C7wQECeS.js","names":["$slots"],"sources":["../../../../src/components/GrStatistic/countUp.ts","../../../../src/components/GrStatistic/formatStatisticValue.ts","../../../../src/components/GrStatistic/GrStatistic.vue","../../../../src/components/GrStatistic/GrStatistic.vue"],"sourcesContent":["/**\n * Перебор чисел для `GrStatistic`: чистая арифметика кадра без Vue и таймеров.\n *\n * Вынесено отдельным модулем по той же причине, что и `formatStatisticValue`:\n * кривая и округление проверяются напрямую, без монтирования и подмены `rAF`.\n */\n\n/** Быстрый старт, мягкая остановка — та же форма, что у `--gr-ease-out`. */\nexport function easeOutCubic(t: number): number {\n const clamped = Math.min(Math.max(t, 0), 1)\n return 1 - (1 - clamped) ** 3\n}\n\n/**\n * Значение кадра на `elapsed` миллисекунде перехода `from → to`.\n *\n * Округление до `precision` обязательно: без него кадры показывали бы\n * `1283.6666666666667` там, где показатель целый, и ширина строки прыгала бы\n * даже при `tabular-nums`. Последний кадр возвращает ровно `to` — приближение\n * не должно оставлять показатель в 1283.9999.\n */\nexport function countUpFrame(\n from: number,\n to: number,\n elapsed: number,\n duration: number,\n precision?: number,\n): number {\n if (!(duration > 0) || elapsed >= duration) return to\n\n const digits = Math.min(Math.max(precision ?? 0, 0), 20)\n const value = from + (to - from) * easeOutCubic(elapsed / duration)\n\n return Number(value.toFixed(digits))\n}\n","export type GrStatisticFormatOptions = {\n /** Число знаков после запятой. `undefined` — оставить как есть. */\n precision?: number\n /** Разделитель групп разрядов. Сильнее локали. */\n groupSeparator?: string\n /** Десятичный разделитель. Сильнее локали. */\n decimalSeparator?: string\n /** BCP-47 локаль: разделители берутся из `Intl.NumberFormat`. */\n locale?: string\n}\n\nconst DEFAULT_GROUP_SEPARATOR = ' '\nconst DEFAULT_DECIMAL_SEPARATOR = '.'\n\n/**\n * Форматирует значение показателя: фиксирует точность и расставляет разделители.\n *\n * Нечисловые значения возвращаются без изменений — это позволяет показывать в\n * `GrStatistic` уже готовые строки («2 ч 15 мин», «—») без обходных пропов.\n * Вынесено из SFC отдельным модулем, чтобы тестировалось без монтирования.\n *\n * Порядок разрешения разделителей: явный проп → локаль → встроенный дефолт.\n */\nexport function formatStatisticValue(\n value: number | string,\n options: GrStatisticFormatOptions = {},\n): string {\n const { precision, groupSeparator, decimalSeparator, locale } = options\n\n const numeric = typeof value === 'number' ? value : Number(value)\n if (typeof value === 'string' && (value.trim() === '' || !Number.isFinite(numeric))) {\n return value\n }\n if (!Number.isFinite(numeric)) return String(value)\n\n if (locale) {\n return formatByLocale(numeric, locale, { precision, groupSeparator, decimalSeparator })\n }\n\n const fixed = precision === undefined ? String(numeric) : numeric.toFixed(precision)\n // `toFixed` не даёт экспоненциальной записи, а `String(число)` — может (1e21+).\n // В таком случае группировать нечего: возвращаем как есть.\n if (fixed.includes('e') || fixed.includes('E')) return fixed\n\n const negative = fixed.startsWith('-')\n const [intPart, fracPart] = (negative ? fixed.slice(1) : fixed).split('.')\n\n const separator = groupSeparator ?? DEFAULT_GROUP_SEPARATOR\n const grouped = separator\n ? intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator)\n : intPart\n\n return [\n negative ? '-' : '',\n grouped,\n fracPart ? `${decimalSeparator ?? DEFAULT_DECIMAL_SEPARATOR}${fracPart}` : '',\n ].join('')\n}\n\n/**\n * `formatToParts` вместо `format`: даёт заменить отдельные разделители, оставив\n * остальные правила локали (индийская группировка, знак минуса, порядок частей).\n */\nfunction formatByLocale(\n value: number,\n locale: string,\n options: Pick<GrStatisticFormatOptions, 'precision' | 'groupSeparator' | 'decimalSeparator'>,\n): string {\n const { precision, groupSeparator, decimalSeparator } = options\n // `Intl` принимает не больше 20 знаков и падает `RangeError` на большем,\n // тогда как ручная ветка через `toFixed` пережила бы до 100.\n const digits = precision === undefined ? undefined : Math.min(Math.max(precision, 0), 20)\n\n return new Intl.NumberFormat(locale, {\n useGrouping: true,\n minimumFractionDigits: digits,\n maximumFractionDigits: digits ?? 20,\n })\n .formatToParts(value)\n .map((part) => {\n if (part.type === 'group' && groupSeparator !== undefined) return groupSeparator\n if (part.type === 'decimal' && decimalSeparator !== undefined) return decimalSeparator\n return part.value\n })\n .join('')\n}\n","<script setup lang=\"ts\">\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { computed, markRaw, onBeforeUnmount, onMounted, ref, useSlots, watch, type Component } from 'vue'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { deltaTone, type GrDeltaPolarity } from '../GrDelta/deltaTone'\nimport { iconClass, iconTag } from '../shared/icon'\nimport GrSkeleton from '../GrSkeleton/GrSkeleton.vue'\n\nimport IconMinus from '~icons/lucide/minus'\nimport IconTrendingDown from '~icons/lucide/trending-down'\nimport IconTrendingUp from '~icons/lucide/trending-up'\n\nimport { countUpFrame } from './countUp'\nimport { formatStatisticValue } from './formatStatisticValue'\n\nimport {\n statisticAffixSizeBySize,\n statisticPlaceholderHeightBySize,\n statisticRootClass,\n statisticTitleClass,\n statisticTitleSizeBySize,\n statisticTrendClassByTrend,\n statisticTrendSizeBySize,\n statisticValueClass,\n type GrStatisticSize,\n type GrStatisticTone,\n type GrStatisticTrend,\n} from './grStatisticStyles'\n\nexport type {\n GrStatisticSize,\n GrStatisticTone,\n GrStatisticTrend,\n} from './grStatisticStyles'\nexport type { GrStatisticFormatOptions } from './formatStatisticValue'\n\n/**\n * Публичный GR-примитив «Statistic» — крупный числовой показатель с подписью,\n * префиксом/суффиксом и строкой динамики.\n *\n * Компонент презентационный: не грузит данные и не считает дельту, только\n * форматирует и подаёт. Форматирование — чистая функция `formatStatisticValue`.\n */\nexport interface GrStatisticProps {\n /** Значение показателя. Нечисловая строка выводится как есть. */\n value: number | string\n /** Подпись над значением. */\n title?: string\n /** Число знаков после запятой. */\n precision?: number\n /** Разделитель разрядов. Сильнее локали; без него и без локали — узкий пробел. */\n groupSeparator?: string\n /** Десятичный разделитель. Сильнее локали; без него и без локали — точка. */\n decimalSeparator?: string\n /**\n * BCP-47 локаль форматирования. Не задана — берётся из i18n-адаптера; нет и\n * адаптера — работают ручные разделители.\n */\n locale?: string\n /** Приписка перед значением (валюта, знак). */\n prefix?: string\n /** Приписка после значения (единица измерения, `%`). */\n suffix?: string\n /**\n * Иконка слева от блока: Vue-компонент либо класс иконки вашей UnoCSS-сборки\n * (`'i-lucide-users'` — тогда нужен ваш `presetIcons`, см. `docs/installation.md`).\n */\n icon?: string | Component\n size?: GrStatisticSize\n /** Тон значения; точечно перекрывается `--gr-statistic-value-color`. */\n tone?: GrStatisticTone\n /**\n * Что считать хорошим: тон выводится из знака самого значения. Для выручки\n * рост — успех, для себестоимости и оттока — наоборот. Явный `tone` сильнее:\n * выведенный тон — умолчание, а не диктат.\n */\n polarity?: GrDeltaPolarity\n /** Направление динамики — задаёт цвет и иконку строки под значением. */\n trend?: GrStatisticTrend\n /** Текст динамики (например `+12,5% к прошлой неделе`). */\n trendText?: string\n /** Состояние загрузки: вместо значения — плейсхолдер. */\n loading?: boolean\n /**\n * Перебирать числа при появлении и при смене значения. Нечисловое значение\n * ставится сразу, под `prefers-reduced-motion: reduce` — тоже.\n */\n animate?: boolean\n /**\n * Длительность перебора в миллисекундах. Не токеном: шкала `--gr-duration-*`\n * заканчивается на 300 мс и описывает смену состояния, а перебор чисел —\n * другой жанр, и его число живёт там же, где твин.\n */\n animateDuration?: number\n /** Свой корневой тег (`RouterLink`, `Link` от Inertia). Сильнее `href`. */\n as?: string | Component\n /** Показатель-ссылка: переход к деталям. */\n href?: string\n /** Показатель-кнопка: интерактивна вся плитка. */\n clickable?: boolean\n}\n\nexport interface GrStatisticEmits {\n (e: 'click', event: MouseEvent): void\n}\n\nconst props = withDefaults(\n defineProps<GrStatisticProps>(),\n {\n title: undefined,\n precision: undefined,\n // Дефолты живут в `formatStatisticValue`: иначе «пользователь задал пробел»\n // было бы неотличимо от «сработал дефолт», и локаль не смогла бы победить.\n groupSeparator: undefined,\n decimalSeparator: undefined,\n locale: undefined,\n prefix: undefined,\n suffix: undefined,\n icon: undefined,\n size: undefined,\n // Дефолт тона живёт в `resolvedTone`: с ним здесь «пользователь задал\n // neutral» было бы неотличимо от «сработал дефолт», и явный\n // `tone=\"neutral\"` не смог бы отменить `polarity`.\n tone: undefined,\n polarity: undefined,\n trend: undefined,\n trendText: undefined,\n loading: false,\n animate: false,\n animateDuration: 600,\n as: undefined,\n href: undefined,\n clickable: false,\n },\n)\n\nconst emit = defineEmits<GrStatisticEmits>()\n\nconst slots = useSlots()\n\nconst { t, locale } = useGranularityTranslations()\n\nconst resolvedLocale = computed(() => props.locale ?? locale.value)\n\n/**\n * Число текущего кадра перебора. `null` — перебора нет, показываем сам проп:\n * так значение остаётся конечным и на сервере, и до первого твина.\n */\nconst frameValue = ref<number | null>(null)\n\nconst formatted = computed(() => formatStatisticValue(frameValue.value ?? props.value, {\n precision: props.precision,\n groupSeparator: props.groupSeparator,\n decimalSeparator: props.decimalSeparator,\n locale: resolvedLocale.value,\n}))\n\n/** Конечное значение — то, что читает диктор, пока на экране идёт перебор. */\nconst finalFormatted = computed(() => formatStatisticValue(props.value, {\n precision: props.precision,\n groupSeparator: props.groupSeparator,\n decimalSeparator: props.decimalSeparator,\n locale: resolvedLocale.value,\n}))\n\nconst isCounting = computed(() => frameValue.value !== null)\n\nconst hasTitle = computed(() => Boolean(props.title || slots.title))\n\nconst isInteractive = computed(() => Boolean(props.as || props.href || props.clickable))\n\nconst rootTag = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n\n if (props.href)\n return 'a'\n\n return props.clickable ? 'button' : 'div'\n})\n\n/**\n * Компонент-ссылка (`Link` от Inertia, `RouterLink`) рендерит `<a>` сам, и без\n * `href` он ведёт в никуда. Строковый тег, кроме `a`, атрибут не понимает —\n * там он и гасится.\n */\nconst rootHref = computed(() => (\n typeof rootTag.value === 'string' && rootTag.value !== 'a' ? undefined : props.href\n))\n\nconst rootClass = computed(() => statisticRootClass({ interactive: isInteractive.value }))\n\nfunction toNumber(value: number | string): number | null {\n const numeric = typeof value === 'number' ? value : Number(value)\n return Number.isFinite(numeric) ? numeric : null\n}\n\nlet frameHandle: number | null = null\n\nfunction stopCounting(): void {\n if (frameHandle !== null) cancelAnimationFrame(frameHandle)\n frameHandle = null\n}\n\n/**\n * Перебор чисел ведёт JS, а глобальный кламп в `base.css` гасит только CSS —\n * значит уважать «уменьшить движение» обязан сам компонент (`docs/motion.md`).\n * Читается в момент старта, а не в теле `setup`: `matchMedia` на сервере нет, и\n * первый клиентский рендер разошёлся бы с серверным.\n */\nfunction prefersReducedMotion(): boolean {\n return typeof window !== 'undefined'\n && window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches === true\n}\n\nfunction runCountUp(from: number, to: number): void {\n stopCounting()\n\n const duration = props.animateDuration\n if (!(duration > 0) || from === to || prefersReducedMotion()) {\n frameValue.value = null\n return\n }\n\n const started = performance.now()\n frameValue.value = from\n\n const step = (now: number): void => {\n const elapsed = now - started\n const value = countUpFrame(from, to, elapsed, duration, props.precision)\n\n if (elapsed >= duration) {\n // Конец перебора снимает и подмену значения, и подмену для диктора.\n frameValue.value = null\n frameHandle = null\n return\n }\n\n frameValue.value = value\n frameHandle = requestAnimationFrame(step)\n }\n\n frameHandle = requestAnimationFrame(step)\n}\n\n/** Перебирать можно только числа: «2 ч 15 мин» и «—» ставятся сразу. */\nfunction startIfNumeric(from: number | string, to: number | string): void {\n if (!props.animate || props.loading) {\n stopCounting()\n frameValue.value = null\n return\n }\n\n const target = toNumber(to)\n const source = toNumber(from)\n\n if (target === null || source === null) {\n stopCounting()\n frameValue.value = null\n return\n }\n\n runCountUp(source, target)\n}\n\n// Появление плитки считается переходом от нуля: ради этого эффекта проп и нужен.\nonMounted(() => startIfNumeric(0, props.value))\n\nwatch(() => props.value, (next, prev) => startIfNumeric(prev, next))\n\nonBeforeUnmount(stopCounting)\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrStatistic' })\nconst resolvedPolarity = useGrComponentProp('GrStatistic', 'polarity', () => props.polarity, 'none')\n\n/**\n * Тон значения: явный проп → выведенный из знака → нейтральный.\n *\n * Отдельной ветки «полярность не задана» нет намеренно: `deltaTone(x, 'none')`\n * нейтрален при любом значении, то есть `'none'` и есть прежнее поведение.\n *\n * Знак берётся у самого пропа, а не у кадра перебора: `frameValue` стартует с\n * нуля, и цвет плитки мигал бы нейтральным на каждой анимации.\n */\nconst resolvedTone = computed<GrStatisticTone>(() => {\n if (props.tone !== undefined) return props.tone\n\n const numeric = toNumber(props.value)\n\n // «2 ч 15 мин» и «—» знака не имеют — красить нечем.\n return numeric === null ? 'neutral' : deltaTone(numeric, resolvedPolarity.value)\n})\n\nconst trendIconByTrend: Record<GrStatisticTrend, Component> = {\n up: IconTrendingUp,\n down: IconTrendingDown,\n flat: IconMinus,\n}\n\n// Иконка направления `aria-hidden`, а «+12,5 %» само по себе рост от падения не\n// отличает: направление доносит скрытая подпись.\nconst trendLabel = computed(() => {\n if (!props.trend) return undefined\n\n const labels = {\n up: () => t('gr.statistic.trendUp', 'Increase'),\n down: () => t('gr.statistic.trendDown', 'Decrease'),\n flat: () => t('gr.statistic.trendFlat', 'No change'),\n }\n\n return labels[props.trend]()\n})\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-statistic\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootHref\"\n :class=\"rootClass\"\n @click=\"emit('click', $event)\"\n >\n <span\n v-if=\"icon || $slots.icon\"\n data-gr-statistic-icon\n class=\"mt-0.5 inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-[var(--gr-radius-lg)] bg-[var(--gr-muted)] text-[var(--gr-muted-fg)]\"\n >\n <slot name=\"icon\">\n <component :is=\"iconTag(icon)\" class=\"block h-4 w-4\" :class=\"iconClass(icon)\" aria-hidden=\"true\" />\n </slot>\n </span>\n\n <div class=\"min-w-0\">\n <!--\n Подпись и значение — пара «термин — значение», а не два соседних блока.\n `<dl>` появляется только вместе с подписью: список определений без `<dt>`\n — та же бессвязность, только с претензией на семантику. Поля обнуляются\n руками: preflight пакета сбрасывает их лишь у `body`.\n -->\n <component :is=\"hasTitle ? 'dl' : 'div'\" class=\"m-0\">\n <dt\n v-if=\"hasTitle\"\n data-gr-statistic-title\n :class=\"[statisticTitleClass, statisticTitleSizeBySize[resolvedSize]]\"\n >\n <slot name=\"title\">\n {{ title }}\n </slot>\n </dt>\n\n <!-- Плейсхолдер загрузки повторяет высоту строки значения, чтобы блок не прыгал. -->\n <component\n :is=\"hasTitle ? 'dd' : 'div'\"\n v-if=\"loading\"\n data-gr-statistic-placeholder\n data-testid=\"gr-statistic-placeholder\"\n class=\"m-0 mt-1\"\n role=\"status\"\n aria-busy=\"true\"\n >\n <GrSkeleton\n width=\"6rem\"\n :height=\"statisticPlaceholderHeightBySize[resolvedSize]\"\n rounded=\"var(--gr-radius-md)\"\n />\n <span class=\"sr-only\">{{ t('gr.loading.defaultText', 'Loading...') }}</span>\n </component>\n\n <component\n :is=\"hasTitle ? 'dd' : 'div'\"\n v-else\n data-gr-statistic-value\n data-testid=\"gr-statistic-value\"\n class=\"m-0 mt-0.5 flex items-baseline gap-1\"\n >\n <span\n v-if=\"prefix || $slots.prefix\"\n data-gr-statistic-prefix\n class=\"text-[var(--gr-muted-fg)]\"\n :class=\"statisticAffixSizeBySize[resolvedSize]\"\n >\n <slot name=\"prefix\">{{ prefix }}</slot>\n </span>\n\n <span\n data-gr-statistic-number\n :class=\"statisticValueClass({ size: resolvedSize, tone: resolvedTone })\"\n :aria-hidden=\"isCounting ? 'true' : undefined\"\n >\n <slot>{{ formatted }}</slot>\n </span>\n\n <!--\n Пока идёт перебор, на экране промежуточное число. Диктору отдаётся\n конечное: «1 284» глазами и «743» в ушах — не шум, а неверные данные.\n -->\n <span v-if=\"isCounting\" data-gr-statistic-final class=\"sr-only\">{{ finalFormatted }}</span>\n\n <span\n v-if=\"suffix || $slots.suffix\"\n data-gr-statistic-suffix\n class=\"text-[var(--gr-muted-fg)]\"\n :class=\"statisticAffixSizeBySize[resolvedSize]\"\n >\n <slot name=\"suffix\">{{ suffix }}</slot>\n </span>\n </component>\n </component>\n\n <div\n v-if=\"trend || trendText || $slots.trend\"\n data-gr-statistic-trend\n data-testid=\"gr-statistic-trend\"\n class=\"mt-1 inline-flex items-center gap-1\"\n :class=\"[statisticTrendSizeBySize[resolvedSize], statisticTrendClassByTrend[trend ?? 'flat']]\"\n >\n <span v-if=\"trendLabel\" data-gr-statistic-trend-label class=\"sr-only\">{{ trendLabel }}</span>\n\n <slot name=\"trend\">\n <component\n :is=\"trendIconByTrend[trend]\"\n v-if=\"trend\"\n class=\"block h-3.5 w-3.5\"\n aria-hidden=\"true\"\n />\n <span>{{ trendText }}</span>\n </slot>\n </div>\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { computed, markRaw, onBeforeUnmount, onMounted, ref, useSlots, watch, type Component } from 'vue'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { deltaTone, type GrDeltaPolarity } from '../GrDelta/deltaTone'\nimport { iconClass, iconTag } from '../shared/icon'\nimport GrSkeleton from '../GrSkeleton/GrSkeleton.vue'\n\nimport IconMinus from '~icons/lucide/minus'\nimport IconTrendingDown from '~icons/lucide/trending-down'\nimport IconTrendingUp from '~icons/lucide/trending-up'\n\nimport { countUpFrame } from './countUp'\nimport { formatStatisticValue } from './formatStatisticValue'\n\nimport {\n statisticAffixSizeBySize,\n statisticPlaceholderHeightBySize,\n statisticRootClass,\n statisticTitleClass,\n statisticTitleSizeBySize,\n statisticTrendClassByTrend,\n statisticTrendSizeBySize,\n statisticValueClass,\n type GrStatisticSize,\n type GrStatisticTone,\n type GrStatisticTrend,\n} from './grStatisticStyles'\n\nexport type {\n GrStatisticSize,\n GrStatisticTone,\n GrStatisticTrend,\n} from './grStatisticStyles'\nexport type { GrStatisticFormatOptions } from './formatStatisticValue'\n\n/**\n * Публичный GR-примитив «Statistic» — крупный числовой показатель с подписью,\n * префиксом/суффиксом и строкой динамики.\n *\n * Компонент презентационный: не грузит данные и не считает дельту, только\n * форматирует и подаёт. Форматирование — чистая функция `formatStatisticValue`.\n */\nexport interface GrStatisticProps {\n /** Значение показателя. Нечисловая строка выводится как есть. */\n value: number | string\n /** Подпись над значением. */\n title?: string\n /** Число знаков после запятой. */\n precision?: number\n /** Разделитель разрядов. Сильнее локали; без него и без локали — узкий пробел. */\n groupSeparator?: string\n /** Десятичный разделитель. Сильнее локали; без него и без локали — точка. */\n decimalSeparator?: string\n /**\n * BCP-47 локаль форматирования. Не задана — берётся из i18n-адаптера; нет и\n * адаптера — работают ручные разделители.\n */\n locale?: string\n /** Приписка перед значением (валюта, знак). */\n prefix?: string\n /** Приписка после значения (единица измерения, `%`). */\n suffix?: string\n /**\n * Иконка слева от блока: Vue-компонент либо класс иконки вашей UnoCSS-сборки\n * (`'i-lucide-users'` — тогда нужен ваш `presetIcons`, см. `docs/installation.md`).\n */\n icon?: string | Component\n size?: GrStatisticSize\n /** Тон значения; точечно перекрывается `--gr-statistic-value-color`. */\n tone?: GrStatisticTone\n /**\n * Что считать хорошим: тон выводится из знака самого значения. Для выручки\n * рост — успех, для себестоимости и оттока — наоборот. Явный `tone` сильнее:\n * выведенный тон — умолчание, а не диктат.\n */\n polarity?: GrDeltaPolarity\n /** Направление динамики — задаёт цвет и иконку строки под значением. */\n trend?: GrStatisticTrend\n /** Текст динамики (например `+12,5% к прошлой неделе`). */\n trendText?: string\n /** Состояние загрузки: вместо значения — плейсхолдер. */\n loading?: boolean\n /**\n * Перебирать числа при появлении и при смене значения. Нечисловое значение\n * ставится сразу, под `prefers-reduced-motion: reduce` — тоже.\n */\n animate?: boolean\n /**\n * Длительность перебора в миллисекундах. Не токеном: шкала `--gr-duration-*`\n * заканчивается на 300 мс и описывает смену состояния, а перебор чисел —\n * другой жанр, и его число живёт там же, где твин.\n */\n animateDuration?: number\n /** Свой корневой тег (`RouterLink`, `Link` от Inertia). Сильнее `href`. */\n as?: string | Component\n /** Показатель-ссылка: переход к деталям. */\n href?: string\n /** Показатель-кнопка: интерактивна вся плитка. */\n clickable?: boolean\n}\n\nexport interface GrStatisticEmits {\n (e: 'click', event: MouseEvent): void\n}\n\nconst props = withDefaults(\n defineProps<GrStatisticProps>(),\n {\n title: undefined,\n precision: undefined,\n // Дефолты живут в `formatStatisticValue`: иначе «пользователь задал пробел»\n // было бы неотличимо от «сработал дефолт», и локаль не смогла бы победить.\n groupSeparator: undefined,\n decimalSeparator: undefined,\n locale: undefined,\n prefix: undefined,\n suffix: undefined,\n icon: undefined,\n size: undefined,\n // Дефолт тона живёт в `resolvedTone`: с ним здесь «пользователь задал\n // neutral» было бы неотличимо от «сработал дефолт», и явный\n // `tone=\"neutral\"` не смог бы отменить `polarity`.\n tone: undefined,\n polarity: undefined,\n trend: undefined,\n trendText: undefined,\n loading: false,\n animate: false,\n animateDuration: 600,\n as: undefined,\n href: undefined,\n clickable: false,\n },\n)\n\nconst emit = defineEmits<GrStatisticEmits>()\n\nconst slots = useSlots()\n\nconst { t, locale } = useGranularityTranslations()\n\nconst resolvedLocale = computed(() => props.locale ?? locale.value)\n\n/**\n * Число текущего кадра перебора. `null` — перебора нет, показываем сам проп:\n * так значение остаётся конечным и на сервере, и до первого твина.\n */\nconst frameValue = ref<number | null>(null)\n\nconst formatted = computed(() => formatStatisticValue(frameValue.value ?? props.value, {\n precision: props.precision,\n groupSeparator: props.groupSeparator,\n decimalSeparator: props.decimalSeparator,\n locale: resolvedLocale.value,\n}))\n\n/** Конечное значение — то, что читает диктор, пока на экране идёт перебор. */\nconst finalFormatted = computed(() => formatStatisticValue(props.value, {\n precision: props.precision,\n groupSeparator: props.groupSeparator,\n decimalSeparator: props.decimalSeparator,\n locale: resolvedLocale.value,\n}))\n\nconst isCounting = computed(() => frameValue.value !== null)\n\nconst hasTitle = computed(() => Boolean(props.title || slots.title))\n\nconst isInteractive = computed(() => Boolean(props.as || props.href || props.clickable))\n\nconst rootTag = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n\n if (props.href)\n return 'a'\n\n return props.clickable ? 'button' : 'div'\n})\n\n/**\n * Компонент-ссылка (`Link` от Inertia, `RouterLink`) рендерит `<a>` сам, и без\n * `href` он ведёт в никуда. Строковый тег, кроме `a`, атрибут не понимает —\n * там он и гасится.\n */\nconst rootHref = computed(() => (\n typeof rootTag.value === 'string' && rootTag.value !== 'a' ? undefined : props.href\n))\n\nconst rootClass = computed(() => statisticRootClass({ interactive: isInteractive.value }))\n\nfunction toNumber(value: number | string): number | null {\n const numeric = typeof value === 'number' ? value : Number(value)\n return Number.isFinite(numeric) ? numeric : null\n}\n\nlet frameHandle: number | null = null\n\nfunction stopCounting(): void {\n if (frameHandle !== null) cancelAnimationFrame(frameHandle)\n frameHandle = null\n}\n\n/**\n * Перебор чисел ведёт JS, а глобальный кламп в `base.css` гасит только CSS —\n * значит уважать «уменьшить движение» обязан сам компонент (`docs/motion.md`).\n * Читается в момент старта, а не в теле `setup`: `matchMedia` на сервере нет, и\n * первый клиентский рендер разошёлся бы с серверным.\n */\nfunction prefersReducedMotion(): boolean {\n return typeof window !== 'undefined'\n && window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches === true\n}\n\nfunction runCountUp(from: number, to: number): void {\n stopCounting()\n\n const duration = props.animateDuration\n if (!(duration > 0) || from === to || prefersReducedMotion()) {\n frameValue.value = null\n return\n }\n\n const started = performance.now()\n frameValue.value = from\n\n const step = (now: number): void => {\n const elapsed = now - started\n const value = countUpFrame(from, to, elapsed, duration, props.precision)\n\n if (elapsed >= duration) {\n // Конец перебора снимает и подмену значения, и подмену для диктора.\n frameValue.value = null\n frameHandle = null\n return\n }\n\n frameValue.value = value\n frameHandle = requestAnimationFrame(step)\n }\n\n frameHandle = requestAnimationFrame(step)\n}\n\n/** Перебирать можно только числа: «2 ч 15 мин» и «—» ставятся сразу. */\nfunction startIfNumeric(from: number | string, to: number | string): void {\n if (!props.animate || props.loading) {\n stopCounting()\n frameValue.value = null\n return\n }\n\n const target = toNumber(to)\n const source = toNumber(from)\n\n if (target === null || source === null) {\n stopCounting()\n frameValue.value = null\n return\n }\n\n runCountUp(source, target)\n}\n\n// Появление плитки считается переходом от нуля: ради этого эффекта проп и нужен.\nonMounted(() => startIfNumeric(0, props.value))\n\nwatch(() => props.value, (next, prev) => startIfNumeric(prev, next))\n\nonBeforeUnmount(stopCounting)\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrStatistic' })\nconst resolvedPolarity = useGrComponentProp('GrStatistic', 'polarity', () => props.polarity, 'none')\n\n/**\n * Тон значения: явный проп → выведенный из знака → нейтральный.\n *\n * Отдельной ветки «полярность не задана» нет намеренно: `deltaTone(x, 'none')`\n * нейтрален при любом значении, то есть `'none'` и есть прежнее поведение.\n *\n * Знак берётся у самого пропа, а не у кадра перебора: `frameValue` стартует с\n * нуля, и цвет плитки мигал бы нейтральным на каждой анимации.\n */\nconst resolvedTone = computed<GrStatisticTone>(() => {\n if (props.tone !== undefined) return props.tone\n\n const numeric = toNumber(props.value)\n\n // «2 ч 15 мин» и «—» знака не имеют — красить нечем.\n return numeric === null ? 'neutral' : deltaTone(numeric, resolvedPolarity.value)\n})\n\nconst trendIconByTrend: Record<GrStatisticTrend, Component> = {\n up: IconTrendingUp,\n down: IconTrendingDown,\n flat: IconMinus,\n}\n\n// Иконка направления `aria-hidden`, а «+12,5 %» само по себе рост от падения не\n// отличает: направление доносит скрытая подпись.\nconst trendLabel = computed(() => {\n if (!props.trend) return undefined\n\n const labels = {\n up: () => t('gr.statistic.trendUp', 'Increase'),\n down: () => t('gr.statistic.trendDown', 'Decrease'),\n flat: () => t('gr.statistic.trendFlat', 'No change'),\n }\n\n return labels[props.trend]()\n})\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-statistic\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootHref\"\n :class=\"rootClass\"\n @click=\"emit('click', $event)\"\n >\n <span\n v-if=\"icon || $slots.icon\"\n data-gr-statistic-icon\n class=\"mt-0.5 inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-[var(--gr-radius-lg)] bg-[var(--gr-muted)] text-[var(--gr-muted-fg)]\"\n >\n <slot name=\"icon\">\n <component :is=\"iconTag(icon)\" class=\"block h-4 w-4\" :class=\"iconClass(icon)\" aria-hidden=\"true\" />\n </slot>\n </span>\n\n <div class=\"min-w-0\">\n <!--\n Подпись и значение — пара «термин — значение», а не два соседних блока.\n `<dl>` появляется только вместе с подписью: список определений без `<dt>`\n — та же бессвязность, только с претензией на семантику. Поля обнуляются\n руками: preflight пакета сбрасывает их лишь у `body`.\n -->\n <component :is=\"hasTitle ? 'dl' : 'div'\" class=\"m-0\">\n <dt\n v-if=\"hasTitle\"\n data-gr-statistic-title\n :class=\"[statisticTitleClass, statisticTitleSizeBySize[resolvedSize]]\"\n >\n <slot name=\"title\">\n {{ title }}\n </slot>\n </dt>\n\n <!-- Плейсхолдер загрузки повторяет высоту строки значения, чтобы блок не прыгал. -->\n <component\n :is=\"hasTitle ? 'dd' : 'div'\"\n v-if=\"loading\"\n data-gr-statistic-placeholder\n data-testid=\"gr-statistic-placeholder\"\n class=\"m-0 mt-1\"\n role=\"status\"\n aria-busy=\"true\"\n >\n <GrSkeleton\n width=\"6rem\"\n :height=\"statisticPlaceholderHeightBySize[resolvedSize]\"\n rounded=\"var(--gr-radius-md)\"\n />\n <span class=\"sr-only\">{{ t('gr.loading.defaultText', 'Loading...') }}</span>\n </component>\n\n <component\n :is=\"hasTitle ? 'dd' : 'div'\"\n v-else\n data-gr-statistic-value\n data-testid=\"gr-statistic-value\"\n class=\"m-0 mt-0.5 flex items-baseline gap-1\"\n >\n <span\n v-if=\"prefix || $slots.prefix\"\n data-gr-statistic-prefix\n class=\"text-[var(--gr-muted-fg)]\"\n :class=\"statisticAffixSizeBySize[resolvedSize]\"\n >\n <slot name=\"prefix\">{{ prefix }}</slot>\n </span>\n\n <span\n data-gr-statistic-number\n :class=\"statisticValueClass({ size: resolvedSize, tone: resolvedTone })\"\n :aria-hidden=\"isCounting ? 'true' : undefined\"\n >\n <slot>{{ formatted }}</slot>\n </span>\n\n <!--\n Пока идёт перебор, на экране промежуточное число. Диктору отдаётся\n конечное: «1 284» глазами и «743» в ушах — не шум, а неверные данные.\n -->\n <span v-if=\"isCounting\" data-gr-statistic-final class=\"sr-only\">{{ finalFormatted }}</span>\n\n <span\n v-if=\"suffix || $slots.suffix\"\n data-gr-statistic-suffix\n class=\"text-[var(--gr-muted-fg)]\"\n :class=\"statisticAffixSizeBySize[resolvedSize]\"\n >\n <slot name=\"suffix\">{{ suffix }}</slot>\n </span>\n </component>\n </component>\n\n <div\n v-if=\"trend || trendText || $slots.trend\"\n data-gr-statistic-trend\n data-testid=\"gr-statistic-trend\"\n class=\"mt-1 inline-flex items-center gap-1\"\n :class=\"[statisticTrendSizeBySize[resolvedSize], statisticTrendClassByTrend[trend ?? 'flat']]\"\n >\n <span v-if=\"trendLabel\" data-gr-statistic-trend-label class=\"sr-only\">{{ trendLabel }}</span>\n\n <slot name=\"trend\">\n <component\n :is=\"trendIconByTrend[trend]\"\n v-if=\"trend\"\n class=\"block h-3.5 w-3.5\"\n aria-hidden=\"true\"\n />\n <span>{{ trendText }}</span>\n </slot>\n </div>\n </div>\n </component>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as formatStatisticValue, t as GrStatistic_default } from "./chunks/GrStatistic-
|
|
1
|
+
import { n as formatStatisticValue, t as GrStatistic_default } from "./chunks/GrStatistic-C7wQECeS.js";
|
|
2
2
|
import { n as grStatisticSafelist, t as grStatisticConfig } from "../../chunks/config-Be9k9bOf.js";
|
|
3
3
|
export { GrStatistic_default as GrStatistic, GrStatistic_default as default, formatStatisticValue, grStatisticConfig, grStatisticSafelist };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { n as GrTabPanels_default, t as GrTabPanel_default } from "./chunks/GrTabPanels-AJt1w1XC.js";
|
|
2
|
-
import { t as grTabPanelsConfig } from "../../chunks/config-
|
|
2
|
+
import { t as grTabPanelsConfig } from "../../chunks/config-eXB87DOi.js";
|
|
3
3
|
export { GrTabPanel_default as GrTabPanel, GrTabPanels_default as GrTabPanels, GrTabPanels_default as default, grTabPanelsConfig };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-
|
|
1
|
+
import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-CQKhl5C_.js";
|
|
2
2
|
export { GRANULARITY_PROVIDER_ID, createGranularityProvider, granularityProvider as default, granularityProvider, granularityComponentConfigs, granularityDefaultThemes, granularityThemeNames };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-
|
|
1
|
+
import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-CQKhl5C_.js";
|
|
2
2
|
export { GRANULARITY_PROVIDER_ID, createGranularityProvider, granularityProvider as default, granularityProvider, granularityComponentConfigs, granularityDefaultThemes, granularityThemeNames };
|
package/dist/i18n/all.js
CHANGED
package/dist/i18n/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { t as GRANULARITY_I18N_KEY } from "../chunks/adapter-CAOxmn2G.js";
|
|
2
|
-
import { i as GRANULARITY_I18N_BLOCK, n as ru, r as en, t as es } from "../chunks/es-
|
|
2
|
+
import { i as GRANULARITY_I18N_BLOCK, n as ru, r as en, t as es } from "../chunks/es-DdJsxlUr.js";
|
|
3
3
|
export { GRANULARITY_I18N_BLOCK, GRANULARITY_I18N_KEY, en, es, ru };
|
package/dist/index.js
CHANGED
|
@@ -50,8 +50,8 @@ import "./components/GrCheckbox/index.js";
|
|
|
50
50
|
import { t as GrCheckboxGroup_default } from "./components/GrCheckboxGroup/chunks/GrCheckboxGroup-BOwrVcFr.js";
|
|
51
51
|
import { t as grCheckboxGroupConfig } from "./chunks/config-BuGlNPE9.js";
|
|
52
52
|
import { useAnnouncer } from "./composables/useAnnouncer.js";
|
|
53
|
-
import { t as GrCodeBlock_default } from "./components/GrCodeBlock/chunks/GrCodeBlock-
|
|
54
|
-
import { n as grCodeBlockSafelist, t as grCodeBlockConfig } from "./chunks/config-
|
|
53
|
+
import { t as GrCodeBlock_default } from "./components/GrCodeBlock/chunks/GrCodeBlock-BmXCLgLS.js";
|
|
54
|
+
import { n as grCodeBlockSafelist, t as grCodeBlockConfig } from "./chunks/config-B_qi4Fma.js";
|
|
55
55
|
import { n as grCollapseSafelist, t as grCollapseConfig } from "./chunks/config-DU2DNSRx.js";
|
|
56
56
|
import { n as GrCollapse_default, t as GrCollapseItem_default } from "./components/GrCollapse/chunks/GrCollapse-C1rCfbc0.js";
|
|
57
57
|
import { n as grIconSafelist, t as grIconConfig } from "./chunks/config-Cp0DE0GH.js";
|
|
@@ -78,10 +78,11 @@ import { t as useDragSort } from "./chunks/useDragSort-0l47h4yb.js";
|
|
|
78
78
|
import { useRovingFocus } from "./composables/useRovingFocus.js";
|
|
79
79
|
import { t as GrDataTable_default } from "./components/GrDataTable/chunks/GrDataTable-B5MmZFUg.js";
|
|
80
80
|
import { n as grDataTableSafelist, t as grDataTableConfig } from "./chunks/config-BC8d_smz.js";
|
|
81
|
-
import { t as GrDelta_default } from "./components/GrDelta/chunks/GrDelta-
|
|
81
|
+
import { t as GrDelta_default } from "./components/GrDelta/chunks/GrDelta-DFvxNpmN.js";
|
|
82
|
+
import { n as deltaTone, t as deltaDirection } from "./chunks/deltaTone-B5OoS1vo.js";
|
|
82
83
|
import { n as grDeltaSafelist, t as grDeltaConfig } from "./chunks/config-DBQQT-WP.js";
|
|
83
|
-
import { n as grDescriptionListSafelist, t as grDescriptionListConfig } from "./chunks/config-
|
|
84
|
-
import { t as GrDescriptionList_default } from "./components/GrDescriptionList/chunks/GrDescriptionList-
|
|
84
|
+
import { n as grDescriptionListSafelist, t as grDescriptionListConfig } from "./chunks/config-DCwQBMmJ.js";
|
|
85
|
+
import { t as GrDescriptionList_default } from "./components/GrDescriptionList/chunks/GrDescriptionList-2zFXzX83.js";
|
|
85
86
|
import { t as grDialogSafelist } from "./chunks/safelist-CkF4v7DC.js";
|
|
86
87
|
import "./components/GrDialog/index.js";
|
|
87
88
|
import { n as useGrFormContext } from "./chunks/context-Bfrgsluh.js";
|
|
@@ -98,11 +99,11 @@ import { t as GrDrawer_default } from "./components/GrDrawer/chunks/GrDrawer-C3z
|
|
|
98
99
|
import { t as GrDropdown_default } from "./components/GrDropdown/chunks/GrDropdown-BSfFOcDx.js";
|
|
99
100
|
import { n as grDropdownSafelist, t as grDropdownConfig } from "./chunks/config-BViooYNv.js";
|
|
100
101
|
import "./components/GrDropdown/index.js";
|
|
101
|
-
import { n as grDropdownMenuSafelist, t as grDropdownMenuConfig } from "./chunks/config-
|
|
102
|
-
import { a as GrDropdownMenuItem_default, c as GrDropdownMenuDivider_default, i as GrDropdownMenuList_default, n as GrDropdownMenuColumn_default, o as GrDropdownMenuGroup_default, r as GrDropdownMenu_default, s as GrDropdownMenuHeader_default, t as GrDropdownMenuColumns_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenu-
|
|
102
|
+
import { n as grDropdownMenuSafelist, t as grDropdownMenuConfig } from "./chunks/config-C5mO5DYZ.js";
|
|
103
|
+
import { a as GrDropdownMenuItem_default, c as GrDropdownMenuDivider_default, i as GrDropdownMenuList_default, n as GrDropdownMenuColumn_default, o as GrDropdownMenuGroup_default, r as GrDropdownMenu_default, s as GrDropdownMenuHeader_default, t as GrDropdownMenuColumns_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenu-DyS6dWDp.js";
|
|
103
104
|
import { t as GrEmptyState_default } from "./components/GrEmptyState/chunks/GrEmptyState-CS9do8eM.js";
|
|
104
105
|
import { n as grEmptyStateSafelist, t as grEmptyStateConfig } from "./chunks/config-vSji8w90.js";
|
|
105
|
-
import { t as GrFilePreview_default } from "./components/GrFilePreview/chunks/GrFilePreview-
|
|
106
|
+
import { n as fileKindOf, r as isPreviewableKind, t as GrFilePreview_default } from "./components/GrFilePreview/chunks/GrFilePreview-D0Bt-0nn.js";
|
|
106
107
|
import { n as grFilePreviewSafelist, t as grFilePreviewConfig } from "./chunks/config-QJ54_fcM.js";
|
|
107
108
|
import { t as GrProgressBar_default } from "./components/GrProgressBar/chunks/GrProgressBar-hszUOC8f.js";
|
|
108
109
|
import { n as GrUploadAbortError, r as GrUploadHttpError, t as GrFileUpload_default } from "./components/GrFileUpload/chunks/GrFileUpload-D3-vC-ap.js";
|
|
@@ -121,12 +122,15 @@ import { n as grInputSafelist, t as grInputConfig } from "./chunks/config-DpeQch
|
|
|
121
122
|
import "./components/GrInput/index.js";
|
|
122
123
|
import { n as grInputTagSafelist, t as grInputTagConfig } from "./chunks/config-BN4sXYXn.js";
|
|
123
124
|
import { t as GrInputTag_default } from "./components/GrInputTag/chunks/GrInputTag-C7QVPijj.js";
|
|
125
|
+
import { t as GrTree_default } from "./components/GrTree/chunks/GrTree-BvOeQ3xJ.js";
|
|
126
|
+
import { t as GrJsonViewer_default } from "./components/GrJsonViewer/chunks/GrJsonViewer-DFUppRNb.js";
|
|
127
|
+
import { n as grJsonViewerSafelist, t as grJsonViewerConfig } from "./chunks/config-CIcynHGr.js";
|
|
124
128
|
import { n as grKbdSafelist, t as grKbdConfig } from "./chunks/config-DA6SnEoy.js";
|
|
125
129
|
import "./components/GrKbd/index.js";
|
|
126
130
|
import { n as grLinkSafelist, t as grLinkConfig } from "./chunks/config-Cl4ST6Qd.js";
|
|
127
131
|
import "./components/GrLink/index.js";
|
|
128
|
-
import { n as grListSafelist, t as grListConfig } from "./chunks/config-
|
|
129
|
-
import { n as GrList_default, t as GrListItem_default } from "./components/GrList/chunks/GrList-
|
|
132
|
+
import { n as grListSafelist, t as grListConfig } from "./chunks/config-CKULiuvc.js";
|
|
133
|
+
import { n as GrList_default, t as GrListItem_default } from "./components/GrList/chunks/GrList-BRYhpqIe.js";
|
|
130
134
|
import { n as grLoadingSafelist, t as grLoadingConfig } from "./chunks/config-CjnbevbD.js";
|
|
131
135
|
import "./components/GrLoading/index.js";
|
|
132
136
|
import { n as grModalSafelist, t as grModalConfig } from "./chunks/config-BtXRpAtq.js";
|
|
@@ -147,12 +151,12 @@ import { n as grProgressCircleSafelist, t as grProgressCircleConfig } from "./ch
|
|
|
147
151
|
import { t as grPromptDialogConfig } from "./chunks/config-C0Ea9ePP.js";
|
|
148
152
|
import "./components/GrPromptDialog/index.js";
|
|
149
153
|
import { t as GrRadio_default } from "./components/GrRadio/chunks/GrRadio-BdhknbO8.js";
|
|
150
|
-
import { n as grRadioSafelist, t as grRadioConfig } from "./chunks/config-
|
|
154
|
+
import { n as grRadioSafelist, t as grRadioConfig } from "./chunks/config-BTCOJO5z2.js";
|
|
151
155
|
import "./components/GrRadio/index.js";
|
|
152
156
|
import { t as GrRadioGroup_default } from "./components/GrRadioGroup/chunks/GrRadioGroup-BVmjKXcv.js";
|
|
153
|
-
import { t as grRadioGroupConfig } from "./chunks/config-
|
|
154
|
-
import { n as grRatingSafelist, t as grRatingConfig } from "./chunks/config-Baj7Wvx
|
|
155
|
-
import { t as GrRating_default } from "./components/GrRating/chunks/GrRating-
|
|
157
|
+
import { t as grRadioGroupConfig } from "./chunks/config-QaIc_gRa.js";
|
|
158
|
+
import { n as grRatingSafelist, t as grRatingConfig } from "./chunks/config-Baj7Wvx-.js";
|
|
159
|
+
import { t as GrRating_default } from "./components/GrRating/chunks/GrRating-BSEtaibx.js";
|
|
156
160
|
import { n as GrFormErrorBanner_default, r as GrUploadErrorBanner_default, t as useResponseError } from "./components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-CgfAwlg3.js";
|
|
157
161
|
import { n as grSegmentedSafelist, t as grSegmentedConfig } from "./chunks/config-BEVBsvni2.js";
|
|
158
162
|
import { t as GrSegmented_default } from "./components/GrSegmented/chunks/GrSegmented-D1mjxF_O.js";
|
|
@@ -168,14 +172,14 @@ import { n as grSortableListSafelist, t as grSortableListConfig } from "./chunks
|
|
|
168
172
|
import { t as GrSortableList_default } from "./components/GrSortableList/chunks/GrSortableList-DPjxilmN.js";
|
|
169
173
|
import { n as grSplitterSafelist, t as grSplitterConfig } from "./chunks/config-BE6n20np.js";
|
|
170
174
|
import { n as sizeFromPointer, t as GrSplitter_default } from "./components/GrSplitter/chunks/GrSplitter-B9_JrT7q.js";
|
|
171
|
-
import { n as formatStatisticValue, t as GrStatistic_default } from "./components/GrStatistic/chunks/GrStatistic-
|
|
175
|
+
import { n as formatStatisticValue, t as GrStatistic_default } from "./components/GrStatistic/chunks/GrStatistic-C7wQECeS.js";
|
|
172
176
|
import { n as grStatisticSafelist, t as grStatisticConfig } from "./chunks/config-Be9k9bOf.js";
|
|
173
177
|
import { n as grSwitchSafelist, t as grSwitchConfig } from "./chunks/config-BoNR7_PD2.js";
|
|
174
178
|
import { t as GrSwitch_default } from "./components/GrSwitch/chunks/GrSwitch-x_vQQ6ao.js";
|
|
175
179
|
import { n as grTableSafelist, t as grTableConfig } from "./chunks/config-WTNhdh6T.js";
|
|
176
180
|
import "./components/GrTable/index.js";
|
|
177
181
|
import { n as GrTabPanels_default, t as GrTabPanel_default } from "./components/GrTabPanels/chunks/GrTabPanels-AJt1w1XC.js";
|
|
178
|
-
import { t as grTabPanelsConfig } from "./chunks/config-
|
|
182
|
+
import { t as grTabPanelsConfig } from "./chunks/config-eXB87DOi.js";
|
|
179
183
|
import { n as grTabsSafelist, t as grTabsConfig } from "./chunks/config-DWN4x6_e.js";
|
|
180
184
|
import { t as GrTabs_default } from "./components/GrTabs/chunks/GrTabs-CBHZkOFY.js";
|
|
181
185
|
import { n as grTextareaSafelist, t as grTextareaConfig } from "./chunks/config-BDfTXHo1.js";
|
|
@@ -187,11 +191,10 @@ import { n as grToasterSafelist, t as grToasterConfig } from "./chunks/config-Sc
|
|
|
187
191
|
import { t as GrToaster_default } from "./components/GrToaster/chunks/GrToaster-DJUzx3sR.js";
|
|
188
192
|
import { n as grTooltipSafelist, t as grTooltipConfig } from "./chunks/config-CN2ULSQL.js";
|
|
189
193
|
import { t as GrTooltip_default } from "./components/GrTooltip/chunks/GrTooltip-B6AwE_UX.js";
|
|
190
|
-
import { t as GrTree_default } from "./components/GrTree/chunks/GrTree-BvOeQ3xJ.js";
|
|
191
194
|
import { n as grTreeSafelist, t as grTreeConfig } from "./chunks/config-CDat1wXf.js";
|
|
192
195
|
import { n as grTreeSelectSafelist, t as grTreeSelectConfig } from "./chunks/config-DCFvmHEv.js";
|
|
193
196
|
import { t as GrTreeSelect_default } from "./components/GrTreeSelect/chunks/GrTreeSelect-_LjTRR7X.js";
|
|
194
197
|
import "./composables/useGrComponentConfig.js";
|
|
195
198
|
import "./composables/useGranularityTranslations.js";
|
|
196
199
|
import { GRANULARITY_THEME_STATE, granularityThemePlugin, initThemeEarly, useTheme } from "./composables/useTheme.js";
|
|
197
|
-
export { FileValidationError, GRANULARITY_THEME_STATE, GRANULARITY_TOAST_STATE, GR_KBD_TOKENS, GR_TONES, GrAlert_default as GrAlert, GrAutocomplete_default as GrAutocomplete, GrAvatar_default as GrAvatar, GrAvatarGroup_default as GrAvatarGroup, GrBadge_default as GrBadge, GrBadgeWrap_default as GrBadgeWrap, GrBottomNav_default as GrBottomNav, GrBreadcrumbs_default as GrBreadcrumbs, GrButton_default as GrButton, GrButtonGroup_default as GrButtonGroup, GrCard_default as GrCard, GrCheckbox_default as GrCheckbox, GrCheckboxGroup_default as GrCheckboxGroup, GrCodeBlock_default as GrCodeBlock, GrCollapse_default as GrCollapse, GrCollapseItem_default as GrCollapseItem, GrColorPicker_default as GrColorPicker, GrCommandPalette_default as GrCommandPalette, GrConfigProvider_default as GrConfigProvider, GrConfirmDialog_default as GrConfirmDialog, GrDataTable_default as GrDataTable, GrDelta_default as GrDelta, GrDescriptionList_default as GrDescriptionList, GrDialog_default as GrDialog, GrDialogCloseButton_default as GrDialogCloseButton, GrDialogFooter_default as GrDialogFooter, GrDialogHeader_default as GrDialogHeader, GrDialogServiceHost_default as GrDialogServiceHost, GrDivider_default as GrDivider, GrDrawer_default as GrDrawer, GrDropdown_default as GrDropdown, GrDropdownMenu_default as GrDropdownMenu, GrDropdownMenuColumn_default as GrDropdownMenuColumn, GrDropdownMenuColumns_default as GrDropdownMenuColumns, GrDropdownMenuDivider_default as GrDropdownMenuDivider, GrDropdownMenuGroup_default as GrDropdownMenuGroup, GrDropdownMenuHeader_default as GrDropdownMenuHeader, GrDropdownMenuItem_default as GrDropdownMenuItem, GrDropdownMenuList_default as GrDropdownMenuList, GrEmptyState_default as GrEmptyState, GrFilePreview_default as GrFilePreview, GrFileUpload_default as GrFileUpload, GrForm_default as GrForm, GrFormErrorBanner_default as GrFormErrorBanner, GrFormField_default as GrFormField, GrFormFile_default as GrFormFile, GrFormSection_default as GrFormSection, GrIcon_default as GrIcon, GrImageViewer_default as GrImageViewer, GrInput_default as GrInput, GrInputTag_default as GrInputTag, GrKbd_default as GrKbd, GrLink_default as GrLink, GrList_default as GrList, GrListItem_default as GrListItem, GrLoading_default as GrLoading, GrModal_default as GrModal, GrNavbar_default as GrNavbar, GrNumberInput_default as GrNumberInput, GrPagination_default as GrPagination, GrPopover_default as GrPopover, GrProgressBar_default as GrProgressBar, GrProgressCircle_default as GrProgressCircle, GrPromptDialog_default as GrPromptDialog, GrRadio_default as GrRadio, GrRadioGroup_default as GrRadioGroup, GrRating_default as GrRating, GrResponseErrorBanner_default as GrResponseErrorBanner, GrSegmented_default as GrSegmented, GrSelect_default as GrSelect, GrSidebar_default as GrSidebar, GrSidebarGroup_default as GrSidebarGroup, GrSidebarItem_default as GrSidebarItem, GrSkeleton_default as GrSkeleton, GrSlider_default as GrSlider, GrSortableList_default as GrSortableList, GrSplitter_default as GrSplitter, GrStatistic_default as GrStatistic, GrSwitch_default as GrSwitch, GrTabPanel_default as GrTabPanel, GrTabPanels_default as GrTabPanels, GrTable_default as GrTable, GrTabs_default as GrTabs, GrTextarea_default as GrTextarea, GrTimeline_default as GrTimeline, GrTimelineItem_default as GrTimelineItem, GrToaster_default as GrToaster, GrTooltip_default as GrTooltip, GrTree_default as GrTree, GrTreeSelect_default as GrTreeSelect, GrUploadAbortError, GrUploadErrorBanner_default as GrUploadErrorBanner, GrUploadHttpError, coreResponseErrorParsers, createGrFormMessageResolver, createLoading, createResponseErrorClassifier, dialogService, extendDefaultParsers, findKbdToken, formatBadgeValue, formatStatisticValue, grAlertConfig, grAutocompleteConfig, grAutocompleteSafelist, grAvatarConfig, grAvatarSafelist, grBadgeConfig, grBadgeSafelist, grBadgeWrapConfig, grBadgeWrapSafelist, grBottomNavConfig, grBottomNavSafelist, grBreadcrumbsConfig, grBreadcrumbsSafelist, grButtonConfig, grButtonGroupConfig, grButtonSafelist, grCardConfig, grCardSafelist, grCheckboxConfig, grCheckboxGroupConfig, grCheckboxSafelist, grCodeBlockConfig, grCodeBlockSafelist, grCollapseConfig, grCollapseSafelist, grColorPickerConfig, grColorPickerSafelist, grCommandPaletteConfig, grCommandPaletteSafelist, grConfigProviderConfig, grConfirmDialogConfig, grDataTableConfig, grDataTableSafelist, grDeltaConfig, grDeltaSafelist, grDescriptionListConfig, grDescriptionListSafelist, grDialogSafelist, grDialogServiceConfig, grDividerConfig, grDividerSafelist, grDrawerConfig, grDrawerSafelist, grDropdownConfig, grDropdownMenuConfig, grDropdownMenuSafelist, grDropdownSafelist, grEmptyStateConfig, grEmptyStateSafelist, grFilePreviewConfig, grFilePreviewSafelist, grFileUploadConfig, grFileUploadSafelist, grFormConfig, grFormFieldConfig, grFormFieldSafelist, grFormFileConfig, grFormFileSafelist, grFormSectionConfig, grFormSectionSafelist, grIconConfig, grIconSafelist, grImageViewerConfig, grImageViewerSafelist, grInputConfig, grInputSafelist, grInputTagConfig, grInputTagSafelist, grKbdConfig, grKbdSafelist, grLinkConfig, grLinkSafelist, grListConfig, grListSafelist, grLoadingConfig, grLoadingSafelist, grModalConfig, grModalSafelist, grNavbarConfig, grNavbarSafelist, grNumberInputConfig, grNumberInputSafelist, grPaginationConfig, grPaginationSafelist, grPopoverConfig, grPopoverSafelist, grProgressBarConfig, grProgressBarSafelist, grProgressCircleConfig, grProgressCircleSafelist, grPromptDialogConfig, grRadioConfig, grRadioGroupConfig, grRadioSafelist, grRatingConfig, grRatingSafelist, grSegmentedConfig, grSegmentedSafelist, grSelectConfig, grSelectSafelist, grSidebarConfig, grSidebarSafelist, grSkeletonConfig, grSliderConfig, grSliderSafelist, grSortableListConfig, grSortableListSafelist, grSplitterConfig, grSplitterSafelist, grStatisticConfig, grStatisticSafelist, grSwitchConfig, grSwitchSafelist, grTabPanelsConfig, grTableConfig, grTableSafelist, grTabsConfig, grTabsSafelist, grTextareaConfig, grTextareaSafelist, grTimelineConfig, grTimelineSafelist, grToasterConfig, grToasterSafelist, grTooltipConfig, grTooltipSafelist, grTreeConfig, grTreeSafelist, grTreeSelectConfig, grTreeSelectSafelist, granularityDialogServicePlugin, granularityThemePlugin, granularityToastPlugin, initThemeEarly, initialsFrom, normalizeError, resolveBreadcrumbsFit, resolveBreadcrumbsLayout, resolveGrConfig, runFieldRules, sizeFromPointer, teardownDialogService, useAnnouncer, useComboboxNavigation, useDialogService, useDismissible, useDragGesture, useDragSort, useFloating, useFocusTrap, useGrButtonGroup, useGrComponentDefaults, useGrComponentProp, useGrComponentSize, useGrConfig, useGrFormContext, useGrFormControl, useGrFormFieldContext, useGrThemeAttrs, useGranularityTranslations, useOverlayLayer, usePortalTarget, useResponseError, useRovingFocus, useTheme, useToast, useVirtualList, vAutofocus, vAutosize, vClickOutside, vDropzone, vHotkey, vLoading };
|
|
200
|
+
export { FileValidationError, GRANULARITY_THEME_STATE, GRANULARITY_TOAST_STATE, GR_KBD_TOKENS, GR_TONES, GrAlert_default as GrAlert, GrAutocomplete_default as GrAutocomplete, GrAvatar_default as GrAvatar, GrAvatarGroup_default as GrAvatarGroup, GrBadge_default as GrBadge, GrBadgeWrap_default as GrBadgeWrap, GrBottomNav_default as GrBottomNav, GrBreadcrumbs_default as GrBreadcrumbs, GrButton_default as GrButton, GrButtonGroup_default as GrButtonGroup, GrCard_default as GrCard, GrCheckbox_default as GrCheckbox, GrCheckboxGroup_default as GrCheckboxGroup, GrCodeBlock_default as GrCodeBlock, GrCollapse_default as GrCollapse, GrCollapseItem_default as GrCollapseItem, GrColorPicker_default as GrColorPicker, GrCommandPalette_default as GrCommandPalette, GrConfigProvider_default as GrConfigProvider, GrConfirmDialog_default as GrConfirmDialog, GrDataTable_default as GrDataTable, GrDelta_default as GrDelta, GrDescriptionList_default as GrDescriptionList, GrDialog_default as GrDialog, GrDialogCloseButton_default as GrDialogCloseButton, GrDialogFooter_default as GrDialogFooter, GrDialogHeader_default as GrDialogHeader, GrDialogServiceHost_default as GrDialogServiceHost, GrDivider_default as GrDivider, GrDrawer_default as GrDrawer, GrDropdown_default as GrDropdown, GrDropdownMenu_default as GrDropdownMenu, GrDropdownMenuColumn_default as GrDropdownMenuColumn, GrDropdownMenuColumns_default as GrDropdownMenuColumns, GrDropdownMenuDivider_default as GrDropdownMenuDivider, GrDropdownMenuGroup_default as GrDropdownMenuGroup, GrDropdownMenuHeader_default as GrDropdownMenuHeader, GrDropdownMenuItem_default as GrDropdownMenuItem, GrDropdownMenuList_default as GrDropdownMenuList, GrEmptyState_default as GrEmptyState, GrFilePreview_default as GrFilePreview, GrFileUpload_default as GrFileUpload, GrForm_default as GrForm, GrFormErrorBanner_default as GrFormErrorBanner, GrFormField_default as GrFormField, GrFormFile_default as GrFormFile, GrFormSection_default as GrFormSection, GrIcon_default as GrIcon, GrImageViewer_default as GrImageViewer, GrInput_default as GrInput, GrInputTag_default as GrInputTag, GrJsonViewer_default as GrJsonViewer, GrKbd_default as GrKbd, GrLink_default as GrLink, GrList_default as GrList, GrListItem_default as GrListItem, GrLoading_default as GrLoading, GrModal_default as GrModal, GrNavbar_default as GrNavbar, GrNumberInput_default as GrNumberInput, GrPagination_default as GrPagination, GrPopover_default as GrPopover, GrProgressBar_default as GrProgressBar, GrProgressCircle_default as GrProgressCircle, GrPromptDialog_default as GrPromptDialog, GrRadio_default as GrRadio, GrRadioGroup_default as GrRadioGroup, GrRating_default as GrRating, GrResponseErrorBanner_default as GrResponseErrorBanner, GrSegmented_default as GrSegmented, GrSelect_default as GrSelect, GrSidebar_default as GrSidebar, GrSidebarGroup_default as GrSidebarGroup, GrSidebarItem_default as GrSidebarItem, GrSkeleton_default as GrSkeleton, GrSlider_default as GrSlider, GrSortableList_default as GrSortableList, GrSplitter_default as GrSplitter, GrStatistic_default as GrStatistic, GrSwitch_default as GrSwitch, GrTabPanel_default as GrTabPanel, GrTabPanels_default as GrTabPanels, GrTable_default as GrTable, GrTabs_default as GrTabs, GrTextarea_default as GrTextarea, GrTimeline_default as GrTimeline, GrTimelineItem_default as GrTimelineItem, GrToaster_default as GrToaster, GrTooltip_default as GrTooltip, GrTree_default as GrTree, GrTreeSelect_default as GrTreeSelect, GrUploadAbortError, GrUploadErrorBanner_default as GrUploadErrorBanner, GrUploadHttpError, coreResponseErrorParsers, createGrFormMessageResolver, createLoading, createResponseErrorClassifier, deltaDirection, deltaTone, dialogService, extendDefaultParsers, fileKindOf, findKbdToken, formatBadgeValue, formatStatisticValue, grAlertConfig, grAutocompleteConfig, grAutocompleteSafelist, grAvatarConfig, grAvatarSafelist, grBadgeConfig, grBadgeSafelist, grBadgeWrapConfig, grBadgeWrapSafelist, grBottomNavConfig, grBottomNavSafelist, grBreadcrumbsConfig, grBreadcrumbsSafelist, grButtonConfig, grButtonGroupConfig, grButtonSafelist, grCardConfig, grCardSafelist, grCheckboxConfig, grCheckboxGroupConfig, grCheckboxSafelist, grCodeBlockConfig, grCodeBlockSafelist, grCollapseConfig, grCollapseSafelist, grColorPickerConfig, grColorPickerSafelist, grCommandPaletteConfig, grCommandPaletteSafelist, grConfigProviderConfig, grConfirmDialogConfig, grDataTableConfig, grDataTableSafelist, grDeltaConfig, grDeltaSafelist, grDescriptionListConfig, grDescriptionListSafelist, grDialogSafelist, grDialogServiceConfig, grDividerConfig, grDividerSafelist, grDrawerConfig, grDrawerSafelist, grDropdownConfig, grDropdownMenuConfig, grDropdownMenuSafelist, grDropdownSafelist, grEmptyStateConfig, grEmptyStateSafelist, grFilePreviewConfig, grFilePreviewSafelist, grFileUploadConfig, grFileUploadSafelist, grFormConfig, grFormFieldConfig, grFormFieldSafelist, grFormFileConfig, grFormFileSafelist, grFormSectionConfig, grFormSectionSafelist, grIconConfig, grIconSafelist, grImageViewerConfig, grImageViewerSafelist, grInputConfig, grInputSafelist, grInputTagConfig, grInputTagSafelist, grJsonViewerConfig, grJsonViewerSafelist, grKbdConfig, grKbdSafelist, grLinkConfig, grLinkSafelist, grListConfig, grListSafelist, grLoadingConfig, grLoadingSafelist, grModalConfig, grModalSafelist, grNavbarConfig, grNavbarSafelist, grNumberInputConfig, grNumberInputSafelist, grPaginationConfig, grPaginationSafelist, grPopoverConfig, grPopoverSafelist, grProgressBarConfig, grProgressBarSafelist, grProgressCircleConfig, grProgressCircleSafelist, grPromptDialogConfig, grRadioConfig, grRadioGroupConfig, grRadioSafelist, grRatingConfig, grRatingSafelist, grSegmentedConfig, grSegmentedSafelist, grSelectConfig, grSelectSafelist, grSidebarConfig, grSidebarSafelist, grSkeletonConfig, grSliderConfig, grSliderSafelist, grSortableListConfig, grSortableListSafelist, grSplitterConfig, grSplitterSafelist, grStatisticConfig, grStatisticSafelist, grSwitchConfig, grSwitchSafelist, grTabPanelsConfig, grTableConfig, grTableSafelist, grTabsConfig, grTabsSafelist, grTextareaConfig, grTextareaSafelist, grTimelineConfig, grTimelineSafelist, grToasterConfig, grToasterSafelist, grTooltipConfig, grTooltipSafelist, grTreeConfig, grTreeSafelist, grTreeSelectConfig, grTreeSelectSafelist, granularityDialogServicePlugin, granularityThemePlugin, granularityToastPlugin, initThemeEarly, initialsFrom, isPreviewableKind, normalizeError, resolveBreadcrumbsFit, resolveBreadcrumbsLayout, resolveGrConfig, runFieldRules, sizeFromPointer, teardownDialogService, useAnnouncer, useComboboxNavigation, useDialogService, useDismissible, useDragGesture, useDragSort, useFloating, useFocusTrap, useGrButtonGroup, useGrComponentDefaults, useGrComponentProp, useGrComponentSize, useGrConfig, useGrFormContext, useGrFormControl, useGrFormFieldContext, useGrThemeAttrs, useGranularityTranslations, useOverlayLayer, usePortalTarget, useResponseError, useRovingFocus, useTheme, useToast, useVirtualList, vAutofocus, vAutosize, vClickOutside, vDropzone, vHotkey, vLoading };
|
package/dist/theme.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as grThemeTokens, n as grDerivedTokens, t as grComponentTokens } from "./chunks/generated-
|
|
1
|
+
import { a as grThemeTokens, n as grDerivedTokens, t as grComponentTokens } from "./chunks/generated-CiCrGDQO.js";
|
|
2
2
|
//#region src/theme/color.ts
|
|
3
3
|
function parseHex(value) {
|
|
4
4
|
const match = value.trim().match(/^#([\da-f]{3}|[\da-f]{6})$/i);
|
package/dist/tokens.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as grThemeTokens, i as grThemeNames, n as grDerivedTokens, r as grFoundationTokens, t as grComponentTokens } from "./chunks/generated-
|
|
1
|
+
import { a as grThemeTokens, i as grThemeNames, n as grDerivedTokens, r as grFoundationTokens, t as grComponentTokens } from "./chunks/generated-CiCrGDQO.js";
|
|
2
2
|
export { grComponentTokens, grDerivedTokens, grFoundationTokens, grThemeNames, grThemeTokens };
|