@feugene/granularity 0.46.0 → 0.48.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.
Files changed (162) hide show
  1. package/README.md +3 -3
  2. package/dist/chunks/{x-circle-BCBURwyX.js → check-circle-Bnrb-CGJ.js} +8 -32
  3. package/dist/chunks/check-circle-Bnrb-CGJ.js.map +1 -0
  4. package/dist/chunks/{config-BqT6PMzO.js → config-B42iJ48O.js} +5 -1
  5. package/dist/chunks/{config-BqT6PMzO.js.map → config-B42iJ48O.js.map} +1 -1
  6. package/dist/chunks/{config-BGCyyXiD.js → config-BAse0laT.js} +5 -1
  7. package/dist/chunks/{config-BGCyyXiD.js.map → config-BAse0laT.js.map} +1 -1
  8. package/dist/chunks/{config-MmPym-Z7.js → config-BLP94dPY.js} +5 -1
  9. package/dist/chunks/{config-MmPym-Z7.js.map → config-BLP94dPY.js.map} +1 -1
  10. package/dist/chunks/{config-CjKpUcmy.js → config-Bdf1bt-m.js} +25 -16
  11. package/dist/chunks/config-Bdf1bt-m.js.map +1 -0
  12. package/dist/chunks/{config-DeyT9dJl.js → config-Bs1HwUcx.js} +47 -4
  13. package/dist/chunks/{config-DeyT9dJl.js.map → config-Bs1HwUcx.js.map} +1 -1
  14. package/dist/chunks/{config-CIkdsWUk.js → config-CIUU9ZpY.js} +4 -1
  15. package/dist/chunks/config-CIUU9ZpY.js.map +1 -0
  16. package/dist/chunks/{config-B3J0alyY.js → config-CzeZg2LO.js} +49 -4
  17. package/dist/chunks/config-CzeZg2LO.js.map +1 -0
  18. package/dist/chunks/{config-DCq4JySZ.js → config-D3HOuHDe.js} +1 -1
  19. package/dist/chunks/{config-DCq4JySZ.js.map → config-D3HOuHDe.js.map} +1 -1
  20. package/dist/chunks/{config-BhfNgyWL.js → config-DENqOoh0.js} +5 -1
  21. package/dist/chunks/config-DENqOoh0.js.map +1 -0
  22. package/dist/chunks/controlState-DoImKciE.js +35 -0
  23. package/dist/chunks/controlState-DoImKciE.js.map +1 -0
  24. package/dist/chunks/{en-DiHzFact.js → en-Bxyn5lW7.js} +12 -2
  25. package/dist/chunks/en-Bxyn5lW7.js.map +1 -0
  26. package/dist/chunks/{es-CeKkMxZ_.js → es-Bj_vc18Z.js} +3 -3
  27. package/dist/chunks/{es-CeKkMxZ_.js.map → es-Bj_vc18Z.js.map} +1 -1
  28. package/dist/chunks/{es-1ZL6NtkB.js → es-Dtl-a7ui.js} +12 -2
  29. package/dist/chunks/es-Dtl-a7ui.js.map +1 -0
  30. package/dist/chunks/{generated-CQ4h6Ieq.js → generated-hELWB0gZ.js} +98 -0
  31. package/dist/chunks/{generated-CQ4h6Ieq.js.map → generated-hELWB0gZ.js.map} +1 -1
  32. package/dist/chunks/{grTableStyles-uuMPSOBR.js → grTableStyles-DkQPMfx9.js} +16 -3
  33. package/dist/chunks/grTableStyles-DkQPMfx9.js.map +1 -0
  34. package/dist/chunks/{granular-provider-CsN_R9dB.js → granular-provider-BOQp7N5o.js} +9 -9
  35. package/dist/chunks/{granular-provider-CsN_R9dB.js.map → granular-provider-BOQp7N5o.js.map} +1 -1
  36. package/dist/chunks/{ru-Dr2RYn0P.js → ru-hrB4I1u_.js} +12 -2
  37. package/dist/chunks/ru-hrB4I1u_.js.map +1 -0
  38. package/dist/chunks/x-circle-BigSZy8m.js +26 -0
  39. package/dist/chunks/x-circle-BigSZy8m.js.map +1 -0
  40. package/dist/components/GrAlert/chunks/{GrAlert-D72y1IEh.js → GrAlert-CfEZghSY.js} +2 -1
  41. package/dist/components/GrAlert/chunks/{GrAlert-D72y1IEh.js.map → GrAlert-CfEZghSY.js.map} +1 -1
  42. package/dist/components/GrAlert/index.js +1 -1
  43. package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-D396_JrW.js → GrAutocomplete-C-uovdv8.js} +320 -224
  44. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-C-uovdv8.js.map +1 -0
  45. package/dist/components/GrAutocomplete/index.js +1 -1
  46. package/dist/components/GrAutocomplete/styles.css +1 -1
  47. package/dist/components/GrAvatar/chunks/{GrAvatar-dWEXiCJG.js → GrAvatar-Do5-C409.js} +12 -1
  48. package/dist/components/GrAvatar/chunks/GrAvatar-Do5-C409.js.map +1 -0
  49. package/dist/components/GrAvatar/index.js +2 -2
  50. package/dist/components/GrAvatar/themes/light.css +35 -0
  51. package/dist/components/GrColorPicker/chunks/{GrColorPicker-9mTR-YZ_.js → GrColorPicker-BRM_4lyI.js} +1 -1
  52. package/dist/components/GrColorPicker/chunks/{GrColorPicker-9mTR-YZ_.js.map → GrColorPicker-BRM_4lyI.js.map} +1 -1
  53. package/dist/components/GrColorPicker/index.js +1 -1
  54. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-Ha4s3DMT.js.map → GrCommandPalette-BJHmkDQv.js.map} +1 -1
  55. package/dist/components/GrCommandPalette/index.js +1 -1
  56. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-e15nFI8M.js → GrConfirmDialog-BzUQwbec.js} +1 -1
  57. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-e15nFI8M.js.map → GrConfirmDialog-BzUQwbec.js.map} +1 -1
  58. package/dist/components/GrConfirmDialog/index.js +1 -1
  59. package/dist/components/GrDataTable/chunks/GrDataTable-DQxYYgQk.js +1519 -0
  60. package/dist/components/GrDataTable/chunks/GrDataTable-DQxYYgQk.js.map +1 -0
  61. package/dist/components/GrDataTable/index.js +2 -2
  62. package/dist/components/GrDataTable/themes/light.css +10 -0
  63. package/dist/components/GrDialogService/chunks/{GrDialogService-BmXiYmUp.js → GrDialogService-Dtq0ZCN5.js} +3 -3
  64. package/dist/components/GrDialogService/chunks/{GrDialogService-BmXiYmUp.js.map → GrDialogService-Dtq0ZCN5.js.map} +1 -1
  65. package/dist/components/GrDialogService/index.js +1 -1
  66. package/dist/components/GrFormField/chunks/GrFormField-DO61vxpS.js.map +1 -1
  67. package/dist/components/GrInput/chunks/{GrInput-TFeBm3gQ.js → GrInput-DV4gMWPR.js} +40 -11
  68. package/dist/components/GrInput/chunks/GrInput-DV4gMWPR.js.map +1 -0
  69. package/dist/components/GrInput/index.js +2 -2
  70. package/dist/components/GrInputTag/chunks/{GrInputTag-Ci8AO1ze.js → GrInputTag-CO0YU-ok.js} +30 -6
  71. package/dist/components/GrInputTag/chunks/GrInputTag-CO0YU-ok.js.map +1 -0
  72. package/dist/components/GrInputTag/index.js +2 -2
  73. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-C6q8dEEZ.js → GrJsonViewer-D7CyWzhT.js} +1 -1
  74. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-C6q8dEEZ.js.map → GrJsonViewer-D7CyWzhT.js.map} +1 -1
  75. package/dist/components/GrJsonViewer/index.js +1 -1
  76. package/dist/components/GrNumberInput/chunks/{GrNumberInput-CL5QhOmx.js → GrNumberInput-BI6-vkcs.js} +48 -16
  77. package/dist/components/GrNumberInput/chunks/GrNumberInput-BI6-vkcs.js.map +1 -0
  78. package/dist/components/GrNumberInput/index.js +2 -2
  79. package/dist/components/GrPagination/chunks/{GrPagination-DhbNZHEF.js → GrPagination-BbaF5eXk.js} +10 -7
  80. package/dist/components/GrPagination/chunks/GrPagination-BbaF5eXk.js.map +1 -0
  81. package/dist/components/GrPagination/index.js +2 -2
  82. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-8RxQsOQ_.js → GrPromptDialog-BEL-QgwE.js} +3 -3
  83. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-8RxQsOQ_.js.map → GrPromptDialog-BEL-QgwE.js.map} +1 -1
  84. package/dist/components/GrPromptDialog/index.js +1 -1
  85. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-NEEJZ8zi.js → GrResponseErrorBanner-Bdd5c07x.js} +1 -1
  86. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-NEEJZ8zi.js.map → GrResponseErrorBanner-Bdd5c07x.js.map} +1 -1
  87. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-ZvBvEQDZ.js → GrResponseErrorBanner-DySe1ym4.js} +1 -1
  88. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-ZvBvEQDZ.js.map → GrResponseErrorBanner-DySe1ym4.js.map} +1 -1
  89. package/dist/components/GrResponseErrorBanner/index.js +2 -2
  90. package/dist/components/GrSelect/chunks/{GrSelect-Do1iAyp1.js → GrSelect-0iI4wdR_.js} +3 -3
  91. package/dist/components/GrSelect/chunks/{GrSelect-Do1iAyp1.js.map → GrSelect-0iI4wdR_.js.map} +1 -1
  92. package/dist/components/GrSelect/index.js +1 -1
  93. package/dist/components/GrTable/chunks/{GrTable-iwzHvlMC.js → GrTable-CKJ-HrsN.js} +1 -1
  94. package/dist/components/GrTable/chunks/{GrTable-iwzHvlMC.js.map → GrTable-CKJ-HrsN.js.map} +1 -1
  95. package/dist/components/GrTable/index.js +2 -2
  96. package/dist/components/GrTextarea/chunks/{GrTextarea-BII3w61K.js → GrTextarea-Bfgc0DD2.js} +73 -32
  97. package/dist/components/GrTextarea/chunks/GrTextarea-Bfgc0DD2.js.map +1 -0
  98. package/dist/components/GrTextarea/index.js +2 -2
  99. package/dist/components/GrToaster/chunks/{GrToaster-D-sV-9of.js → GrToaster-CZixNk0l.js} +2 -1
  100. package/dist/components/GrToaster/chunks/{GrToaster-D-sV-9of.js.map → GrToaster-CZixNk0l.js.map} +1 -1
  101. package/dist/components/GrToaster/index.js +1 -1
  102. package/dist/components/GrTransfer/chunks/{GrTransfer-8FA78ny6.js → GrTransfer-DdfBUf35.js} +2 -2
  103. package/dist/components/GrTransfer/chunks/{GrTransfer-8FA78ny6.js.map → GrTransfer-DdfBUf35.js.map} +1 -1
  104. package/dist/components/GrTransfer/index.js +1 -1
  105. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DBu5nMGA.js → GrTreeSelect-B6KoDYiZ.js} +43 -18
  106. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-B6KoDYiZ.js.map +1 -0
  107. package/dist/components/GrTreeSelect/index.js +2 -2
  108. package/dist/granular-provider-node.js +1 -1
  109. package/dist/granular-provider.js +1 -1
  110. package/dist/i18n/all.js +1 -1
  111. package/dist/i18n/index.js +1 -1
  112. package/dist/index.js +32 -32
  113. package/dist/theme.js +1 -1
  114. package/dist/tokens.js +1 -1
  115. package/dist/types/components/GrAutocomplete/composables/useAutocompleteNavigation.d.ts +39 -0
  116. package/dist/types/components/GrAutocomplete/composables/useAutocompletePanel.d.ts +36 -0
  117. package/dist/types/components/GrAutocomplete/composables/useAutocompleteValues.d.ts +28 -0
  118. package/dist/types/components/GrAutocomplete/composables/useAutocompleteVirtual.d.ts +33 -0
  119. package/dist/types/components/GrAutocomplete/composables/useRemoteOptions.d.ts +33 -0
  120. package/dist/types/components/GrAvatar/GrAvatar.vue.d.ts +11 -0
  121. package/dist/types/components/GrAvatar/defaults.d.ts +1 -0
  122. package/dist/types/components/GrAvatar/grAvatarStyles.d.ts +26 -1
  123. package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +60 -1
  124. package/dist/types/components/GrDataTable/composables/useDataTableColumnOrder.d.ts +45 -0
  125. package/dist/types/components/GrDataTable/composables/useDataTableColumnWidths.d.ts +38 -0
  126. package/dist/types/components/GrDataTable/composables/useDataTableExpansion.d.ts +46 -0
  127. package/dist/types/components/GrDataTable/composables/useDataTableLayout.d.ts +29 -0
  128. package/dist/types/components/GrDataTable/composables/useDataTableRowKeys.d.ts +16 -0
  129. package/dist/types/components/GrDataTable/composables/useDataTableSelection.d.ts +32 -0
  130. package/dist/types/components/GrDataTable/composables/useDataTableSort.d.ts +37 -0
  131. package/dist/types/components/GrDataTable/grDataTableStyles.d.ts +23 -0
  132. package/dist/types/components/GrFormField/GrFormField.vue.d.ts +7 -1
  133. package/dist/types/components/GrPagination/GrPagination.vue.d.ts +17 -2
  134. package/dist/types/components/GrPagination/grPaginationStyles.d.ts +15 -6
  135. package/dist/types/components/GrPagination/index.d.ts +1 -1
  136. package/dist/types/components/GrTable/grTableStyles.d.ts +16 -3
  137. package/dist/types/components/shared/controlState.d.ts +36 -0
  138. package/dist/types/i18n/messages/en.d.ts +20 -0
  139. package/dist/types/i18n/messages/es.d.ts +20 -0
  140. package/dist/types/i18n/messages/ru.d.ts +20 -0
  141. package/dist/web-types.json +79 -3
  142. package/package.json +1 -1
  143. package/dist/chunks/config-B3J0alyY.js.map +0 -1
  144. package/dist/chunks/config-BhfNgyWL.js.map +0 -1
  145. package/dist/chunks/config-CIkdsWUk.js.map +0 -1
  146. package/dist/chunks/config-CjKpUcmy.js.map +0 -1
  147. package/dist/chunks/en-DiHzFact.js.map +0 -1
  148. package/dist/chunks/es-1ZL6NtkB.js.map +0 -1
  149. package/dist/chunks/grTableStyles-uuMPSOBR.js.map +0 -1
  150. package/dist/chunks/ru-Dr2RYn0P.js.map +0 -1
  151. package/dist/chunks/x-circle-BCBURwyX.js.map +0 -1
  152. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-D396_JrW.js.map +0 -1
  153. package/dist/components/GrAvatar/chunks/GrAvatar-dWEXiCJG.js.map +0 -1
  154. package/dist/components/GrDataTable/chunks/GrDataTable-xNSmO_I-.js +0 -1134
  155. package/dist/components/GrDataTable/chunks/GrDataTable-xNSmO_I-.js.map +0 -1
  156. package/dist/components/GrInput/chunks/GrInput-TFeBm3gQ.js.map +0 -1
  157. package/dist/components/GrInputTag/chunks/GrInputTag-Ci8AO1ze.js.map +0 -1
  158. package/dist/components/GrNumberInput/chunks/GrNumberInput-CL5QhOmx.js.map +0 -1
  159. package/dist/components/GrPagination/chunks/GrPagination-DhbNZHEF.js.map +0 -1
  160. package/dist/components/GrTextarea/chunks/GrTextarea-BII3w61K.js.map +0 -1
  161. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-DBu5nMGA.js.map +0 -1
  162. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-Ha4s3DMT.js → GrCommandPalette-BJHmkDQv.js} +1 -1
@@ -1,3 +1,3 @@
1
- import { t as GrSelect_default } from "./chunks/GrSelect-Do1iAyp1.js";
1
+ import { t as GrSelect_default } from "./chunks/GrSelect-0iI4wdR_.js";
2
2
  import { n as grSelectSafelist, t as grSelectConfig } from "../../chunks/config--t2dxj0t.js";
3
3
  export { GrSelect_default as GrSelect, GrSelect_default as default, grSelectConfig, grSelectSafelist };
@@ -2,7 +2,7 @@ import { a as useGrComponentSize } from "../../../chunks/context-CPMRfwVr.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 hasMeaningfulSlotContent } from "../../../chunks/slotNodes-DxNXpC7v.js";
5
- import { a as tableSizes, i as stripedClass, n as hoverableClass, r as loadingRowCellClass, t as emptyCellClass } from "../../../chunks/grTableStyles-uuMPSOBR.js";
5
+ import { a as tableSizes, i as stripedClass, n as hoverableClass, r as loadingRowCellClass, t as emptyCellClass } from "../../../chunks/grTableStyles-DkQPMfx9.js";
6
6
  import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useSlots } from "vue";
7
7
  //#region src/components/GrTable/GrTable.vue?vue&type=script&setup=true&lang.ts
8
8
  var _hoisted_1 = [
@@ -1 +1 @@
1
- {"version":3,"file":"GrTable-iwzHvlMC.js","names":[],"sources":["../../../../src/components/GrTable/GrTable.vue","../../../../src/components/GrTable/GrTable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, useSlots } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport GrSkeleton from '../GrSkeleton/GrSkeleton.vue'\nimport { hasMeaningfulSlotContent } from '../shared/slotNodes'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport {\n emptyCellClass,\n hoverableClass,\n loadingRowCellClass,\n stripedClass,\n tableSizes,\n type GrTableSize,\n} from './grTableStyles'\n\nexport interface GrTableProps {\n /**\n * Размер таблицы — базовый кегль текста. Паддинги ячеек оставлены за\n * консьюмером (GrTable — «тонкий» контейнер).\n */\n size?: GrTableSize\n /**\n * Текст caption для screen reader'ов. Рендерится как `<caption class=\"sr-only\">`,\n * если не передан слот `#caption`.\n */\n caption?: string\n /** Прямой ARIA-label для `<table>`. Игнорируется, если задан `ariaLabelledby`. */\n ariaLabel?: string\n /** ID элемента-заголовка, связанного с `<table>` через `aria-labelledby`. */\n ariaLabelledby?: string\n /**\n * ARIA-label для скролл-контейнера. Включает `role=\"region\"`; сам скролл\n * достижим с клавиатуры всегда, независимо от метки.\n */\n regionLabel?: string\n /** Идёт загрузка: вместо строк — скелетоны, контейнер помечен `aria-busy`. */\n loading?: boolean\n /** Сколько строк-заглушек показать при `loading`. */\n loadingRows?: number\n /** Сколько колонок занимает служебная строка (пустое состояние и скелетоны). */\n columnCount?: number\n /** Текст пустого состояния. Слот `#empty` сильнее. */\n emptyText?: string\n /** Таблица пуста. По умолчанию определяется по содержимому слота. */\n empty?: boolean\n /** Чередование строк. */\n striped?: boolean\n /** Подсветка строки под курсором. */\n hoverable?: boolean\n /**\n * Прилипающий заголовок: `<thead>` остаётся видимым при вертикальном скролле.\n * Осмысленно вместе с `maxHeight` (иначе таблица не скроллится вертикально).\n */\n stickyHeader?: boolean\n /**\n * Полное число строк набора, включая строки заголовка (`aria-rowcount`).\n *\n * Нужен, когда в DOM не весь набор — например, при виртуализации: диктор\n * считает строки по разметке и объявил бы «5 из 20» на таблице в десять\n * тысяч. Строки при этом обязаны нести `aria-rowindex`.\n */\n rowCount?: number\n /**\n * Фиксированная раскладка (`table-layout: fixed`): ширины колонок берутся из\n * первой строки, а не из содержимого всех.\n *\n * Обязателен, если в DOM не весь набор: иначе ширины считаются по\n * отрисованному окну и прыгают на каждой прокрутке.\n *\n * Класс — arbitrary-значение, а не `table-fixed`: такого правила в\n * `presetMini` нет, и класс молча не превратился бы в CSS.\n */\n fixedLayout?: boolean\n /**\n * Минимальная ширина самой таблицы (число — пиксели).\n *\n * Нужна при `fixedLayout`: с фиксированной раскладкой и шириной `auto`\n * браузер вписывает таблицу в контейнер и делит место между колонками\n * пропорционально — то есть заданные ширины молча ужимаются, а\n * горизонтальной прокрутки, на которой держатся закреплённые колонки, не\n * возникает вовсе.\n */\n tableMinWidth?: string | number\n /**\n * Максимальная высота скролл-контейнера (включает вертикальный скролл).\n * Число трактуется как пиксели. Нужен для работы `stickyHeader`.\n */\n maxHeight?: string | number\n}\n\n/**\n * `GrTable` — «тонкий» GR-контейнер для табличных данных.\n *\n * Рендерит `<table>` внутри скролл-обёртки и даёт слоты `#caption`, `#header`,\n * default (tbody) и `#footer`. Стили ячеек (`<th>`/`<td>` паддинги, выравнивание)\n * оставлены на консьюмере.\n *\n * ВАЖНО: `min-w-full` сам по себе не даст горизонтального скролла. Для него\n * консьюмеру нужны `white-space: nowrap` на ячейках или явные ширины колонок.\n */\nconst props = withDefaults(defineProps<GrTableProps>(), {\n size: undefined,\n caption: undefined,\n ariaLabel: undefined,\n ariaLabelledby: undefined,\n regionLabel: undefined,\n loading: false,\n loadingRows: 3,\n columnCount: 1,\n emptyText: undefined,\n empty: undefined,\n striped: false,\n hoverable: false,\n stickyHeader: false,\n maxHeight: undefined,\n rowCount: undefined,\n fixedLayout: false,\n tableMinWidth: undefined,\n})\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTable' })\nconst tableTextClass = computed(() => tableSizes[resolvedSize.value])\nconst hasCaption = computed(() => Boolean(slots.caption) || Boolean(props.caption))\n\nconst { t } = useGranularityTranslations()\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.table.empty', 'Nothing here yet'))\n\n// Пустоту видно по слоту: `v-for` по пустому массиву оставляет фрагмент без\n// узлов, `v-if` — комментарий, и ни то ни другое строкой не является.\nconst isEmpty = computed(() => {\n if (props.empty !== undefined)\n return props.empty\n\n return !hasMeaningfulSlotContent(slots.default?.() ?? [])\n})\n\nconst showRows = computed(() => !props.loading && !isEmpty.value)\nconst loadingRowCount = computed(() => Math.max(1, Math.trunc(props.loadingRows)))\nconst serviceColSpan = computed(() => Math.max(1, Math.trunc(props.columnCount)))\n\nconst tbodyClass = computed(() => [\n 'text-[var(--gr-fg)]',\n props.striped && showRows.value ? stripedClass : '',\n props.hoverable && showRows.value ? hoverableClass : '',\n].filter(Boolean).join(' '))\n\nconst scrollStyle = computed(() => {\n // Неполный набор в DOM (`rowCount`) означает виртуализацию, а с ней обязан\n // быть выключен браузерный scroll anchoring: он подправляет `scrollTop`,\n // когда меняется высота содержимого выше видимого узла, — а окно меняет её\n // на каждом кадре прокрутки, и список уезжает.\n const anchor = props.rowCount === undefined ? undefined : { overflowAnchor: 'none' as const }\n\n if (props.maxHeight === undefined)\n return anchor\n\n const value = typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight\n return { ...anchor, maxHeight: value, overflowY: 'auto' as const }\n})\n\n// Прилипающий заголовок: `<thead>` на `position: sticky`; фон обязателен, иначе\n// сквозь него будут просвечивать строки при скролле.\nconst theadClass = computed(() => [\n 'bg-[var(--gr-muted)] text-[var(--gr-muted-fg)]',\n props.stickyHeader ? 'sticky top-0 z-[1]' : '',\n].filter(Boolean).join(' '))\n\nconst tableStyle = computed(() => {\n if (props.tableMinWidth === undefined)\n return undefined\n\n const value = typeof props.tableMinWidth === 'number' ? `${props.tableMinWidth}px` : props.tableMinWidth\n\n return { minWidth: value }\n})\n\nconst scrollEl = ref<HTMLElement | null>(null)\n\nfunction scrollTo(options: ScrollToOptions): void {\n scrollEl.value?.scrollTo(options)\n}\n\n// Только верхний уровень собственного tbody: вложенная таблица в ячейке не\n// должна сдвигать индексацию строк.\nfunction contentRows(): HTMLElement[] {\n if (!showRows.value)\n return []\n const el = scrollEl.value\n if (!el)\n return []\n return Array.from(el.querySelectorAll<HTMLElement>(':scope > table > tbody > tr'))\n}\n\nfunction scrollToRow(index: number, options?: ScrollIntoViewOptions): boolean {\n const row = contentRows()[index]\n if (!row)\n return false\n row.scrollIntoView(options ?? { block: 'nearest' })\n return true\n}\n\ndefineExpose({\n /** Прокрутить скролл-контейнер таблицы — тот же контракт, что у `GrDataTable`. */\n scrollTo,\n /** Прокрутить к строке содержимого по её индексу в разметке. `false` — строки нет в DOM. */\n scrollToRow,\n})\n\ndefineSlots<{\n /** Строки таблицы, когда разметка пишется руками вместо `data`. */\n default?: () => any\n /** Подпись таблицы — `<caption>`, читается диктором первой. */\n caption?: () => any\n /** Шапка вместо построенной по `columns`. */\n header?: () => any\n /** Содержимое, пока едут данные, — вместо строк-заглушек. */\n loading?: () => any\n /** Пустое состояние вместо текста по умолчанию. */\n empty?: () => any\n /** Итоговая строка под таблицей. */\n footer?: () => any\n}>()\n\n/**\n * `relative` на скроллере — не для потомков с координатами, а чтобы он стал\n * containing block. Без него абсолютные потомки (`sr-only`-подсказка у кнопки\n * сортировки — единственный такой в самой таблице, но разметка ячеек чужая)\n * считают позицию от документа и выпадают из прокрутки наружу: на узком экране\n * широкая таблица начинает тащить вбок всю страницу, а не только себя.\n *\n * Живёт здесь, а не над `<div>`: комментарий в корне `<template>` делает\n * компонент фрагментом, и `$el` у потребителя становится Comment-нодой —\n * `GrDataTable` падает на `root.matches` ещё до первого рендера.\n */\n</script>\n\n<template>\n <div\n ref=\"scrollEl\"\n data-gr-table-scroll\n :role=\"regionLabel ? 'region' : undefined\"\n :aria-label=\"regionLabel\"\n :aria-busy=\"loading ? 'true' : undefined\"\n tabindex=\"0\"\n class=\"relative overflow-x-auto rounded-[var(--gr-radius-lg)] border border-[var(--gr-brd)] bg-[var(--gr-card)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n :style=\"scrollStyle\"\n >\n <table\n data-gr-table\n class=\"min-w-full\" :class=\"[tableTextClass, fixedLayout ? '[table-layout:fixed]' : '']\"\n :style=\"tableStyle\"\n :aria-label=\"ariaLabelledby ? undefined : ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-rowcount=\"rowCount\"\n >\n <caption v-if=\"hasCaption\" class=\"sr-only\">\n <slot name=\"caption\">\n{{ caption }}\n</slot>\n </caption>\n <thead :class=\"theadClass\">\n <slot name=\"header\" />\n </thead>\n <tbody :class=\"tbodyClass\">\n <template v-if=\"loading\">\n <slot name=\"loading\">\n <tr v-for=\"row in loadingRowCount\" :key=\"row\" data-gr-table-loading-row>\n <td :colspan=\"serviceColSpan\" :class=\"loadingRowCellClass\">\n <GrSkeleton />\n </td>\n </tr>\n </slot>\n </template>\n\n <tr v-else-if=\"isEmpty\" data-gr-table-empty>\n <td :colspan=\"serviceColSpan\" :class=\"emptyCellClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </td>\n </tr>\n\n <slot v-else />\n </tbody>\n <tfoot v-if=\"slots.footer\" class=\"text-[var(--gr-fg)]\">\n <slot name=\"footer\" />\n </tfoot>\n </table>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useSlots } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport GrSkeleton from '../GrSkeleton/GrSkeleton.vue'\nimport { hasMeaningfulSlotContent } from '../shared/slotNodes'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport {\n emptyCellClass,\n hoverableClass,\n loadingRowCellClass,\n stripedClass,\n tableSizes,\n type GrTableSize,\n} from './grTableStyles'\n\nexport interface GrTableProps {\n /**\n * Размер таблицы — базовый кегль текста. Паддинги ячеек оставлены за\n * консьюмером (GrTable — «тонкий» контейнер).\n */\n size?: GrTableSize\n /**\n * Текст caption для screen reader'ов. Рендерится как `<caption class=\"sr-only\">`,\n * если не передан слот `#caption`.\n */\n caption?: string\n /** Прямой ARIA-label для `<table>`. Игнорируется, если задан `ariaLabelledby`. */\n ariaLabel?: string\n /** ID элемента-заголовка, связанного с `<table>` через `aria-labelledby`. */\n ariaLabelledby?: string\n /**\n * ARIA-label для скролл-контейнера. Включает `role=\"region\"`; сам скролл\n * достижим с клавиатуры всегда, независимо от метки.\n */\n regionLabel?: string\n /** Идёт загрузка: вместо строк — скелетоны, контейнер помечен `aria-busy`. */\n loading?: boolean\n /** Сколько строк-заглушек показать при `loading`. */\n loadingRows?: number\n /** Сколько колонок занимает служебная строка (пустое состояние и скелетоны). */\n columnCount?: number\n /** Текст пустого состояния. Слот `#empty` сильнее. */\n emptyText?: string\n /** Таблица пуста. По умолчанию определяется по содержимому слота. */\n empty?: boolean\n /** Чередование строк. */\n striped?: boolean\n /** Подсветка строки под курсором. */\n hoverable?: boolean\n /**\n * Прилипающий заголовок: `<thead>` остаётся видимым при вертикальном скролле.\n * Осмысленно вместе с `maxHeight` (иначе таблица не скроллится вертикально).\n */\n stickyHeader?: boolean\n /**\n * Полное число строк набора, включая строки заголовка (`aria-rowcount`).\n *\n * Нужен, когда в DOM не весь набор — например, при виртуализации: диктор\n * считает строки по разметке и объявил бы «5 из 20» на таблице в десять\n * тысяч. Строки при этом обязаны нести `aria-rowindex`.\n */\n rowCount?: number\n /**\n * Фиксированная раскладка (`table-layout: fixed`): ширины колонок берутся из\n * первой строки, а не из содержимого всех.\n *\n * Обязателен, если в DOM не весь набор: иначе ширины считаются по\n * отрисованному окну и прыгают на каждой прокрутке.\n *\n * Класс — arbitrary-значение, а не `table-fixed`: такого правила в\n * `presetMini` нет, и класс молча не превратился бы в CSS.\n */\n fixedLayout?: boolean\n /**\n * Минимальная ширина самой таблицы (число — пиксели).\n *\n * Нужна при `fixedLayout`: с фиксированной раскладкой и шириной `auto`\n * браузер вписывает таблицу в контейнер и делит место между колонками\n * пропорционально — то есть заданные ширины молча ужимаются, а\n * горизонтальной прокрутки, на которой держатся закреплённые колонки, не\n * возникает вовсе.\n */\n tableMinWidth?: string | number\n /**\n * Максимальная высота скролл-контейнера (включает вертикальный скролл).\n * Число трактуется как пиксели. Нужен для работы `stickyHeader`.\n */\n maxHeight?: string | number\n}\n\n/**\n * `GrTable` — «тонкий» GR-контейнер для табличных данных.\n *\n * Рендерит `<table>` внутри скролл-обёртки и даёт слоты `#caption`, `#header`,\n * default (tbody) и `#footer`. Стили ячеек (`<th>`/`<td>` паддинги, выравнивание)\n * оставлены на консьюмере.\n *\n * ВАЖНО: `min-w-full` сам по себе не даст горизонтального скролла. Для него\n * консьюмеру нужны `white-space: nowrap` на ячейках или явные ширины колонок.\n */\nconst props = withDefaults(defineProps<GrTableProps>(), {\n size: undefined,\n caption: undefined,\n ariaLabel: undefined,\n ariaLabelledby: undefined,\n regionLabel: undefined,\n loading: false,\n loadingRows: 3,\n columnCount: 1,\n emptyText: undefined,\n empty: undefined,\n striped: false,\n hoverable: false,\n stickyHeader: false,\n maxHeight: undefined,\n rowCount: undefined,\n fixedLayout: false,\n tableMinWidth: undefined,\n})\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTable' })\nconst tableTextClass = computed(() => tableSizes[resolvedSize.value])\nconst hasCaption = computed(() => Boolean(slots.caption) || Boolean(props.caption))\n\nconst { t } = useGranularityTranslations()\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.table.empty', 'Nothing here yet'))\n\n// Пустоту видно по слоту: `v-for` по пустому массиву оставляет фрагмент без\n// узлов, `v-if` — комментарий, и ни то ни другое строкой не является.\nconst isEmpty = computed(() => {\n if (props.empty !== undefined)\n return props.empty\n\n return !hasMeaningfulSlotContent(slots.default?.() ?? [])\n})\n\nconst showRows = computed(() => !props.loading && !isEmpty.value)\nconst loadingRowCount = computed(() => Math.max(1, Math.trunc(props.loadingRows)))\nconst serviceColSpan = computed(() => Math.max(1, Math.trunc(props.columnCount)))\n\nconst tbodyClass = computed(() => [\n 'text-[var(--gr-fg)]',\n props.striped && showRows.value ? stripedClass : '',\n props.hoverable && showRows.value ? hoverableClass : '',\n].filter(Boolean).join(' '))\n\nconst scrollStyle = computed(() => {\n // Неполный набор в DOM (`rowCount`) означает виртуализацию, а с ней обязан\n // быть выключен браузерный scroll anchoring: он подправляет `scrollTop`,\n // когда меняется высота содержимого выше видимого узла, — а окно меняет её\n // на каждом кадре прокрутки, и список уезжает.\n const anchor = props.rowCount === undefined ? undefined : { overflowAnchor: 'none' as const }\n\n if (props.maxHeight === undefined)\n return anchor\n\n const value = typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight\n return { ...anchor, maxHeight: value, overflowY: 'auto' as const }\n})\n\n// Прилипающий заголовок: `<thead>` на `position: sticky`; фон обязателен, иначе\n// сквозь него будут просвечивать строки при скролле.\nconst theadClass = computed(() => [\n 'bg-[var(--gr-muted)] text-[var(--gr-muted-fg)]',\n props.stickyHeader ? 'sticky top-0 z-[1]' : '',\n].filter(Boolean).join(' '))\n\nconst tableStyle = computed(() => {\n if (props.tableMinWidth === undefined)\n return undefined\n\n const value = typeof props.tableMinWidth === 'number' ? `${props.tableMinWidth}px` : props.tableMinWidth\n\n return { minWidth: value }\n})\n\nconst scrollEl = ref<HTMLElement | null>(null)\n\nfunction scrollTo(options: ScrollToOptions): void {\n scrollEl.value?.scrollTo(options)\n}\n\n// Только верхний уровень собственного tbody: вложенная таблица в ячейке не\n// должна сдвигать индексацию строк.\nfunction contentRows(): HTMLElement[] {\n if (!showRows.value)\n return []\n const el = scrollEl.value\n if (!el)\n return []\n return Array.from(el.querySelectorAll<HTMLElement>(':scope > table > tbody > tr'))\n}\n\nfunction scrollToRow(index: number, options?: ScrollIntoViewOptions): boolean {\n const row = contentRows()[index]\n if (!row)\n return false\n row.scrollIntoView(options ?? { block: 'nearest' })\n return true\n}\n\ndefineExpose({\n /** Прокрутить скролл-контейнер таблицы — тот же контракт, что у `GrDataTable`. */\n scrollTo,\n /** Прокрутить к строке содержимого по её индексу в разметке. `false` — строки нет в DOM. */\n scrollToRow,\n})\n\ndefineSlots<{\n /** Строки таблицы, когда разметка пишется руками вместо `data`. */\n default?: () => any\n /** Подпись таблицы — `<caption>`, читается диктором первой. */\n caption?: () => any\n /** Шапка вместо построенной по `columns`. */\n header?: () => any\n /** Содержимое, пока едут данные, — вместо строк-заглушек. */\n loading?: () => any\n /** Пустое состояние вместо текста по умолчанию. */\n empty?: () => any\n /** Итоговая строка под таблицей. */\n footer?: () => any\n}>()\n\n/**\n * `relative` на скроллере — не для потомков с координатами, а чтобы он стал\n * containing block. Без него абсолютные потомки (`sr-only`-подсказка у кнопки\n * сортировки — единственный такой в самой таблице, но разметка ячеек чужая)\n * считают позицию от документа и выпадают из прокрутки наружу: на узком экране\n * широкая таблица начинает тащить вбок всю страницу, а не только себя.\n *\n * Живёт здесь, а не над `<div>`: комментарий в корне `<template>` делает\n * компонент фрагментом, и `$el` у потребителя становится Comment-нодой —\n * `GrDataTable` падает на `root.matches` ещё до первого рендера.\n */\n</script>\n\n<template>\n <div\n ref=\"scrollEl\"\n data-gr-table-scroll\n :role=\"regionLabel ? 'region' : undefined\"\n :aria-label=\"regionLabel\"\n :aria-busy=\"loading ? 'true' : undefined\"\n tabindex=\"0\"\n class=\"relative overflow-x-auto rounded-[var(--gr-radius-lg)] border border-[var(--gr-brd)] bg-[var(--gr-card)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n :style=\"scrollStyle\"\n >\n <table\n data-gr-table\n class=\"min-w-full\" :class=\"[tableTextClass, fixedLayout ? '[table-layout:fixed]' : '']\"\n :style=\"tableStyle\"\n :aria-label=\"ariaLabelledby ? undefined : ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-rowcount=\"rowCount\"\n >\n <caption v-if=\"hasCaption\" class=\"sr-only\">\n <slot name=\"caption\">\n{{ caption }}\n</slot>\n </caption>\n <thead :class=\"theadClass\">\n <slot name=\"header\" />\n </thead>\n <tbody :class=\"tbodyClass\">\n <template v-if=\"loading\">\n <slot name=\"loading\">\n <tr v-for=\"row in loadingRowCount\" :key=\"row\" data-gr-table-loading-row>\n <td :colspan=\"serviceColSpan\" :class=\"loadingRowCellClass\">\n <GrSkeleton />\n </td>\n </tr>\n </slot>\n </template>\n\n <tr v-else-if=\"isEmpty\" data-gr-table-empty>\n <td :colspan=\"serviceColSpan\" :class=\"emptyCellClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </td>\n </tr>\n\n <slot v-else />\n </tbody>\n <tfoot v-if=\"slots.footer\" class=\"text-[var(--gr-fg)]\">\n <slot name=\"footer\" />\n </tfoot>\n </table>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrTable-CKJ-HrsN.js","names":[],"sources":["../../../../src/components/GrTable/GrTable.vue","../../../../src/components/GrTable/GrTable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, useSlots } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport GrSkeleton from '../GrSkeleton/GrSkeleton.vue'\nimport { hasMeaningfulSlotContent } from '../shared/slotNodes'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport {\n emptyCellClass,\n hoverableClass,\n loadingRowCellClass,\n stripedClass,\n tableSizes,\n type GrTableSize,\n} from './grTableStyles'\n\nexport interface GrTableProps {\n /**\n * Размер таблицы — базовый кегль текста. Паддинги ячеек оставлены за\n * консьюмером (GrTable — «тонкий» контейнер).\n */\n size?: GrTableSize\n /**\n * Текст caption для screen reader'ов. Рендерится как `<caption class=\"sr-only\">`,\n * если не передан слот `#caption`.\n */\n caption?: string\n /** Прямой ARIA-label для `<table>`. Игнорируется, если задан `ariaLabelledby`. */\n ariaLabel?: string\n /** ID элемента-заголовка, связанного с `<table>` через `aria-labelledby`. */\n ariaLabelledby?: string\n /**\n * ARIA-label для скролл-контейнера. Включает `role=\"region\"`; сам скролл\n * достижим с клавиатуры всегда, независимо от метки.\n */\n regionLabel?: string\n /** Идёт загрузка: вместо строк — скелетоны, контейнер помечен `aria-busy`. */\n loading?: boolean\n /** Сколько строк-заглушек показать при `loading`. */\n loadingRows?: number\n /** Сколько колонок занимает служебная строка (пустое состояние и скелетоны). */\n columnCount?: number\n /** Текст пустого состояния. Слот `#empty` сильнее. */\n emptyText?: string\n /** Таблица пуста. По умолчанию определяется по содержимому слота. */\n empty?: boolean\n /** Чередование строк. */\n striped?: boolean\n /** Подсветка строки под курсором. */\n hoverable?: boolean\n /**\n * Прилипающий заголовок: `<thead>` остаётся видимым при вертикальном скролле.\n * Осмысленно вместе с `maxHeight` (иначе таблица не скроллится вертикально).\n */\n stickyHeader?: boolean\n /**\n * Полное число строк набора, включая строки заголовка (`aria-rowcount`).\n *\n * Нужен, когда в DOM не весь набор — например, при виртуализации: диктор\n * считает строки по разметке и объявил бы «5 из 20» на таблице в десять\n * тысяч. Строки при этом обязаны нести `aria-rowindex`.\n */\n rowCount?: number\n /**\n * Фиксированная раскладка (`table-layout: fixed`): ширины колонок берутся из\n * первой строки, а не из содержимого всех.\n *\n * Обязателен, если в DOM не весь набор: иначе ширины считаются по\n * отрисованному окну и прыгают на каждой прокрутке.\n *\n * Класс — arbitrary-значение, а не `table-fixed`: такого правила в\n * `presetMini` нет, и класс молча не превратился бы в CSS.\n */\n fixedLayout?: boolean\n /**\n * Минимальная ширина самой таблицы (число — пиксели).\n *\n * Нужна при `fixedLayout`: с фиксированной раскладкой и шириной `auto`\n * браузер вписывает таблицу в контейнер и делит место между колонками\n * пропорционально — то есть заданные ширины молча ужимаются, а\n * горизонтальной прокрутки, на которой держатся закреплённые колонки, не\n * возникает вовсе.\n */\n tableMinWidth?: string | number\n /**\n * Максимальная высота скролл-контейнера (включает вертикальный скролл).\n * Число трактуется как пиксели. Нужен для работы `stickyHeader`.\n */\n maxHeight?: string | number\n}\n\n/**\n * `GrTable` — «тонкий» GR-контейнер для табличных данных.\n *\n * Рендерит `<table>` внутри скролл-обёртки и даёт слоты `#caption`, `#header`,\n * default (tbody) и `#footer`. Стили ячеек (`<th>`/`<td>` паддинги, выравнивание)\n * оставлены на консьюмере.\n *\n * ВАЖНО: `min-w-full` сам по себе не даст горизонтального скролла. Для него\n * консьюмеру нужны `white-space: nowrap` на ячейках или явные ширины колонок.\n */\nconst props = withDefaults(defineProps<GrTableProps>(), {\n size: undefined,\n caption: undefined,\n ariaLabel: undefined,\n ariaLabelledby: undefined,\n regionLabel: undefined,\n loading: false,\n loadingRows: 3,\n columnCount: 1,\n emptyText: undefined,\n empty: undefined,\n striped: false,\n hoverable: false,\n stickyHeader: false,\n maxHeight: undefined,\n rowCount: undefined,\n fixedLayout: false,\n tableMinWidth: undefined,\n})\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTable' })\nconst tableTextClass = computed(() => tableSizes[resolvedSize.value])\nconst hasCaption = computed(() => Boolean(slots.caption) || Boolean(props.caption))\n\nconst { t } = useGranularityTranslations()\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.table.empty', 'Nothing here yet'))\n\n// Пустоту видно по слоту: `v-for` по пустому массиву оставляет фрагмент без\n// узлов, `v-if` — комментарий, и ни то ни другое строкой не является.\nconst isEmpty = computed(() => {\n if (props.empty !== undefined)\n return props.empty\n\n return !hasMeaningfulSlotContent(slots.default?.() ?? [])\n})\n\nconst showRows = computed(() => !props.loading && !isEmpty.value)\nconst loadingRowCount = computed(() => Math.max(1, Math.trunc(props.loadingRows)))\nconst serviceColSpan = computed(() => Math.max(1, Math.trunc(props.columnCount)))\n\nconst tbodyClass = computed(() => [\n 'text-[var(--gr-fg)]',\n props.striped && showRows.value ? stripedClass : '',\n props.hoverable && showRows.value ? hoverableClass : '',\n].filter(Boolean).join(' '))\n\nconst scrollStyle = computed(() => {\n // Неполный набор в DOM (`rowCount`) означает виртуализацию, а с ней обязан\n // быть выключен браузерный scroll anchoring: он подправляет `scrollTop`,\n // когда меняется высота содержимого выше видимого узла, — а окно меняет её\n // на каждом кадре прокрутки, и список уезжает.\n const anchor = props.rowCount === undefined ? undefined : { overflowAnchor: 'none' as const }\n\n if (props.maxHeight === undefined)\n return anchor\n\n const value = typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight\n return { ...anchor, maxHeight: value, overflowY: 'auto' as const }\n})\n\n// Прилипающий заголовок: `<thead>` на `position: sticky`; фон обязателен, иначе\n// сквозь него будут просвечивать строки при скролле.\nconst theadClass = computed(() => [\n 'bg-[var(--gr-muted)] text-[var(--gr-muted-fg)]',\n props.stickyHeader ? 'sticky top-0 z-[1]' : '',\n].filter(Boolean).join(' '))\n\nconst tableStyle = computed(() => {\n if (props.tableMinWidth === undefined)\n return undefined\n\n const value = typeof props.tableMinWidth === 'number' ? `${props.tableMinWidth}px` : props.tableMinWidth\n\n return { minWidth: value }\n})\n\nconst scrollEl = ref<HTMLElement | null>(null)\n\nfunction scrollTo(options: ScrollToOptions): void {\n scrollEl.value?.scrollTo(options)\n}\n\n// Только верхний уровень собственного tbody: вложенная таблица в ячейке не\n// должна сдвигать индексацию строк.\nfunction contentRows(): HTMLElement[] {\n if (!showRows.value)\n return []\n const el = scrollEl.value\n if (!el)\n return []\n return Array.from(el.querySelectorAll<HTMLElement>(':scope > table > tbody > tr'))\n}\n\nfunction scrollToRow(index: number, options?: ScrollIntoViewOptions): boolean {\n const row = contentRows()[index]\n if (!row)\n return false\n row.scrollIntoView(options ?? { block: 'nearest' })\n return true\n}\n\ndefineExpose({\n /** Прокрутить скролл-контейнер таблицы — тот же контракт, что у `GrDataTable`. */\n scrollTo,\n /** Прокрутить к строке содержимого по её индексу в разметке. `false` — строки нет в DOM. */\n scrollToRow,\n})\n\ndefineSlots<{\n /** Строки таблицы, когда разметка пишется руками вместо `data`. */\n default?: () => any\n /** Подпись таблицы — `<caption>`, читается диктором первой. */\n caption?: () => any\n /** Шапка вместо построенной по `columns`. */\n header?: () => any\n /** Содержимое, пока едут данные, — вместо строк-заглушек. */\n loading?: () => any\n /** Пустое состояние вместо текста по умолчанию. */\n empty?: () => any\n /** Итоговая строка под таблицей. */\n footer?: () => any\n}>()\n\n/**\n * `relative` на скроллере — не для потомков с координатами, а чтобы он стал\n * containing block. Без него абсолютные потомки (`sr-only`-подсказка у кнопки\n * сортировки — единственный такой в самой таблице, но разметка ячеек чужая)\n * считают позицию от документа и выпадают из прокрутки наружу: на узком экране\n * широкая таблица начинает тащить вбок всю страницу, а не только себя.\n *\n * Живёт здесь, а не над `<div>`: комментарий в корне `<template>` делает\n * компонент фрагментом, и `$el` у потребителя становится Comment-нодой —\n * `GrDataTable` падает на `root.matches` ещё до первого рендера.\n */\n</script>\n\n<template>\n <div\n ref=\"scrollEl\"\n data-gr-table-scroll\n :role=\"regionLabel ? 'region' : undefined\"\n :aria-label=\"regionLabel\"\n :aria-busy=\"loading ? 'true' : undefined\"\n tabindex=\"0\"\n class=\"relative overflow-x-auto rounded-[var(--gr-radius-lg)] border border-[var(--gr-brd)] bg-[var(--gr-card)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n :style=\"scrollStyle\"\n >\n <table\n data-gr-table\n class=\"min-w-full\" :class=\"[tableTextClass, fixedLayout ? '[table-layout:fixed]' : '']\"\n :style=\"tableStyle\"\n :aria-label=\"ariaLabelledby ? undefined : ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-rowcount=\"rowCount\"\n >\n <caption v-if=\"hasCaption\" class=\"sr-only\">\n <slot name=\"caption\">\n{{ caption }}\n</slot>\n </caption>\n <thead :class=\"theadClass\">\n <slot name=\"header\" />\n </thead>\n <tbody :class=\"tbodyClass\">\n <template v-if=\"loading\">\n <slot name=\"loading\">\n <tr v-for=\"row in loadingRowCount\" :key=\"row\" data-gr-table-loading-row>\n <td :colspan=\"serviceColSpan\" :class=\"loadingRowCellClass\">\n <GrSkeleton />\n </td>\n </tr>\n </slot>\n </template>\n\n <tr v-else-if=\"isEmpty\" data-gr-table-empty>\n <td :colspan=\"serviceColSpan\" :class=\"emptyCellClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </td>\n </tr>\n\n <slot v-else />\n </tbody>\n <tfoot v-if=\"slots.footer\" class=\"text-[var(--gr-fg)]\">\n <slot name=\"footer\" />\n </tfoot>\n </table>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useSlots } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport GrSkeleton from '../GrSkeleton/GrSkeleton.vue'\nimport { hasMeaningfulSlotContent } from '../shared/slotNodes'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport {\n emptyCellClass,\n hoverableClass,\n loadingRowCellClass,\n stripedClass,\n tableSizes,\n type GrTableSize,\n} from './grTableStyles'\n\nexport interface GrTableProps {\n /**\n * Размер таблицы — базовый кегль текста. Паддинги ячеек оставлены за\n * консьюмером (GrTable — «тонкий» контейнер).\n */\n size?: GrTableSize\n /**\n * Текст caption для screen reader'ов. Рендерится как `<caption class=\"sr-only\">`,\n * если не передан слот `#caption`.\n */\n caption?: string\n /** Прямой ARIA-label для `<table>`. Игнорируется, если задан `ariaLabelledby`. */\n ariaLabel?: string\n /** ID элемента-заголовка, связанного с `<table>` через `aria-labelledby`. */\n ariaLabelledby?: string\n /**\n * ARIA-label для скролл-контейнера. Включает `role=\"region\"`; сам скролл\n * достижим с клавиатуры всегда, независимо от метки.\n */\n regionLabel?: string\n /** Идёт загрузка: вместо строк — скелетоны, контейнер помечен `aria-busy`. */\n loading?: boolean\n /** Сколько строк-заглушек показать при `loading`. */\n loadingRows?: number\n /** Сколько колонок занимает служебная строка (пустое состояние и скелетоны). */\n columnCount?: number\n /** Текст пустого состояния. Слот `#empty` сильнее. */\n emptyText?: string\n /** Таблица пуста. По умолчанию определяется по содержимому слота. */\n empty?: boolean\n /** Чередование строк. */\n striped?: boolean\n /** Подсветка строки под курсором. */\n hoverable?: boolean\n /**\n * Прилипающий заголовок: `<thead>` остаётся видимым при вертикальном скролле.\n * Осмысленно вместе с `maxHeight` (иначе таблица не скроллится вертикально).\n */\n stickyHeader?: boolean\n /**\n * Полное число строк набора, включая строки заголовка (`aria-rowcount`).\n *\n * Нужен, когда в DOM не весь набор — например, при виртуализации: диктор\n * считает строки по разметке и объявил бы «5 из 20» на таблице в десять\n * тысяч. Строки при этом обязаны нести `aria-rowindex`.\n */\n rowCount?: number\n /**\n * Фиксированная раскладка (`table-layout: fixed`): ширины колонок берутся из\n * первой строки, а не из содержимого всех.\n *\n * Обязателен, если в DOM не весь набор: иначе ширины считаются по\n * отрисованному окну и прыгают на каждой прокрутке.\n *\n * Класс — arbitrary-значение, а не `table-fixed`: такого правила в\n * `presetMini` нет, и класс молча не превратился бы в CSS.\n */\n fixedLayout?: boolean\n /**\n * Минимальная ширина самой таблицы (число — пиксели).\n *\n * Нужна при `fixedLayout`: с фиксированной раскладкой и шириной `auto`\n * браузер вписывает таблицу в контейнер и делит место между колонками\n * пропорционально — то есть заданные ширины молча ужимаются, а\n * горизонтальной прокрутки, на которой держатся закреплённые колонки, не\n * возникает вовсе.\n */\n tableMinWidth?: string | number\n /**\n * Максимальная высота скролл-контейнера (включает вертикальный скролл).\n * Число трактуется как пиксели. Нужен для работы `stickyHeader`.\n */\n maxHeight?: string | number\n}\n\n/**\n * `GrTable` — «тонкий» GR-контейнер для табличных данных.\n *\n * Рендерит `<table>` внутри скролл-обёртки и даёт слоты `#caption`, `#header`,\n * default (tbody) и `#footer`. Стили ячеек (`<th>`/`<td>` паддинги, выравнивание)\n * оставлены на консьюмере.\n *\n * ВАЖНО: `min-w-full` сам по себе не даст горизонтального скролла. Для него\n * консьюмеру нужны `white-space: nowrap` на ячейках или явные ширины колонок.\n */\nconst props = withDefaults(defineProps<GrTableProps>(), {\n size: undefined,\n caption: undefined,\n ariaLabel: undefined,\n ariaLabelledby: undefined,\n regionLabel: undefined,\n loading: false,\n loadingRows: 3,\n columnCount: 1,\n emptyText: undefined,\n empty: undefined,\n striped: false,\n hoverable: false,\n stickyHeader: false,\n maxHeight: undefined,\n rowCount: undefined,\n fixedLayout: false,\n tableMinWidth: undefined,\n})\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTable' })\nconst tableTextClass = computed(() => tableSizes[resolvedSize.value])\nconst hasCaption = computed(() => Boolean(slots.caption) || Boolean(props.caption))\n\nconst { t } = useGranularityTranslations()\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.table.empty', 'Nothing here yet'))\n\n// Пустоту видно по слоту: `v-for` по пустому массиву оставляет фрагмент без\n// узлов, `v-if` — комментарий, и ни то ни другое строкой не является.\nconst isEmpty = computed(() => {\n if (props.empty !== undefined)\n return props.empty\n\n return !hasMeaningfulSlotContent(slots.default?.() ?? [])\n})\n\nconst showRows = computed(() => !props.loading && !isEmpty.value)\nconst loadingRowCount = computed(() => Math.max(1, Math.trunc(props.loadingRows)))\nconst serviceColSpan = computed(() => Math.max(1, Math.trunc(props.columnCount)))\n\nconst tbodyClass = computed(() => [\n 'text-[var(--gr-fg)]',\n props.striped && showRows.value ? stripedClass : '',\n props.hoverable && showRows.value ? hoverableClass : '',\n].filter(Boolean).join(' '))\n\nconst scrollStyle = computed(() => {\n // Неполный набор в DOM (`rowCount`) означает виртуализацию, а с ней обязан\n // быть выключен браузерный scroll anchoring: он подправляет `scrollTop`,\n // когда меняется высота содержимого выше видимого узла, — а окно меняет её\n // на каждом кадре прокрутки, и список уезжает.\n const anchor = props.rowCount === undefined ? undefined : { overflowAnchor: 'none' as const }\n\n if (props.maxHeight === undefined)\n return anchor\n\n const value = typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight\n return { ...anchor, maxHeight: value, overflowY: 'auto' as const }\n})\n\n// Прилипающий заголовок: `<thead>` на `position: sticky`; фон обязателен, иначе\n// сквозь него будут просвечивать строки при скролле.\nconst theadClass = computed(() => [\n 'bg-[var(--gr-muted)] text-[var(--gr-muted-fg)]',\n props.stickyHeader ? 'sticky top-0 z-[1]' : '',\n].filter(Boolean).join(' '))\n\nconst tableStyle = computed(() => {\n if (props.tableMinWidth === undefined)\n return undefined\n\n const value = typeof props.tableMinWidth === 'number' ? `${props.tableMinWidth}px` : props.tableMinWidth\n\n return { minWidth: value }\n})\n\nconst scrollEl = ref<HTMLElement | null>(null)\n\nfunction scrollTo(options: ScrollToOptions): void {\n scrollEl.value?.scrollTo(options)\n}\n\n// Только верхний уровень собственного tbody: вложенная таблица в ячейке не\n// должна сдвигать индексацию строк.\nfunction contentRows(): HTMLElement[] {\n if (!showRows.value)\n return []\n const el = scrollEl.value\n if (!el)\n return []\n return Array.from(el.querySelectorAll<HTMLElement>(':scope > table > tbody > tr'))\n}\n\nfunction scrollToRow(index: number, options?: ScrollIntoViewOptions): boolean {\n const row = contentRows()[index]\n if (!row)\n return false\n row.scrollIntoView(options ?? { block: 'nearest' })\n return true\n}\n\ndefineExpose({\n /** Прокрутить скролл-контейнер таблицы — тот же контракт, что у `GrDataTable`. */\n scrollTo,\n /** Прокрутить к строке содержимого по её индексу в разметке. `false` — строки нет в DOM. */\n scrollToRow,\n})\n\ndefineSlots<{\n /** Строки таблицы, когда разметка пишется руками вместо `data`. */\n default?: () => any\n /** Подпись таблицы — `<caption>`, читается диктором первой. */\n caption?: () => any\n /** Шапка вместо построенной по `columns`. */\n header?: () => any\n /** Содержимое, пока едут данные, — вместо строк-заглушек. */\n loading?: () => any\n /** Пустое состояние вместо текста по умолчанию. */\n empty?: () => any\n /** Итоговая строка под таблицей. */\n footer?: () => any\n}>()\n\n/**\n * `relative` на скроллере — не для потомков с координатами, а чтобы он стал\n * containing block. Без него абсолютные потомки (`sr-only`-подсказка у кнопки\n * сортировки — единственный такой в самой таблице, но разметка ячеек чужая)\n * считают позицию от документа и выпадают из прокрутки наружу: на узком экране\n * широкая таблица начинает тащить вбок всю страницу, а не только себя.\n *\n * Живёт здесь, а не над `<div>`: комментарий в корне `<template>` делает\n * компонент фрагментом, и `$el` у потребителя становится Comment-нодой —\n * `GrDataTable` падает на `root.matches` ещё до первого рендера.\n */\n</script>\n\n<template>\n <div\n ref=\"scrollEl\"\n data-gr-table-scroll\n :role=\"regionLabel ? 'region' : undefined\"\n :aria-label=\"regionLabel\"\n :aria-busy=\"loading ? 'true' : undefined\"\n tabindex=\"0\"\n class=\"relative overflow-x-auto rounded-[var(--gr-radius-lg)] border border-[var(--gr-brd)] bg-[var(--gr-card)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n :style=\"scrollStyle\"\n >\n <table\n data-gr-table\n class=\"min-w-full\" :class=\"[tableTextClass, fixedLayout ? '[table-layout:fixed]' : '']\"\n :style=\"tableStyle\"\n :aria-label=\"ariaLabelledby ? undefined : ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-rowcount=\"rowCount\"\n >\n <caption v-if=\"hasCaption\" class=\"sr-only\">\n <slot name=\"caption\">\n{{ caption }}\n</slot>\n </caption>\n <thead :class=\"theadClass\">\n <slot name=\"header\" />\n </thead>\n <tbody :class=\"tbodyClass\">\n <template v-if=\"loading\">\n <slot name=\"loading\">\n <tr v-for=\"row in loadingRowCount\" :key=\"row\" data-gr-table-loading-row>\n <td :colspan=\"serviceColSpan\" :class=\"loadingRowCellClass\">\n <GrSkeleton />\n </td>\n </tr>\n </slot>\n </template>\n\n <tr v-else-if=\"isEmpty\" data-gr-table-empty>\n <td :colspan=\"serviceColSpan\" :class=\"emptyCellClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </td>\n </tr>\n\n <slot v-else />\n </tbody>\n <tfoot v-if=\"slots.footer\" class=\"text-[var(--gr-fg)]\">\n <slot name=\"footer\" />\n </tfoot>\n </table>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrTable_default } from "./chunks/GrTable-iwzHvlMC.js";
2
- import { n as grTableSafelist, t as grTableConfig } from "../../chunks/config-DCq4JySZ.js";
1
+ import { t as GrTable_default } from "./chunks/GrTable-CKJ-HrsN.js";
2
+ import { n as grTableSafelist, t as grTableConfig } from "../../chunks/config-D3HOuHDe.js";
3
3
  export { GrTable_default as GrTable, GrTable_default as default, grTableConfig, grTableSafelist };
@@ -1,11 +1,13 @@
1
+ import { n as alert_triangle_default, t as check_circle_default } from "../../../chunks/check-circle-Bnrb-CGJ.js";
1
2
  import { t as x_default } from "../../../chunks/x-2KXnqxiD.js";
2
3
  import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CPMRfwVr.js";
3
4
  import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
4
5
  import { vAutosize } from "../../../directives/autosize.js";
5
6
  import { n as useGrFormFieldContext } from "../../../chunks/context-DdNIxa1w.js";
6
7
  import { useGrFormControl } from "../../../composables/useGrFormControl.js";
8
+ import { a as controlStateTextKey, i as controlStateIconColors, n as controlStateFallbackText, r as controlStateIconClass, t as controlSignalState } from "../../../chunks/controlState-DoImKciE.js";
7
9
  import { a as enabledSurfaceClass, c as lineCountClass, i as disabledSurfaceClass, l as resizeClass, n as countClass, o as grTextareaClass, r as countRowClass, u as sizes } from "../../../chunks/grTextareaStyles-Bp35BGna.js";
8
- import { computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeProps, normalizeClass, openBlock, ref, toDisplayString, unref, useId, withDirectives } from "vue";
10
+ import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeProps, normalizeClass, openBlock, ref, resolveDynamicComponent, toDisplayString, unref, useId, withDirectives } from "vue";
9
11
  //#region src/components/GrTextarea/GrTextarea.vue?vue&type=script&setup=true&lang.ts
10
12
  var _hoisted_1 = {
11
13
  key: 0,
@@ -15,11 +17,13 @@ var _hoisted_1 = {
15
17
  var _hoisted_2 = ["aria-label"];
16
18
  var _hoisted_3 = ["id"];
17
19
  var _hoisted_4 = ["id"];
18
- var _hoisted_5 = {
20
+ var _hoisted_5 = ["id"];
21
+ var _hoisted_6 = {
19
22
  key: 1,
20
23
  class: "relative w-full"
21
24
  };
22
- var _hoisted_6 = ["aria-label"];
25
+ var _hoisted_7 = ["aria-label"];
26
+ var _hoisted_8 = ["id"];
23
27
  var baseClass = "w-full rounded-[var(--gr-radius-control)] border text-[var(--gr-fg)] placeholder:text-[var(--gr-muted-fg)] transition-colors duration-[var(--gr-duration-fast)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)] disabled:cursor-not-allowed";
24
28
  //#endregion
25
29
  //#region src/components/GrTextarea/GrTextarea.vue
@@ -91,16 +95,25 @@ var GrTextarea_default = /* @__PURE__ */ defineComponent({
91
95
  const resolvedId = computed(() => props.id ?? field?.id.value);
92
96
  const countId = useId();
93
97
  const lineCountId = useId();
94
- const describedBy = computed(() => [
95
- field?.describedById.value,
96
- props.showCount ? countId : void 0,
97
- props.showLineCount ? lineCountId : void 0
98
- ].filter(Boolean).join(" ") || void 0);
98
+ const stateTextId = useId();
99
99
  /** Обёртка нужна любому из счётчиков — и кнопке очистки. */
100
100
  const hasCounters = computed(() => props.showCount || props.showLineCount);
101
101
  const lineCount = computed(() => props.modelValue.split("\n").length);
102
102
  const countText = computed(() => props.maxlength !== void 0 ? `${props.modelValue.length} / ${props.maxlength}` : String(props.modelValue.length));
103
103
  const { disabled: isDisabled, invalid: isInvalid, required: isRequired, readonly: isReadonly } = useGrFormControl(() => props);
104
+ /**
105
+ * Небуквенный признак состояния: иконка для глаз, скрытая подпись для
106
+ * скринридера. Разбор — `shared/controlState`.
107
+ */
108
+ const signalState = computed(() => controlSignalState(props.state, isInvalid.value));
109
+ const stateIcon = computed(() => signalState.value === "success" ? check_circle_default : alert_triangle_default);
110
+ const stateIconClass = computed(() => signalState.value ? `${controlStateIconClass} ${controlStateIconColors[signalState.value]}` : "");
111
+ const describedBy = computed(() => [
112
+ field?.describedById.value,
113
+ props.showCount ? countId : void 0,
114
+ props.showLineCount ? lineCountId : void 0,
115
+ signalState.value ? stateTextId : void 0
116
+ ].filter(Boolean).join(" ") || void 0);
104
117
  const textareaEl = ref(null);
105
118
  function focus() {
106
119
  textareaEl.value?.focus();
@@ -115,6 +128,7 @@ var GrTextarea_default = /* @__PURE__ */ defineComponent({
115
128
  const resolvedSize = useGrComponentSize(() => props.size, { component: "GrTextarea" });
116
129
  const resolvedClearable = useGrComponentProp("GrTextarea", "clearable", () => props.clearable, false);
117
130
  const { t } = useGranularityTranslations();
131
+ const stateText = computed(() => signalState.value ? t(controlStateTextKey[signalState.value], controlStateFallbackText[signalState.value]) : "");
118
132
  const resolvedClearLabel = computed(() => props.clearLabel ?? t("gr.input.clear", "Clear"));
119
133
  /** С `maxLines` — «3 / 10», без него — локализованная подпись с формой числа. */
120
134
  const lineCountText = computed(() => props.maxLines !== void 0 ? `${lineCount.value} / ${props.maxLines}` : t("gr.textarea.lines", "{n} lines", { n: lineCount.value }));
@@ -189,39 +203,66 @@ var GrTextarea_default = /* @__PURE__ */ defineComponent({
189
203
  class: "h-4 w-4",
190
204
  "aria-hidden": "true"
191
205
  })], 8, _hoisted_2)) : createCommentVNode("", true),
206
+ signalState.value ? (openBlock(), createElementBlock("span", {
207
+ key: 1,
208
+ "data-gr-textarea-state": "",
209
+ class: normalizeClass(["absolute top-2", [stateIconClass.value, showClear.value ? "right-10" : "right-2"]]),
210
+ "aria-hidden": "true"
211
+ }, [(openBlock(), createBlock(resolveDynamicComponent(stateIcon.value), { class: "h-4 w-4" }))], 2)) : createCommentVNode("", true),
212
+ signalState.value ? (openBlock(), createElementBlock("span", {
213
+ key: 2,
214
+ id: unref(stateTextId),
215
+ "data-gr-textarea-state-text": "",
216
+ class: "sr-only"
217
+ }, toDisplayString(stateText.value), 9, _hoisted_3)) : createCommentVNode("", true),
192
218
  createElementVNode("div", { class: normalizeClass(unref(countRowClass)) }, [__props.showLineCount ? (openBlock(), createElementBlock("div", {
193
219
  key: 0,
194
220
  id: unref(lineCountId),
195
221
  "data-gr-textarea-line-count": "",
196
222
  class: normalizeClass(unref(lineCountClass))
197
- }, toDisplayString(lineCountText.value), 11, _hoisted_3)) : createCommentVNode("", true), __props.showCount ? (openBlock(), createElementBlock("div", {
223
+ }, toDisplayString(lineCountText.value), 11, _hoisted_4)) : createCommentVNode("", true), __props.showCount ? (openBlock(), createElementBlock("div", {
198
224
  key: 1,
199
225
  id: unref(countId),
200
226
  "data-gr-textarea-count": "",
201
227
  class: normalizeClass(["ml-auto", unref(countClass)])
202
- }, toDisplayString(countText.value), 11, _hoisted_4)) : createCommentVNode("", true)], 2)
203
- ])) : unref(resolvedClearable) ? (openBlock(), createElementBlock("div", _hoisted_5, [withDirectives(createElementVNode("textarea", mergeProps({
204
- ref_key: "textareaEl",
205
- ref: textareaEl
206
- }, {
207
- ...textareaAttrs.value,
208
- ..._ctx.$attrs
209
- }, {
210
- onInput,
211
- onChange,
212
- onFocus,
213
- onBlur
214
- }), null, 16), [[unref(vAutosize), __props.autosize]]), showClear.value ? (openBlock(), createElementBlock("button", {
215
- key: 0,
216
- type: "button",
217
- "data-gr-textarea-clear": "",
218
- "aria-label": resolvedClearLabel.value,
219
- class: "absolute right-2 top-2 flex h-6 w-6 items-center justify-center rounded-[var(--gr-radius-sm)] text-[var(--gr-muted-fg)] transition-colors hover:bg-[var(--gr-muted)] hover:text-[var(--gr-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]",
220
- onClick: clear
221
- }, [createVNode(unref(x_default), {
222
- class: "h-4 w-4",
223
- "aria-hidden": "true"
224
- })], 8, _hoisted_6)) : createCommentVNode("", true)])) : withDirectives((openBlock(), createElementBlock("textarea", mergeProps({
228
+ }, toDisplayString(countText.value), 11, _hoisted_5)) : createCommentVNode("", true)], 2)
229
+ ])) : unref(resolvedClearable) || signalState.value ? (openBlock(), createElementBlock("div", _hoisted_6, [
230
+ withDirectives(createElementVNode("textarea", mergeProps({
231
+ ref_key: "textareaEl",
232
+ ref: textareaEl
233
+ }, {
234
+ ...textareaAttrs.value,
235
+ ..._ctx.$attrs
236
+ }, {
237
+ onInput,
238
+ onChange,
239
+ onFocus,
240
+ onBlur
241
+ }), null, 16), [[unref(vAutosize), __props.autosize]]),
242
+ showClear.value ? (openBlock(), createElementBlock("button", {
243
+ key: 0,
244
+ type: "button",
245
+ "data-gr-textarea-clear": "",
246
+ "aria-label": resolvedClearLabel.value,
247
+ class: "absolute right-2 top-2 flex h-6 w-6 items-center justify-center rounded-[var(--gr-radius-sm)] text-[var(--gr-muted-fg)] transition-colors hover:bg-[var(--gr-muted)] hover:text-[var(--gr-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]",
248
+ onClick: clear
249
+ }, [createVNode(unref(x_default), {
250
+ class: "h-4 w-4",
251
+ "aria-hidden": "true"
252
+ })], 8, _hoisted_7)) : createCommentVNode("", true),
253
+ signalState.value ? (openBlock(), createElementBlock("span", {
254
+ key: 1,
255
+ "data-gr-textarea-state": "",
256
+ class: normalizeClass(["absolute top-2", [stateIconClass.value, showClear.value ? "right-10" : "right-2"]]),
257
+ "aria-hidden": "true"
258
+ }, [(openBlock(), createBlock(resolveDynamicComponent(stateIcon.value), { class: "h-4 w-4" }))], 2)) : createCommentVNode("", true),
259
+ signalState.value ? (openBlock(), createElementBlock("span", {
260
+ key: 2,
261
+ id: unref(stateTextId),
262
+ "data-gr-textarea-state-text": "",
263
+ class: "sr-only"
264
+ }, toDisplayString(stateText.value), 9, _hoisted_8)) : createCommentVNode("", true)
265
+ ])) : withDirectives((openBlock(), createElementBlock("textarea", mergeProps({
225
266
  key: 2,
226
267
  ref_key: "textareaEl",
227
268
  ref: textareaEl
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrTextarea-Bfgc0DD2.js","names":["$attrs"],"sources":["../../../../src/components/GrTextarea/GrTextarea.vue","../../../../src/components/GrTextarea/GrTextarea.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrTextarea — многострочное поле ввода GR-примитива.\n *\n * Состояния:\n * - `state`: визуальный оттенок рамки (`default | success | warning | danger`).\n * - `invalid`: форсирует `danger`-состояние и проставляет `aria-invalid=\"true\"`.\n */\nimport { computed, ref, useId } from 'vue'\nimport {\n countClass,\n countRowClass,\n lineCountClass,\n disabledSurfaceClass,\n enabledSurfaceClass,\n grTextareaClass,\n resizeClass,\n sizes,\n type GrTextareaResize,\n type GrTextareaSize,\n type GrTextareaState,\n} from './grTextareaStyles'\nimport IconX from '~icons/lucide/x'\nimport IconCheckCircle from '~icons/lucide/check-circle'\nimport IconAlertTriangle from '~icons/lucide/alert-triangle'\nimport { vAutosize } from '../../directives'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport {\n controlSignalState,\n controlStateFallbackText,\n controlStateIconClass,\n controlStateIconColors,\n controlStateTextKey,\n} from '../shared/controlState'\n\nexport interface GrTextareaProps {\n modelValue: string\n placeholder?: string\n autocomplete?: string\n disabled?: boolean\n /** Только для чтения: значение видно и уходит в форму, но не редактируется. */\n readonly?: boolean\n invalid?: boolean\n /** Обязательное поле (`aria-required`). Складывается с `required` у `GrFormField`. */\n required?: boolean\n /** Доступное имя вне `GrFormField`. */\n ariaLabel?: string\n state?: GrTextareaState\n name?: string\n id?: string\n rows?: number\n size?: GrTextareaSize\n /** Ограничение длины + основа для счётчика символов. */\n maxlength?: number\n /** Показывать счётчик символов (`len` или `len/maxlength`). */\n showCount?: boolean\n /**\n * Показывать счётчик строк. Считаются **логические** строки (переводы строки), а\n * не визуальные переносы: при `autosize` число не меняется от ширины поля.\n */\n showLineCount?: boolean\n /**\n * Ориентир по числу строк для счётчика (`3 / 10`). Ввод не ограничивает: обрезать\n * набранный текст за пользователя компонент не вправе.\n */\n maxLines?: number\n /** Подгонять высоту под содержимое (директива `v-autosize`). */\n autosize?: boolean\n /** Кнопка очистки значения. Настраивается через `GrConfigProvider`. */\n clearable?: boolean\n /** A11y-подпись кнопки очистки. */\n clearLabel?: string\n /** Ручное изменение размера пользователем. */\n resize?: GrTextareaResize\n}\n\nexport interface GrTextareaEmits {\n (e: 'update:modelValue', value: string): void\n /** Значение зафиксировано нативным `change` — по `blur`. */\n (e: 'change', value: string): void\n /** Значение стёрто кнопкой очистки. */\n (e: 'clear'): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(defineProps<GrTextareaProps>(), {\n placeholder: undefined,\n autocomplete: undefined,\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n ariaLabel: undefined,\n state: 'default',\n name: undefined,\n id: undefined,\n rows: 4,\n size: undefined,\n maxlength: undefined,\n showCount: false,\n autosize: false,\n clearable: undefined,\n clearLabel: undefined,\n resize: 'vertical',\n})\n\ndefineOptions({\n // Иначе атрибуты потребителя (`data-*`, `aria-*`, `name`) садятся на корень,\n // а корень со `showCount` — обёртка счётчика, а не само поле.\n inheritAttrs: false,\n})\n\nconst emit = defineEmits<GrTextareaEmits>()\n\n// Fallback из контекста `GrFormField` (id/aria-describedby/invalid/required).\nconst field = useGrFormFieldContext()\nconst resolvedId = computed(() => props.id ?? field?.id.value)\n\n// Счётчик обязан быть частью описания поля: иначе «12 / 60» видно глазами, но\n// не слышно — при том что ограничение длины и есть его смысл.\nconst countId = useId()\nconst lineCountId = useId()\nconst stateTextId = useId()\n\n/** Обёртка нужна любому из счётчиков — и кнопке очистки. */\nconst hasCounters = computed(() => props.showCount || props.showLineCount)\n\nconst lineCount = computed(() => props.modelValue.split('\\n').length)\n\nconst countText = computed(() =>\n props.maxlength !== undefined ? `${props.modelValue.length} / ${props.maxlength}` : String(props.modelValue.length),\n)\nconst {\n disabled: isDisabled,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\n/**\n * Небуквенный признак состояния: иконка для глаз, скрытая подпись для\n * скринридера. Разбор — `shared/controlState`.\n */\nconst signalState = computed(() => controlSignalState(props.state, isInvalid.value))\nconst stateIcon = computed(() => (signalState.value === 'success' ? IconCheckCircle : IconAlertTriangle))\nconst stateIconClass = computed(() => (signalState.value\n ? `${controlStateIconClass} ${controlStateIconColors[signalState.value]}`\n : ''))\n\nconst describedBy = computed(() =>\n [\n field?.describedById.value,\n props.showCount ? countId : undefined,\n props.showLineCount ? lineCountId : undefined,\n signalState.value ? stateTextId : undefined,\n ]\n .filter(Boolean)\n .join(' ') || undefined,\n)\n\nconst textareaEl = ref<HTMLTextAreaElement | null>(null)\n\nfunction focus(): void {\n textareaEl.value?.focus()\n}\n\nfunction blur(): void {\n textareaEl.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTextarea' })\nconst resolvedClearable = useGrComponentProp('GrTextarea', 'clearable', () => props.clearable, false)\n\nconst { t } = useGranularityTranslations()\n\nconst stateText = computed(() => (signalState.value\n ? t(controlStateTextKey[signalState.value], controlStateFallbackText[signalState.value])\n : ''))\nconst resolvedClearLabel = computed(() => props.clearLabel ?? t('gr.input.clear', 'Clear'))\n\n/** С `maxLines` — «3 / 10», без него — локализованная подпись с формой числа. */\nconst lineCountText = computed(() => (\n props.maxLines !== undefined\n ? `${lineCount.value} / ${props.maxLines}`\n : t('gr.textarea.lines', '{n} lines', { n: lineCount.value })\n))\n\nconst showClear = computed(() =>\n resolvedClearable.value && !isDisabled.value && !isReadonly.value && props.modelValue !== '',\n)\n\nfunction clear(): void {\n emit('update:modelValue', '')\n emit('change', '')\n emit('clear')\n focus()\n}\n\nconst baseClass = 'w-full rounded-[var(--gr-radius-control)] border text-[var(--gr-fg)] placeholder:text-[var(--gr-muted-fg)] transition-colors duration-[var(--gr-duration-fast)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)] disabled:cursor-not-allowed'\n\nconst className = computed(() => [\n sizes[resolvedSize.value],\n resizeClass[props.resize],\n isDisabled.value ? disabledSurfaceClass : enabledSurfaceClass,\n grTextareaClass({\n state: props.state,\n invalid: isInvalid.value,\n }),\n].join(' '))\n\n// Обе ветки шаблона (со счётчиком и без) рендерят одно и то же поле, поэтому\n// атрибуты живут одним объектом: двадцать строк копипасты расходятся молча.\nconst textareaAttrs = computed(() => ({\n 'id': resolvedId.value,\n 'data-gr-textarea': '',\n 'name': props.name,\n 'rows': props.rows,\n 'maxlength': props.maxlength,\n 'autocomplete': props.autocomplete,\n 'placeholder': props.placeholder,\n 'disabled': isDisabled.value,\n 'value': props.modelValue,\n 'aria-invalid': isInvalid.value ? ('true' as const) : undefined,\n 'aria-describedby': describedBy.value,\n 'aria-required': isRequired.value ? ('true' as const) : undefined,\n 'aria-readonly': isReadonly.value ? ('true' as const) : undefined,\n 'aria-label': props.ariaLabel,\n 'readonly': isReadonly.value,\n 'class': [baseClass, className.value],\n}))\n\nfunction onInput(e: Event): void {\n emit('update:modelValue', (e.target as HTMLTextAreaElement).value)\n}\n\n// Объявленный emit уходит из `$attrs`, поэтому нативные события переизлучаем\n// руками — иначе `@change`/`@focus`/`@blur` у потребителя перестали бы работать.\nfunction onChange(e: Event): void {\n emit('change', (e.target as HTMLTextAreaElement).value)\n}\n\nfunction onFocus(e: FocusEvent): void {\n emit('focus', e)\n}\n\nfunction onBlur(e: FocusEvent): void {\n emit('blur', e)\n}\n</script>\n\n<template>\n <div v-if=\"hasCounters\" data-gr-textarea-wrap class=\"relative w-full\">\n <textarea\n ref=\"textareaEl\"\n v-autosize=\"autosize\"\n v-bind=\"{ ...textareaAttrs, ...$attrs }\"\n @input=\"onInput\"\n @change=\"onChange\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n />\n\n <button\n v-if=\"showClear\"\n type=\"button\"\n data-gr-textarea-clear\n :aria-label=\"resolvedClearLabel\"\n class=\"absolute right-2 top-2 flex h-6 w-6 items-center justify-center rounded-[var(--gr-radius-sm)] text-[var(--gr-muted-fg)] transition-colors hover:bg-[var(--gr-muted)] hover:text-[var(--gr-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n @click=\"clear\"\n >\n <IconX class=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n\n <span\n v-if=\"signalState\"\n data-gr-textarea-state\n class=\"absolute top-2\" :class=\"[stateIconClass, showClear ? 'right-10' : 'right-2']\"\n aria-hidden=\"true\"\n >\n <component :is=\"stateIcon\" class=\"h-4 w-4\" />\n </span>\n\n <span v-if=\"signalState\" :id=\"stateTextId\" data-gr-textarea-state-text class=\"sr-only\">{{ stateText }}</span>\n\n <div :class=\"countRowClass\">\n <div\n v-if=\"showLineCount\"\n :id=\"lineCountId\"\n data-gr-textarea-line-count\n :class=\"lineCountClass\"\n >\n {{ lineCountText }}\n </div>\n\n <!-- Символьный счётчик всегда прижат вправо: без счётчика строк он остаётся\n единственным в ряду, и `justify-between` его туда и отправляет. -->\n <div\n v-if=\"showCount\"\n :id=\"countId\"\n data-gr-textarea-count\n class=\"ml-auto\"\n :class=\"countClass\"\n >\n {{ countText }}\n </div>\n </div>\n </div>\n\n <!-- Обёртка появляется под кнопку очистки и под признак состояния: без них\n поле остаётся корневым элементом — на этом стоит контракт\n fallthrough-атрибутов. -->\n <div v-else-if=\"resolvedClearable || signalState\" class=\"relative w-full\">\n <textarea\n ref=\"textareaEl\"\n v-autosize=\"autosize\"\n v-bind=\"{ ...textareaAttrs, ...$attrs }\"\n @input=\"onInput\"\n @change=\"onChange\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n />\n\n <button\n v-if=\"showClear\"\n type=\"button\"\n data-gr-textarea-clear\n :aria-label=\"resolvedClearLabel\"\n class=\"absolute right-2 top-2 flex h-6 w-6 items-center justify-center rounded-[var(--gr-radius-sm)] text-[var(--gr-muted-fg)] transition-colors hover:bg-[var(--gr-muted)] hover:text-[var(--gr-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n @click=\"clear\"\n >\n <IconX class=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n\n <span\n v-if=\"signalState\"\n data-gr-textarea-state\n class=\"absolute top-2\" :class=\"[stateIconClass, showClear ? 'right-10' : 'right-2']\"\n aria-hidden=\"true\"\n >\n <component :is=\"stateIcon\" class=\"h-4 w-4\" />\n </span>\n\n <span v-if=\"signalState\" :id=\"stateTextId\" data-gr-textarea-state-text class=\"sr-only\">{{ stateText }}</span>\n </div>\n\n <textarea\n v-else\n ref=\"textareaEl\"\n v-autosize=\"autosize\"\n v-bind=\"{ ...textareaAttrs, ...$attrs }\"\n @input=\"onInput\"\n @change=\"onChange\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrTextarea — многострочное поле ввода GR-примитива.\n *\n * Состояния:\n * - `state`: визуальный оттенок рамки (`default | success | warning | danger`).\n * - `invalid`: форсирует `danger`-состояние и проставляет `aria-invalid=\"true\"`.\n */\nimport { computed, ref, useId } from 'vue'\nimport {\n countClass,\n countRowClass,\n lineCountClass,\n disabledSurfaceClass,\n enabledSurfaceClass,\n grTextareaClass,\n resizeClass,\n sizes,\n type GrTextareaResize,\n type GrTextareaSize,\n type GrTextareaState,\n} from './grTextareaStyles'\nimport IconX from '~icons/lucide/x'\nimport IconCheckCircle from '~icons/lucide/check-circle'\nimport IconAlertTriangle from '~icons/lucide/alert-triangle'\nimport { vAutosize } from '../../directives'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport {\n controlSignalState,\n controlStateFallbackText,\n controlStateIconClass,\n controlStateIconColors,\n controlStateTextKey,\n} from '../shared/controlState'\n\nexport interface GrTextareaProps {\n modelValue: string\n placeholder?: string\n autocomplete?: string\n disabled?: boolean\n /** Только для чтения: значение видно и уходит в форму, но не редактируется. */\n readonly?: boolean\n invalid?: boolean\n /** Обязательное поле (`aria-required`). Складывается с `required` у `GrFormField`. */\n required?: boolean\n /** Доступное имя вне `GrFormField`. */\n ariaLabel?: string\n state?: GrTextareaState\n name?: string\n id?: string\n rows?: number\n size?: GrTextareaSize\n /** Ограничение длины + основа для счётчика символов. */\n maxlength?: number\n /** Показывать счётчик символов (`len` или `len/maxlength`). */\n showCount?: boolean\n /**\n * Показывать счётчик строк. Считаются **логические** строки (переводы строки), а\n * не визуальные переносы: при `autosize` число не меняется от ширины поля.\n */\n showLineCount?: boolean\n /**\n * Ориентир по числу строк для счётчика (`3 / 10`). Ввод не ограничивает: обрезать\n * набранный текст за пользователя компонент не вправе.\n */\n maxLines?: number\n /** Подгонять высоту под содержимое (директива `v-autosize`). */\n autosize?: boolean\n /** Кнопка очистки значения. Настраивается через `GrConfigProvider`. */\n clearable?: boolean\n /** A11y-подпись кнопки очистки. */\n clearLabel?: string\n /** Ручное изменение размера пользователем. */\n resize?: GrTextareaResize\n}\n\nexport interface GrTextareaEmits {\n (e: 'update:modelValue', value: string): void\n /** Значение зафиксировано нативным `change` — по `blur`. */\n (e: 'change', value: string): void\n /** Значение стёрто кнопкой очистки. */\n (e: 'clear'): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(defineProps<GrTextareaProps>(), {\n placeholder: undefined,\n autocomplete: undefined,\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n ariaLabel: undefined,\n state: 'default',\n name: undefined,\n id: undefined,\n rows: 4,\n size: undefined,\n maxlength: undefined,\n showCount: false,\n autosize: false,\n clearable: undefined,\n clearLabel: undefined,\n resize: 'vertical',\n})\n\ndefineOptions({\n // Иначе атрибуты потребителя (`data-*`, `aria-*`, `name`) садятся на корень,\n // а корень со `showCount` — обёртка счётчика, а не само поле.\n inheritAttrs: false,\n})\n\nconst emit = defineEmits<GrTextareaEmits>()\n\n// Fallback из контекста `GrFormField` (id/aria-describedby/invalid/required).\nconst field = useGrFormFieldContext()\nconst resolvedId = computed(() => props.id ?? field?.id.value)\n\n// Счётчик обязан быть частью описания поля: иначе «12 / 60» видно глазами, но\n// не слышно — при том что ограничение длины и есть его смысл.\nconst countId = useId()\nconst lineCountId = useId()\nconst stateTextId = useId()\n\n/** Обёртка нужна любому из счётчиков — и кнопке очистки. */\nconst hasCounters = computed(() => props.showCount || props.showLineCount)\n\nconst lineCount = computed(() => props.modelValue.split('\\n').length)\n\nconst countText = computed(() =>\n props.maxlength !== undefined ? `${props.modelValue.length} / ${props.maxlength}` : String(props.modelValue.length),\n)\nconst {\n disabled: isDisabled,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\n/**\n * Небуквенный признак состояния: иконка для глаз, скрытая подпись для\n * скринридера. Разбор — `shared/controlState`.\n */\nconst signalState = computed(() => controlSignalState(props.state, isInvalid.value))\nconst stateIcon = computed(() => (signalState.value === 'success' ? IconCheckCircle : IconAlertTriangle))\nconst stateIconClass = computed(() => (signalState.value\n ? `${controlStateIconClass} ${controlStateIconColors[signalState.value]}`\n : ''))\n\nconst describedBy = computed(() =>\n [\n field?.describedById.value,\n props.showCount ? countId : undefined,\n props.showLineCount ? lineCountId : undefined,\n signalState.value ? stateTextId : undefined,\n ]\n .filter(Boolean)\n .join(' ') || undefined,\n)\n\nconst textareaEl = ref<HTMLTextAreaElement | null>(null)\n\nfunction focus(): void {\n textareaEl.value?.focus()\n}\n\nfunction blur(): void {\n textareaEl.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTextarea' })\nconst resolvedClearable = useGrComponentProp('GrTextarea', 'clearable', () => props.clearable, false)\n\nconst { t } = useGranularityTranslations()\n\nconst stateText = computed(() => (signalState.value\n ? t(controlStateTextKey[signalState.value], controlStateFallbackText[signalState.value])\n : ''))\nconst resolvedClearLabel = computed(() => props.clearLabel ?? t('gr.input.clear', 'Clear'))\n\n/** С `maxLines` — «3 / 10», без него — локализованная подпись с формой числа. */\nconst lineCountText = computed(() => (\n props.maxLines !== undefined\n ? `${lineCount.value} / ${props.maxLines}`\n : t('gr.textarea.lines', '{n} lines', { n: lineCount.value })\n))\n\nconst showClear = computed(() =>\n resolvedClearable.value && !isDisabled.value && !isReadonly.value && props.modelValue !== '',\n)\n\nfunction clear(): void {\n emit('update:modelValue', '')\n emit('change', '')\n emit('clear')\n focus()\n}\n\nconst baseClass = 'w-full rounded-[var(--gr-radius-control)] border text-[var(--gr-fg)] placeholder:text-[var(--gr-muted-fg)] transition-colors duration-[var(--gr-duration-fast)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)] disabled:cursor-not-allowed'\n\nconst className = computed(() => [\n sizes[resolvedSize.value],\n resizeClass[props.resize],\n isDisabled.value ? disabledSurfaceClass : enabledSurfaceClass,\n grTextareaClass({\n state: props.state,\n invalid: isInvalid.value,\n }),\n].join(' '))\n\n// Обе ветки шаблона (со счётчиком и без) рендерят одно и то же поле, поэтому\n// атрибуты живут одним объектом: двадцать строк копипасты расходятся молча.\nconst textareaAttrs = computed(() => ({\n 'id': resolvedId.value,\n 'data-gr-textarea': '',\n 'name': props.name,\n 'rows': props.rows,\n 'maxlength': props.maxlength,\n 'autocomplete': props.autocomplete,\n 'placeholder': props.placeholder,\n 'disabled': isDisabled.value,\n 'value': props.modelValue,\n 'aria-invalid': isInvalid.value ? ('true' as const) : undefined,\n 'aria-describedby': describedBy.value,\n 'aria-required': isRequired.value ? ('true' as const) : undefined,\n 'aria-readonly': isReadonly.value ? ('true' as const) : undefined,\n 'aria-label': props.ariaLabel,\n 'readonly': isReadonly.value,\n 'class': [baseClass, className.value],\n}))\n\nfunction onInput(e: Event): void {\n emit('update:modelValue', (e.target as HTMLTextAreaElement).value)\n}\n\n// Объявленный emit уходит из `$attrs`, поэтому нативные события переизлучаем\n// руками — иначе `@change`/`@focus`/`@blur` у потребителя перестали бы работать.\nfunction onChange(e: Event): void {\n emit('change', (e.target as HTMLTextAreaElement).value)\n}\n\nfunction onFocus(e: FocusEvent): void {\n emit('focus', e)\n}\n\nfunction onBlur(e: FocusEvent): void {\n emit('blur', e)\n}\n</script>\n\n<template>\n <div v-if=\"hasCounters\" data-gr-textarea-wrap class=\"relative w-full\">\n <textarea\n ref=\"textareaEl\"\n v-autosize=\"autosize\"\n v-bind=\"{ ...textareaAttrs, ...$attrs }\"\n @input=\"onInput\"\n @change=\"onChange\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n />\n\n <button\n v-if=\"showClear\"\n type=\"button\"\n data-gr-textarea-clear\n :aria-label=\"resolvedClearLabel\"\n class=\"absolute right-2 top-2 flex h-6 w-6 items-center justify-center rounded-[var(--gr-radius-sm)] text-[var(--gr-muted-fg)] transition-colors hover:bg-[var(--gr-muted)] hover:text-[var(--gr-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n @click=\"clear\"\n >\n <IconX class=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n\n <span\n v-if=\"signalState\"\n data-gr-textarea-state\n class=\"absolute top-2\" :class=\"[stateIconClass, showClear ? 'right-10' : 'right-2']\"\n aria-hidden=\"true\"\n >\n <component :is=\"stateIcon\" class=\"h-4 w-4\" />\n </span>\n\n <span v-if=\"signalState\" :id=\"stateTextId\" data-gr-textarea-state-text class=\"sr-only\">{{ stateText }}</span>\n\n <div :class=\"countRowClass\">\n <div\n v-if=\"showLineCount\"\n :id=\"lineCountId\"\n data-gr-textarea-line-count\n :class=\"lineCountClass\"\n >\n {{ lineCountText }}\n </div>\n\n <!-- Символьный счётчик всегда прижат вправо: без счётчика строк он остаётся\n единственным в ряду, и `justify-between` его туда и отправляет. -->\n <div\n v-if=\"showCount\"\n :id=\"countId\"\n data-gr-textarea-count\n class=\"ml-auto\"\n :class=\"countClass\"\n >\n {{ countText }}\n </div>\n </div>\n </div>\n\n <!-- Обёртка появляется под кнопку очистки и под признак состояния: без них\n поле остаётся корневым элементом — на этом стоит контракт\n fallthrough-атрибутов. -->\n <div v-else-if=\"resolvedClearable || signalState\" class=\"relative w-full\">\n <textarea\n ref=\"textareaEl\"\n v-autosize=\"autosize\"\n v-bind=\"{ ...textareaAttrs, ...$attrs }\"\n @input=\"onInput\"\n @change=\"onChange\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n />\n\n <button\n v-if=\"showClear\"\n type=\"button\"\n data-gr-textarea-clear\n :aria-label=\"resolvedClearLabel\"\n class=\"absolute right-2 top-2 flex h-6 w-6 items-center justify-center rounded-[var(--gr-radius-sm)] text-[var(--gr-muted-fg)] transition-colors hover:bg-[var(--gr-muted)] hover:text-[var(--gr-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n @click=\"clear\"\n >\n <IconX class=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n\n <span\n v-if=\"signalState\"\n data-gr-textarea-state\n class=\"absolute top-2\" :class=\"[stateIconClass, showClear ? 'right-10' : 'right-2']\"\n aria-hidden=\"true\"\n >\n <component :is=\"stateIcon\" class=\"h-4 w-4\" />\n </span>\n\n <span v-if=\"signalState\" :id=\"stateTextId\" data-gr-textarea-state-text class=\"sr-only\">{{ stateText }}</span>\n </div>\n\n <textarea\n v-else\n ref=\"textareaEl\"\n v-autosize=\"autosize\"\n v-bind=\"{ ...textareaAttrs, ...$attrs }\"\n @input=\"onInput\"\n @change=\"onChange\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n />\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrTextarea_default } from "./chunks/GrTextarea-BII3w61K.js";
2
- import { n as grTextareaSafelist, t as grTextareaConfig } from "../../chunks/config-BhfNgyWL.js";
1
+ import { t as GrTextarea_default } from "./chunks/GrTextarea-Bfgc0DD2.js";
2
+ import { n as grTextareaSafelist, t as grTextareaConfig } from "../../chunks/config-DENqOoh0.js";
3
3
  export { GrTextarea_default as GrTextarea, GrTextarea_default as default, grTextareaConfig, grTextareaSafelist };
@@ -1,6 +1,7 @@
1
- import { n as check_circle_default, r as alert_triangle_default, t as x_circle_default } from "../../../chunks/x-circle-BCBURwyX.js";
1
+ import { n as alert_triangle_default, t as check_circle_default } from "../../../chunks/check-circle-Bnrb-CGJ.js";
2
2
  import { t as info_default } from "../../../chunks/info-Be2OccTu.js";
3
3
  import { t as x_default } from "../../../chunks/x-2KXnqxiD.js";
4
+ import { t as x_circle_default } from "../../../chunks/x-circle-BigSZy8m.js";
4
5
  import { s as useGrThemeAttrs } from "../../../chunks/context-CPMRfwVr.js";
5
6
  import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
6
7
  import { t as usePortalTarget } from "../../../chunks/usePortalTarget-BhrRgdqW.js";