@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.
- package/README.md +3 -3
- package/dist/chunks/{x-circle-BCBURwyX.js → check-circle-Bnrb-CGJ.js} +8 -32
- package/dist/chunks/check-circle-Bnrb-CGJ.js.map +1 -0
- package/dist/chunks/{config-BqT6PMzO.js → config-B42iJ48O.js} +5 -1
- package/dist/chunks/{config-BqT6PMzO.js.map → config-B42iJ48O.js.map} +1 -1
- package/dist/chunks/{config-BGCyyXiD.js → config-BAse0laT.js} +5 -1
- package/dist/chunks/{config-BGCyyXiD.js.map → config-BAse0laT.js.map} +1 -1
- package/dist/chunks/{config-MmPym-Z7.js → config-BLP94dPY.js} +5 -1
- package/dist/chunks/{config-MmPym-Z7.js.map → config-BLP94dPY.js.map} +1 -1
- package/dist/chunks/{config-CjKpUcmy.js → config-Bdf1bt-m.js} +25 -16
- package/dist/chunks/config-Bdf1bt-m.js.map +1 -0
- package/dist/chunks/{config-DeyT9dJl.js → config-Bs1HwUcx.js} +47 -4
- package/dist/chunks/{config-DeyT9dJl.js.map → config-Bs1HwUcx.js.map} +1 -1
- package/dist/chunks/{config-CIkdsWUk.js → config-CIUU9ZpY.js} +4 -1
- package/dist/chunks/config-CIUU9ZpY.js.map +1 -0
- package/dist/chunks/{config-B3J0alyY.js → config-CzeZg2LO.js} +49 -4
- package/dist/chunks/config-CzeZg2LO.js.map +1 -0
- package/dist/chunks/{config-DCq4JySZ.js → config-D3HOuHDe.js} +1 -1
- package/dist/chunks/{config-DCq4JySZ.js.map → config-D3HOuHDe.js.map} +1 -1
- package/dist/chunks/{config-BhfNgyWL.js → config-DENqOoh0.js} +5 -1
- package/dist/chunks/config-DENqOoh0.js.map +1 -0
- package/dist/chunks/controlState-DoImKciE.js +35 -0
- package/dist/chunks/controlState-DoImKciE.js.map +1 -0
- package/dist/chunks/{en-DiHzFact.js → en-Bxyn5lW7.js} +12 -2
- package/dist/chunks/en-Bxyn5lW7.js.map +1 -0
- package/dist/chunks/{es-CeKkMxZ_.js → es-Bj_vc18Z.js} +3 -3
- package/dist/chunks/{es-CeKkMxZ_.js.map → es-Bj_vc18Z.js.map} +1 -1
- package/dist/chunks/{es-1ZL6NtkB.js → es-Dtl-a7ui.js} +12 -2
- package/dist/chunks/es-Dtl-a7ui.js.map +1 -0
- package/dist/chunks/{generated-CQ4h6Ieq.js → generated-hELWB0gZ.js} +98 -0
- package/dist/chunks/{generated-CQ4h6Ieq.js.map → generated-hELWB0gZ.js.map} +1 -1
- package/dist/chunks/{grTableStyles-uuMPSOBR.js → grTableStyles-DkQPMfx9.js} +16 -3
- package/dist/chunks/grTableStyles-DkQPMfx9.js.map +1 -0
- package/dist/chunks/{granular-provider-CsN_R9dB.js → granular-provider-BOQp7N5o.js} +9 -9
- package/dist/chunks/{granular-provider-CsN_R9dB.js.map → granular-provider-BOQp7N5o.js.map} +1 -1
- package/dist/chunks/{ru-Dr2RYn0P.js → ru-hrB4I1u_.js} +12 -2
- package/dist/chunks/ru-hrB4I1u_.js.map +1 -0
- package/dist/chunks/x-circle-BigSZy8m.js +26 -0
- package/dist/chunks/x-circle-BigSZy8m.js.map +1 -0
- package/dist/components/GrAlert/chunks/{GrAlert-D72y1IEh.js → GrAlert-CfEZghSY.js} +2 -1
- package/dist/components/GrAlert/chunks/{GrAlert-D72y1IEh.js.map → GrAlert-CfEZghSY.js.map} +1 -1
- package/dist/components/GrAlert/index.js +1 -1
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-D396_JrW.js → GrAutocomplete-C-uovdv8.js} +320 -224
- package/dist/components/GrAutocomplete/chunks/GrAutocomplete-C-uovdv8.js.map +1 -0
- package/dist/components/GrAutocomplete/index.js +1 -1
- package/dist/components/GrAutocomplete/styles.css +1 -1
- package/dist/components/GrAvatar/chunks/{GrAvatar-dWEXiCJG.js → GrAvatar-Do5-C409.js} +12 -1
- package/dist/components/GrAvatar/chunks/GrAvatar-Do5-C409.js.map +1 -0
- package/dist/components/GrAvatar/index.js +2 -2
- package/dist/components/GrAvatar/themes/light.css +35 -0
- package/dist/components/GrColorPicker/chunks/{GrColorPicker-9mTR-YZ_.js → GrColorPicker-BRM_4lyI.js} +1 -1
- package/dist/components/GrColorPicker/chunks/{GrColorPicker-9mTR-YZ_.js.map → GrColorPicker-BRM_4lyI.js.map} +1 -1
- package/dist/components/GrColorPicker/index.js +1 -1
- package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-Ha4s3DMT.js.map → GrCommandPalette-BJHmkDQv.js.map} +1 -1
- package/dist/components/GrCommandPalette/index.js +1 -1
- package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-e15nFI8M.js → GrConfirmDialog-BzUQwbec.js} +1 -1
- package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-e15nFI8M.js.map → GrConfirmDialog-BzUQwbec.js.map} +1 -1
- package/dist/components/GrConfirmDialog/index.js +1 -1
- package/dist/components/GrDataTable/chunks/GrDataTable-DQxYYgQk.js +1519 -0
- package/dist/components/GrDataTable/chunks/GrDataTable-DQxYYgQk.js.map +1 -0
- package/dist/components/GrDataTable/index.js +2 -2
- package/dist/components/GrDataTable/themes/light.css +10 -0
- package/dist/components/GrDialogService/chunks/{GrDialogService-BmXiYmUp.js → GrDialogService-Dtq0ZCN5.js} +3 -3
- package/dist/components/GrDialogService/chunks/{GrDialogService-BmXiYmUp.js.map → GrDialogService-Dtq0ZCN5.js.map} +1 -1
- package/dist/components/GrDialogService/index.js +1 -1
- package/dist/components/GrFormField/chunks/GrFormField-DO61vxpS.js.map +1 -1
- package/dist/components/GrInput/chunks/{GrInput-TFeBm3gQ.js → GrInput-DV4gMWPR.js} +40 -11
- package/dist/components/GrInput/chunks/GrInput-DV4gMWPR.js.map +1 -0
- package/dist/components/GrInput/index.js +2 -2
- package/dist/components/GrInputTag/chunks/{GrInputTag-Ci8AO1ze.js → GrInputTag-CO0YU-ok.js} +30 -6
- package/dist/components/GrInputTag/chunks/GrInputTag-CO0YU-ok.js.map +1 -0
- package/dist/components/GrInputTag/index.js +2 -2
- package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-C6q8dEEZ.js → GrJsonViewer-D7CyWzhT.js} +1 -1
- package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-C6q8dEEZ.js.map → GrJsonViewer-D7CyWzhT.js.map} +1 -1
- package/dist/components/GrJsonViewer/index.js +1 -1
- package/dist/components/GrNumberInput/chunks/{GrNumberInput-CL5QhOmx.js → GrNumberInput-BI6-vkcs.js} +48 -16
- package/dist/components/GrNumberInput/chunks/GrNumberInput-BI6-vkcs.js.map +1 -0
- package/dist/components/GrNumberInput/index.js +2 -2
- package/dist/components/GrPagination/chunks/{GrPagination-DhbNZHEF.js → GrPagination-BbaF5eXk.js} +10 -7
- package/dist/components/GrPagination/chunks/GrPagination-BbaF5eXk.js.map +1 -0
- package/dist/components/GrPagination/index.js +2 -2
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-8RxQsOQ_.js → GrPromptDialog-BEL-QgwE.js} +3 -3
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-8RxQsOQ_.js.map → GrPromptDialog-BEL-QgwE.js.map} +1 -1
- package/dist/components/GrPromptDialog/index.js +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-NEEJZ8zi.js → GrResponseErrorBanner-Bdd5c07x.js} +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-NEEJZ8zi.js.map → GrResponseErrorBanner-Bdd5c07x.js.map} +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-ZvBvEQDZ.js → GrResponseErrorBanner-DySe1ym4.js} +1 -1
- package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-ZvBvEQDZ.js.map → GrResponseErrorBanner-DySe1ym4.js.map} +1 -1
- package/dist/components/GrResponseErrorBanner/index.js +2 -2
- package/dist/components/GrSelect/chunks/{GrSelect-Do1iAyp1.js → GrSelect-0iI4wdR_.js} +3 -3
- package/dist/components/GrSelect/chunks/{GrSelect-Do1iAyp1.js.map → GrSelect-0iI4wdR_.js.map} +1 -1
- package/dist/components/GrSelect/index.js +1 -1
- package/dist/components/GrTable/chunks/{GrTable-iwzHvlMC.js → GrTable-CKJ-HrsN.js} +1 -1
- package/dist/components/GrTable/chunks/{GrTable-iwzHvlMC.js.map → GrTable-CKJ-HrsN.js.map} +1 -1
- package/dist/components/GrTable/index.js +2 -2
- package/dist/components/GrTextarea/chunks/{GrTextarea-BII3w61K.js → GrTextarea-Bfgc0DD2.js} +73 -32
- package/dist/components/GrTextarea/chunks/GrTextarea-Bfgc0DD2.js.map +1 -0
- package/dist/components/GrTextarea/index.js +2 -2
- package/dist/components/GrToaster/chunks/{GrToaster-D-sV-9of.js → GrToaster-CZixNk0l.js} +2 -1
- package/dist/components/GrToaster/chunks/{GrToaster-D-sV-9of.js.map → GrToaster-CZixNk0l.js.map} +1 -1
- package/dist/components/GrToaster/index.js +1 -1
- package/dist/components/GrTransfer/chunks/{GrTransfer-8FA78ny6.js → GrTransfer-DdfBUf35.js} +2 -2
- package/dist/components/GrTransfer/chunks/{GrTransfer-8FA78ny6.js.map → GrTransfer-DdfBUf35.js.map} +1 -1
- package/dist/components/GrTransfer/index.js +1 -1
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DBu5nMGA.js → GrTreeSelect-B6KoDYiZ.js} +43 -18
- package/dist/components/GrTreeSelect/chunks/GrTreeSelect-B6KoDYiZ.js.map +1 -0
- package/dist/components/GrTreeSelect/index.js +2 -2
- 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 +32 -32
- package/dist/theme.js +1 -1
- package/dist/tokens.js +1 -1
- package/dist/types/components/GrAutocomplete/composables/useAutocompleteNavigation.d.ts +39 -0
- package/dist/types/components/GrAutocomplete/composables/useAutocompletePanel.d.ts +36 -0
- package/dist/types/components/GrAutocomplete/composables/useAutocompleteValues.d.ts +28 -0
- package/dist/types/components/GrAutocomplete/composables/useAutocompleteVirtual.d.ts +33 -0
- package/dist/types/components/GrAutocomplete/composables/useRemoteOptions.d.ts +33 -0
- package/dist/types/components/GrAvatar/GrAvatar.vue.d.ts +11 -0
- package/dist/types/components/GrAvatar/defaults.d.ts +1 -0
- package/dist/types/components/GrAvatar/grAvatarStyles.d.ts +26 -1
- package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +60 -1
- package/dist/types/components/GrDataTable/composables/useDataTableColumnOrder.d.ts +45 -0
- package/dist/types/components/GrDataTable/composables/useDataTableColumnWidths.d.ts +38 -0
- package/dist/types/components/GrDataTable/composables/useDataTableExpansion.d.ts +46 -0
- package/dist/types/components/GrDataTable/composables/useDataTableLayout.d.ts +29 -0
- package/dist/types/components/GrDataTable/composables/useDataTableRowKeys.d.ts +16 -0
- package/dist/types/components/GrDataTable/composables/useDataTableSelection.d.ts +32 -0
- package/dist/types/components/GrDataTable/composables/useDataTableSort.d.ts +37 -0
- package/dist/types/components/GrDataTable/grDataTableStyles.d.ts +23 -0
- package/dist/types/components/GrFormField/GrFormField.vue.d.ts +7 -1
- package/dist/types/components/GrPagination/GrPagination.vue.d.ts +17 -2
- package/dist/types/components/GrPagination/grPaginationStyles.d.ts +15 -6
- package/dist/types/components/GrPagination/index.d.ts +1 -1
- package/dist/types/components/GrTable/grTableStyles.d.ts +16 -3
- package/dist/types/components/shared/controlState.d.ts +36 -0
- package/dist/types/i18n/messages/en.d.ts +20 -0
- package/dist/types/i18n/messages/es.d.ts +20 -0
- package/dist/types/i18n/messages/ru.d.ts +20 -0
- package/dist/web-types.json +79 -3
- package/package.json +1 -1
- package/dist/chunks/config-B3J0alyY.js.map +0 -1
- package/dist/chunks/config-BhfNgyWL.js.map +0 -1
- package/dist/chunks/config-CIkdsWUk.js.map +0 -1
- package/dist/chunks/config-CjKpUcmy.js.map +0 -1
- package/dist/chunks/en-DiHzFact.js.map +0 -1
- package/dist/chunks/es-1ZL6NtkB.js.map +0 -1
- package/dist/chunks/grTableStyles-uuMPSOBR.js.map +0 -1
- package/dist/chunks/ru-Dr2RYn0P.js.map +0 -1
- package/dist/chunks/x-circle-BCBURwyX.js.map +0 -1
- package/dist/components/GrAutocomplete/chunks/GrAutocomplete-D396_JrW.js.map +0 -1
- package/dist/components/GrAvatar/chunks/GrAvatar-dWEXiCJG.js.map +0 -1
- package/dist/components/GrDataTable/chunks/GrDataTable-xNSmO_I-.js +0 -1134
- package/dist/components/GrDataTable/chunks/GrDataTable-xNSmO_I-.js.map +0 -1
- package/dist/components/GrInput/chunks/GrInput-TFeBm3gQ.js.map +0 -1
- package/dist/components/GrInputTag/chunks/GrInputTag-Ci8AO1ze.js.map +0 -1
- package/dist/components/GrNumberInput/chunks/GrNumberInput-CL5QhOmx.js.map +0 -1
- package/dist/components/GrPagination/chunks/GrPagination-DhbNZHEF.js.map +0 -1
- package/dist/components/GrTextarea/chunks/GrTextarea-BII3w61K.js.map +0 -1
- package/dist/components/GrTreeSelect/chunks/GrTreeSelect-DBu5nMGA.js.map +0 -1
- package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-Ha4s3DMT.js → GrCommandPalette-BJHmkDQv.js} +1 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ComputedRef, Ref } from 'vue';
|
|
2
|
+
import type { GrAutocompleteOption, GrAutocompleteValue } from '../GrAutocomplete.vue';
|
|
3
|
+
/**
|
|
4
|
+
* Состав панели `GrAutocomplete`: что показывать под запросом.
|
|
5
|
+
*
|
|
6
|
+
* Три решения, которые легко перепутать между собой. При `fetchOptions`
|
|
7
|
+
* локальный матчер выключается — он отсеял бы то, что сервер уже прислал в
|
|
8
|
+
* ответ на этот же запрос. Ниже `minQueryLength` список пуст, а не «прошлый»:
|
|
9
|
+
* показывать старый набор под подсказкой «введите ещё N» значит
|
|
10
|
+
* дезинформировать. А «Add …» не предлагается, если такое значение или подпись
|
|
11
|
+
* уже есть среди опций.
|
|
12
|
+
*/
|
|
13
|
+
export interface UseAutocompletePanelOptions<TValue extends GrAutocompleteValue> {
|
|
14
|
+
optionsResolved: ComputedRef<GrAutocompleteOption<TValue>[]>;
|
|
15
|
+
/** Введённый текст без нормализации: тримит уже сам модуль. */
|
|
16
|
+
query: Ref<string>;
|
|
17
|
+
/** Пользователь начал ввод — до этого single-режим показывает весь список. */
|
|
18
|
+
dirty: Ref<boolean>;
|
|
19
|
+
filterable: () => boolean;
|
|
20
|
+
filter: () => ((option: GrAutocompleteOption<TValue>, query: string) => boolean) | undefined;
|
|
21
|
+
fetchOptions: () => unknown;
|
|
22
|
+
multiple: () => boolean;
|
|
23
|
+
minQueryLength: () => number;
|
|
24
|
+
allowCustomValue: () => boolean;
|
|
25
|
+
selectedValues: ComputedRef<TValue[]>;
|
|
26
|
+
modelSingle: ComputedRef<TValue | ''>;
|
|
27
|
+
isLoading: ComputedRef<boolean>;
|
|
28
|
+
}
|
|
29
|
+
export interface AutocompletePanel<TValue extends GrAutocompleteValue> {
|
|
30
|
+
searchQuery: ComputedRef<string>;
|
|
31
|
+
belowMinQuery: ComputedRef<boolean>;
|
|
32
|
+
effectiveOptions: ComputedRef<GrAutocompleteOption<TValue>[]>;
|
|
33
|
+
canAddCustom: ComputedRef<boolean>;
|
|
34
|
+
showEmpty: ComputedRef<boolean>;
|
|
35
|
+
}
|
|
36
|
+
export declare function useAutocompletePanel<TValue extends GrAutocompleteValue>(options: UseAutocompletePanelOptions<TValue>): AutocompletePanel<TValue>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ComputedRef, Ref, ShallowRef } from 'vue';
|
|
2
|
+
import type { GrAutocompleteModelValue, GrAutocompleteOption, GrAutocompleteValue } from '../GrAutocomplete.vue';
|
|
3
|
+
/**
|
|
4
|
+
* Значение и опции `GrAutocomplete`: что выбрано и как это назвать.
|
|
5
|
+
*
|
|
6
|
+
* Ничего про панель, клавиатуру и вид. Состав списка зависит от того, отвечал
|
|
7
|
+
* ли уже сервер: до первого ответа источник — проп `options`, иначе последний
|
|
8
|
+
* ответ `fetchOptions`.
|
|
9
|
+
*/
|
|
10
|
+
export interface UseAutocompleteValuesOptions<TValue extends GrAutocompleteValue> {
|
|
11
|
+
modelValue: () => GrAutocompleteModelValue<TValue>;
|
|
12
|
+
options: () => GrAutocompleteOption<TValue>[] | undefined;
|
|
13
|
+
multiple: () => boolean;
|
|
14
|
+
fetchOptions: () => unknown;
|
|
15
|
+
remoteOptions: ShallowRef<GrAutocompleteOption<TValue>[]>;
|
|
16
|
+
remoteAnswered: Ref<boolean>;
|
|
17
|
+
}
|
|
18
|
+
export interface AutocompleteValues<TValue extends GrAutocompleteValue> {
|
|
19
|
+
optionsResolved: ComputedRef<GrAutocompleteOption<TValue>[]>;
|
|
20
|
+
isEmptyValue: (value: unknown) => boolean;
|
|
21
|
+
modelSingle: ComputedRef<TValue | ''>;
|
|
22
|
+
selectedValues: ComputedRef<TValue[]>;
|
|
23
|
+
hasSelection: ComputedRef<boolean>;
|
|
24
|
+
labelFor: (value: GrAutocompleteValue) => string;
|
|
25
|
+
selectedOptions: ComputedRef<GrAutocompleteOption<TValue>[]>;
|
|
26
|
+
singleSelectedLabel: ComputedRef<string>;
|
|
27
|
+
}
|
|
28
|
+
export declare function useAutocompleteValues<TValue extends GrAutocompleteValue>(options: UseAutocompleteValuesOptions<TValue>): AutocompleteValues<TValue>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ComputedRef, Ref } from 'vue';
|
|
2
|
+
import { useVirtualList } from '../../../composables/useVirtualList';
|
|
3
|
+
import type { GrAutocompleteOption, GrAutocompleteValue } from '../GrAutocomplete.vue';
|
|
4
|
+
/**
|
|
5
|
+
* Виртуализация панели `GrAutocomplete`.
|
|
6
|
+
*
|
|
7
|
+
* Набор — `[«Add …»?] + effectiveOptions`, тот же, по которому ходит клавиатура.
|
|
8
|
+
* Иначе верхняя распорка вытолкнула бы строку «Add …» вниз: она отрисована
|
|
9
|
+
* внутри listbox'а первой и является полноценной опцией. Отсюда `addOffset`,
|
|
10
|
+
* который сдвигает окно виртуализатора относительно индексов в списке опций.
|
|
11
|
+
*/
|
|
12
|
+
export interface UseAutocompleteVirtualOptions<TValue extends GrAutocompleteValue> {
|
|
13
|
+
/** Контейнер списка: по нему считается окно и замеряются строки. */
|
|
14
|
+
listboxEl: Ref<HTMLElement | null>;
|
|
15
|
+
effectiveOptions: ComputedRef<GrAutocompleteOption<TValue>[]>;
|
|
16
|
+
canAddCustom: ComputedRef<boolean>;
|
|
17
|
+
virtual: () => boolean;
|
|
18
|
+
dropdownMaxHeight: () => number;
|
|
19
|
+
}
|
|
20
|
+
export interface AutocompleteVirtual<TValue extends GrAutocompleteValue> {
|
|
21
|
+
/** Сдвиг окна из-за строки «Add …»: она идёт нулевым элементом набора. */
|
|
22
|
+
addOffset: ComputedRef<number>;
|
|
23
|
+
virtualCount: ComputedRef<number>;
|
|
24
|
+
virtualizer: ReturnType<typeof useVirtualList>;
|
|
25
|
+
showAddOption: ComputedRef<boolean>;
|
|
26
|
+
renderedOptions: ComputedRef<Array<{
|
|
27
|
+
option: GrAutocompleteOption<TValue>;
|
|
28
|
+
index: number;
|
|
29
|
+
}>>;
|
|
30
|
+
optionSetProps: (virtualIndex: number) => Record<string, number> | undefined;
|
|
31
|
+
listboxStyle: ComputedRef<Record<string, string>>;
|
|
32
|
+
}
|
|
33
|
+
export declare function useAutocompleteVirtual<TValue extends GrAutocompleteValue>(options: UseAutocompleteVirtualOptions<TValue>): AutocompleteVirtual<TValue>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Ref, ShallowRef } from 'vue';
|
|
2
|
+
import type { GrAutocompleteOption, GrAutocompleteValue } from '../GrAutocomplete.vue';
|
|
3
|
+
/**
|
|
4
|
+
* Дебаунснутая удалённая загрузка опций.
|
|
5
|
+
*
|
|
6
|
+
* Три вещи, каждая из которых по отдельности выглядит необязательной, а вместе
|
|
7
|
+
* составляют весь смысл модуля: запрос откладывается на `debounce`, летящий
|
|
8
|
+
* отменяется новым, а ответ, стартовавший раньше и пришедший позже, обязан
|
|
9
|
+
* проиграть последнему — иначе список показывает результат старого запроса.
|
|
10
|
+
*
|
|
11
|
+
* От DOM не зависит вовсе, поэтому проверяется без монтирования компонента.
|
|
12
|
+
*
|
|
13
|
+
* Единственный потребитель сегодня — `GrAutocomplete`. Появится второй
|
|
14
|
+
* (открытая строка аудита: `GrTransfer` отдаёт `search` наружу, а подгрузку
|
|
15
|
+
* делает потребитель) — модулю место в `composables/internal/`.
|
|
16
|
+
*/
|
|
17
|
+
export interface UseRemoteOptionsOptions<TValue extends GrAutocompleteValue> {
|
|
18
|
+
fetchOptions: () => ((query: string, signal: AbortSignal) => Promise<GrAutocompleteOption<TValue>[]>) | undefined;
|
|
19
|
+
/** Стартовый список: его смена сбрасывает ответ сервера. */
|
|
20
|
+
options: () => GrAutocompleteOption<TValue>[] | undefined;
|
|
21
|
+
debounce: () => number;
|
|
22
|
+
minQueryLength: () => number;
|
|
23
|
+
onSearch: (query: string) => void;
|
|
24
|
+
onSearchError: (error: unknown) => void;
|
|
25
|
+
}
|
|
26
|
+
export interface RemoteOptions<TValue extends GrAutocompleteValue> {
|
|
27
|
+
remoteOptions: ShallowRef<GrAutocompleteOption<TValue>[]>;
|
|
28
|
+
remoteAnswered: Ref<boolean>;
|
|
29
|
+
remoteLoading: Ref<boolean>;
|
|
30
|
+
scheduleSearch: (value: string) => void;
|
|
31
|
+
cancelSearch: () => void;
|
|
32
|
+
}
|
|
33
|
+
export declare function useRemoteOptions<TValue extends GrAutocompleteValue>(options: UseRemoteOptionsOptions<TValue>): RemoteOptions<TValue>;
|
|
@@ -16,6 +16,14 @@ export interface GrAvatarProps {
|
|
|
16
16
|
/** Имя участника: даёт инициалы и доступное имя аватара. */
|
|
17
17
|
name?: string;
|
|
18
18
|
shape?: GrAvatarShape;
|
|
19
|
+
/**
|
|
20
|
+
* Красить фон по имени: одинаковое имя всегда даёт одинаковый цвет.
|
|
21
|
+
*
|
|
22
|
+
* Выключен по умолчанию — серый аватар это осознанный нейтральный дефолт, а
|
|
23
|
+
* цветной может спорить с оформлением продукта. Палитру задаёт тема
|
|
24
|
+
* (`--gr-avatar-N-bg`/`-fg`), компонент только выбирает слот.
|
|
25
|
+
*/
|
|
26
|
+
autoColor?: boolean;
|
|
19
27
|
/** Статус участника. Точка декоративна — рядом идёт скрытая подпись. */
|
|
20
28
|
status?: GrAvatarStatus;
|
|
21
29
|
}
|
|
@@ -30,6 +38,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
30
38
|
alt: undefined;
|
|
31
39
|
name: undefined;
|
|
32
40
|
shape: undefined;
|
|
41
|
+
autoColor: undefined;
|
|
33
42
|
status: undefined;
|
|
34
43
|
}>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<GrAvatarProps>, {
|
|
35
44
|
size: undefined;
|
|
@@ -38,10 +47,12 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
38
47
|
alt: undefined;
|
|
39
48
|
name: undefined;
|
|
40
49
|
shape: undefined;
|
|
50
|
+
autoColor: undefined;
|
|
41
51
|
status: undefined;
|
|
42
52
|
}>>> & Readonly<{}>, {
|
|
43
53
|
size: GrSizeWithPx;
|
|
44
54
|
shape: GrAvatarShape;
|
|
55
|
+
autoColor: boolean;
|
|
45
56
|
status: GrAvatarStatus;
|
|
46
57
|
name: string;
|
|
47
58
|
alt: string;
|
|
@@ -8,6 +8,7 @@ import type { GrAvatarShape } from './grAvatarStyles';
|
|
|
8
8
|
export interface GrAvatarConfigurableProps {
|
|
9
9
|
size: GrComponentSize;
|
|
10
10
|
shape: GrAvatarShape;
|
|
11
|
+
autoColor: boolean;
|
|
11
12
|
}
|
|
12
13
|
declare module '../../composables/useGrComponentConfig' {
|
|
13
14
|
interface GrComponentDefaultsRegistry {
|
|
@@ -3,7 +3,32 @@ export type GrAvatarShape = 'circle' | 'square';
|
|
|
3
3
|
export declare const GR_AVATAR_STATUSES: readonly ["online", "offline", "busy", "away"];
|
|
4
4
|
export type GrAvatarStatus = typeof GR_AVATAR_STATUSES[number];
|
|
5
5
|
export declare const shapes: Record<GrAvatarShape, string>;
|
|
6
|
-
export declare const rootBaseClass = "relative inline-flex shrink-0 items-center justify-center overflow-hidden border border-[var(--gr-brd)]
|
|
6
|
+
export declare const rootBaseClass = "relative inline-flex shrink-0 items-center justify-center overflow-hidden border border-[var(--gr-brd)] font-700";
|
|
7
|
+
/** Цвет по умолчанию. Отделён от базы, иначе он спорил бы с автоцветом порядком правил. */
|
|
8
|
+
export declare const rootNeutralClass = "bg-[var(--gr-muted)] text-[var(--gr-muted-fg)]";
|
|
9
|
+
/**
|
|
10
|
+
* Палитра автоцвета: подложка и инициалы одним классом на слот.
|
|
11
|
+
*
|
|
12
|
+
* Цвета сюда не попадают — только имена слотов. Что стоит за слотом, решает
|
|
13
|
+
* тема (`--gr-avatar-N-bg`/`-fg` ссылаются на пары `-light`/`-text` тонов), и
|
|
14
|
+
* приложение вправе переопределить любой, не трогая компонент.
|
|
15
|
+
*
|
|
16
|
+
* Классы статические: UnoCSS сканирует литералы, и собранный в рантайме
|
|
17
|
+
* `bg-[var(--gr-avatar-${n}-bg)]` в CSS не превратился бы.
|
|
18
|
+
*/
|
|
19
|
+
export declare const avatarToneClasses: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Слот палитры по имени: тот же человек — тот же цвет.
|
|
22
|
+
*
|
|
23
|
+
* Стабильность здесь и есть смысл функции: цвет не должен меняться ни между
|
|
24
|
+
* сессиями, ни между сервером и клиентом, иначе аватар мигает на гидрации, а
|
|
25
|
+
* узнаваемость — то, ради чего автоцвет и заводят, — теряется. Отсюда обычный
|
|
26
|
+
* детерминированный перебор кодов, а не хеш из окружения.
|
|
27
|
+
*
|
|
28
|
+
* `>>> 0` обязателен: без него сумма уходит в отрицательные на длинных именах,
|
|
29
|
+
* и остаток от деления даёт отрицательный индекс.
|
|
30
|
+
*/
|
|
31
|
+
export declare function avatarToneIndex(name: string): number;
|
|
7
32
|
/** Индикатор статуса: кольцо цветом фона отделяет точку от самого аватара. */
|
|
8
33
|
export declare const statusDotClass = "absolute bottom-0 right-0 block h-1/4 w-1/4 min-h-2 min-w-2 rounded-[var(--gr-radius-full)] ring-2 ring-[var(--gr-bg)]";
|
|
9
34
|
export declare const statusToneClass: Record<GrAvatarStatus, string>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { GrDataTableSortDir } from './grDataTableSort';
|
|
2
2
|
import { type GrDataTableSize } from './grDataTableStyles';
|
|
3
3
|
/**
|
|
4
4
|
* Ключ колонки. Собственные поля строки подсказываются автодополнением, но
|
|
@@ -150,6 +150,31 @@ export interface GrDataTableProps<TRow extends Record<string, unknown> = Record<
|
|
|
150
150
|
* Не заданы — ширины компонент помнит сам.
|
|
151
151
|
*/
|
|
152
152
|
columnWidths?: Record<string, number>;
|
|
153
|
+
/**
|
|
154
|
+
* Второй ярус строки: колонка с кнопкой раскрытия и блок подробностей под
|
|
155
|
+
* строкой. Содержимое рисует слот `#detail`.
|
|
156
|
+
*/
|
|
157
|
+
expandable?: boolean;
|
|
158
|
+
/** Контролируемый список раскрытых ключей (`v-model:expandedKeys`). */
|
|
159
|
+
expandedKeys?: Array<string | number>;
|
|
160
|
+
/** У какой строки есть второй ярус. Остальные кнопки не получают. */
|
|
161
|
+
expandableRow?: (row: TRow) => boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Подгрузка подробностей в момент раскрытия. Без неё содержимое берётся из
|
|
164
|
+
* самой строки. `signal` обязателен: строку сворачивают чаще, чем ждут.
|
|
165
|
+
*/
|
|
166
|
+
loadDetail?: (row: TRow, signal: AbortSignal) => Promise<unknown>;
|
|
167
|
+
/** Раскрыта не больше одной строки. */
|
|
168
|
+
accordion?: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* Рисовать ли служебную колонку с собственной кнопкой раскрытия.
|
|
171
|
+
*
|
|
172
|
+
* `false` — колонки нет, и раскрытием управляет разметка потребителя: слоты
|
|
173
|
+
* ячеек получают `expanded` и `toggleExpand`, чтобы кнопку можно было
|
|
174
|
+
* поставить в свой столбец действий рядом с остальными. Тогда `aria-expanded`
|
|
175
|
+
* и доступное имя ложатся на неё же — компоненту их вешать не на что.
|
|
176
|
+
*/
|
|
177
|
+
expandColumn?: boolean;
|
|
153
178
|
}
|
|
154
179
|
export interface GrDataTableEmits<TRow extends Record<string, unknown> = Record<string, unknown>> {
|
|
155
180
|
(e: 'update:sortKey', value: string): void;
|
|
@@ -175,10 +200,32 @@ export interface GrDataTableEmits<TRow extends Record<string, unknown> = Record<
|
|
|
175
200
|
key: string;
|
|
176
201
|
width: number;
|
|
177
202
|
}): void;
|
|
203
|
+
(e: 'update:expandedKeys', value: Array<string | number>): void;
|
|
204
|
+
(e: 'expand', payload: {
|
|
205
|
+
row: TRow;
|
|
206
|
+
key: string | number;
|
|
207
|
+
}): void;
|
|
208
|
+
(e: 'collapse', payload: {
|
|
209
|
+
row: TRow;
|
|
210
|
+
key: string | number;
|
|
211
|
+
}): void;
|
|
212
|
+
(e: 'detailLoadError', payload: {
|
|
213
|
+
row: TRow;
|
|
214
|
+
key: string | number;
|
|
215
|
+
error: unknown;
|
|
216
|
+
}): void;
|
|
178
217
|
}
|
|
179
218
|
declare const __VLS_export: <TRow extends Record<string, unknown> = Record<string, unknown>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
180
219
|
props: import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & __VLS_PrettifyLocal<GrDataTableProps<TRow> & {
|
|
220
|
+
onCollapse?: ((payload: {
|
|
221
|
+
row: TRow;
|
|
222
|
+
key: string | number;
|
|
223
|
+
}) => any) | undefined;
|
|
181
224
|
"onUpdate:selected"?: ((value: (string | number)[]) => any) | undefined;
|
|
225
|
+
onExpand?: ((payload: {
|
|
226
|
+
row: TRow;
|
|
227
|
+
key: string | number;
|
|
228
|
+
}) => any) | undefined;
|
|
182
229
|
"onUpdate:sortKey"?: ((value: string) => any) | undefined;
|
|
183
230
|
"onUpdate:sortDir"?: ((value: GrDataTableSortDir) => any) | undefined;
|
|
184
231
|
onSortChange?: ((value: {
|
|
@@ -201,6 +248,12 @@ declare const __VLS_export: <TRow extends Record<string, unknown> = Record<strin
|
|
|
201
248
|
key: string;
|
|
202
249
|
width: number;
|
|
203
250
|
}) => any) | undefined;
|
|
251
|
+
"onUpdate:expandedKeys"?: ((value: (string | number)[]) => any) | undefined;
|
|
252
|
+
onDetailLoadError?: ((payload: {
|
|
253
|
+
row: TRow;
|
|
254
|
+
key: string | number;
|
|
255
|
+
error: unknown;
|
|
256
|
+
}) => any) | undefined;
|
|
204
257
|
}> & (typeof globalThis extends {
|
|
205
258
|
__VLS_PROPS_FALLBACK: infer P;
|
|
206
259
|
} ? P : {});
|
|
@@ -213,6 +266,12 @@ declare const __VLS_export: <TRow extends Record<string, unknown> = Record<strin
|
|
|
213
266
|
clearSort: () => void;
|
|
214
267
|
/** Отметить/снять все выбираемые строки. */
|
|
215
268
|
toggleAll: () => void;
|
|
269
|
+
/**
|
|
270
|
+
* Сбросить загруженные подробности: у одной строки либо у всех.
|
|
271
|
+
* Нужен, когда запись изменилась на сервере, — само по себе раскрытие
|
|
272
|
+
* держит загруженное, пока строка жива.
|
|
273
|
+
*/
|
|
274
|
+
invalidateDetail: (key?: import("./composables/useDataTableExpansion").GrDataTableRowKey) => void;
|
|
216
275
|
}>) => void;
|
|
217
276
|
attrs: any;
|
|
218
277
|
slots: {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ComputedRef } from 'vue';
|
|
2
|
+
import { useDragSort } from '../../../composables/useDragSort';
|
|
3
|
+
import { useRovingFocus } from '../../../composables/useRovingFocus';
|
|
4
|
+
import type { GrDataColumn } from '../GrDataTable.vue';
|
|
5
|
+
/**
|
|
6
|
+
* Порядок колонок `GrDataTable`: перестановка указателем и с клавиатуры.
|
|
7
|
+
*
|
|
8
|
+
* Закреплённые колонки стоят своими группами у своих краёв, и перенос через
|
|
9
|
+
* границу группы запрещён — иначе «закреплена слева» перестало бы означать
|
|
10
|
+
* «слева». Отсюда `pinGroupOf` и проверка `sameGroup` в каждом пути переноса.
|
|
11
|
+
*
|
|
12
|
+
* Карты элементов приходят снаружи: их наполняет шаблон, и они же нужны
|
|
13
|
+
* модулям ширины и раскладки — владеть ими единолично этот модуль не может.
|
|
14
|
+
*/
|
|
15
|
+
export interface UseDataTableColumnOrderOptions<TRow extends Record<string, unknown>> {
|
|
16
|
+
columns: () => GrDataColumn<TRow>[];
|
|
17
|
+
/** Контролируемый порядок. `undefined` — компонент помнит порядок сам. */
|
|
18
|
+
columnOrder: () => string[] | undefined;
|
|
19
|
+
reorderableColumns: () => boolean;
|
|
20
|
+
loading: () => boolean;
|
|
21
|
+
/** Заголовочные ячейки по ключу колонки — цель перетаскивания. */
|
|
22
|
+
headerCellEls: Map<string, HTMLElement>;
|
|
23
|
+
/** Ручки переноса по ключу колонки — кольцо роверного фокуса. */
|
|
24
|
+
columnHandleEls: Map<string, HTMLElement>;
|
|
25
|
+
onOrderChange: (order: string[], moved: {
|
|
26
|
+
key: string;
|
|
27
|
+
from: number;
|
|
28
|
+
to: number;
|
|
29
|
+
}) => void;
|
|
30
|
+
/** Объявление в живой регион: перенос указателем без него беззвучен. */
|
|
31
|
+
announceMove: (label: string, position: number, count: number) => void;
|
|
32
|
+
}
|
|
33
|
+
export interface DataTableColumnOrder<TRow extends Record<string, unknown>> {
|
|
34
|
+
orderedColumns: ComputedRef<GrDataColumn<TRow>[]>;
|
|
35
|
+
columnKeys: ComputedRef<string[]>;
|
|
36
|
+
pinGroupOf: (col: GrDataColumn<TRow>) => number;
|
|
37
|
+
indexOfColumn: (key: string) => number;
|
|
38
|
+
draggingColumnKey: ComputedRef<string | null>;
|
|
39
|
+
columnDropClass: (index: number) => string;
|
|
40
|
+
onColumnHandleKeydown: (event: KeyboardEvent, key: string) => Promise<void>;
|
|
41
|
+
/** Жест и кольцо фокуса отдаются целиком: шаблон зовёт их собственный API. */
|
|
42
|
+
columnSort: ReturnType<typeof useDragSort<string, number>>;
|
|
43
|
+
columnRoving: ReturnType<typeof useRovingFocus<string>>;
|
|
44
|
+
}
|
|
45
|
+
export declare function useDataTableColumnOrder<TRow extends Record<string, unknown>>(options: UseDataTableColumnOrderOptions<TRow>): DataTableColumnOrder<TRow>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ComputedRef, Ref } from 'vue';
|
|
2
|
+
import type { GrDataColumn } from '../GrDataTable.vue';
|
|
3
|
+
/** Уже колонки не бывает: в неё перестаёт помещаться даже стрелка сортировки. */
|
|
4
|
+
export declare const MIN_COLUMN_WIDTH = 48;
|
|
5
|
+
/**
|
|
6
|
+
* Ширина колонок `GrDataTable`: протяжка ручки, клавиатура и сброс к авторазметке.
|
|
7
|
+
*
|
|
8
|
+
* Измеренные ширины сюда **приходят снаружи** (`setMeasuredWidths`): замер —
|
|
9
|
+
* дело раскладки, которая ходит в DOM после отрисовки, а здесь они только
|
|
10
|
+
* читаются, чтобы ручка называла значение с первого рендера.
|
|
11
|
+
*/
|
|
12
|
+
export interface UseDataTableColumnWidthsOptions<TRow extends Record<string, unknown>> {
|
|
13
|
+
/** Колонки в текущем порядке — по ним считается минимальная ширина таблицы. */
|
|
14
|
+
orderedColumns: () => GrDataColumn<TRow>[];
|
|
15
|
+
/** Контролируемые ширины. `undefined` — компонент помнит их сам. */
|
|
16
|
+
columnWidths: () => Record<string, number> | undefined;
|
|
17
|
+
resizableColumns: () => boolean;
|
|
18
|
+
loading: () => boolean;
|
|
19
|
+
/** Заголовочные ячейки: стартовая ширина протяжки берётся замером. */
|
|
20
|
+
headerCellEls: Map<string, HTMLElement>;
|
|
21
|
+
onWidthsChange: (widths: Record<string, number>) => void;
|
|
22
|
+
onColumnResize: (key: string, width: number) => void;
|
|
23
|
+
announceWidth: (label: string, width: number) => void;
|
|
24
|
+
}
|
|
25
|
+
export interface DataTableColumnWidths<TRow extends Record<string, unknown>> {
|
|
26
|
+
columnWidths: ComputedRef<Record<string, number>>;
|
|
27
|
+
measuredColumnWidths: Ref<Record<string, number>>;
|
|
28
|
+
setMeasuredWidths: (widths: Record<string, number>) => void;
|
|
29
|
+
widthOf: (col: GrDataColumn<TRow>) => string | number | undefined;
|
|
30
|
+
tableMinWidth: ComputedRef<number | undefined>;
|
|
31
|
+
resizingKey: Ref<string | null>;
|
|
32
|
+
onResizerPointerDown: (event: PointerEvent, key: string) => void;
|
|
33
|
+
onResizerKeydown: (event: KeyboardEvent, key: string) => void;
|
|
34
|
+
/** Сброс к авторазметке — двойной клик по ручке в шаблоне. */
|
|
35
|
+
resetColumnWidth: (key: string) => void;
|
|
36
|
+
resizerValue: (col: GrDataColumn<TRow>) => number;
|
|
37
|
+
}
|
|
38
|
+
export declare function useDataTableColumnWidths<TRow extends Record<string, unknown>>(options: UseDataTableColumnWidthsOptions<TRow>): DataTableColumnWidths<TRow>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ComputedRef } from 'vue';
|
|
2
|
+
export type GrDataTableDetailState = 'idle' | 'loading' | 'error' | 'ready';
|
|
3
|
+
export type GrDataTableRowKey = string | number;
|
|
4
|
+
/** Подгрузка подробностей строки. `signal` обязателен: строку сворачивают чаще, чем ждут. */
|
|
5
|
+
export type GrDataTableLoadDetail<TRow> = (row: TRow, signal: AbortSignal) => Promise<unknown>;
|
|
6
|
+
/**
|
|
7
|
+
* Раскрытие строк `GrDataTable`: состояние второго яруса и его подгрузка.
|
|
8
|
+
*
|
|
9
|
+
* Всё хранится **по ключу строки**, а не по индексу: сортировка и смена
|
|
10
|
+
* страницы переставляют строки, и привязка к позиции показывала бы подробности
|
|
11
|
+
* соседа.
|
|
12
|
+
*
|
|
13
|
+
* Асинхронность здесь по образцу `GrAutocomplete/useRemoteOptions`, а не
|
|
14
|
+
* `useTree`: у дерева ленивая загрузка живёт колбэком без пути ошибки — не
|
|
15
|
+
* позвал потребитель `resolve`, и узел грузится вечно. Строка обязана уметь
|
|
16
|
+
* показать отказ и дать повтор.
|
|
17
|
+
*/
|
|
18
|
+
export interface UseDataTableExpansionOptions<TRow extends Record<string, unknown>> {
|
|
19
|
+
/** Контролируемый список. `undefined` — состояние помнит компонент. */
|
|
20
|
+
expandedKeys: () => GrDataTableRowKey[] | undefined;
|
|
21
|
+
/** Идентичность набора: её смена сбрасывает кэш подробностей. */
|
|
22
|
+
rows: () => TRow[];
|
|
23
|
+
expandableRow: () => ((row: TRow) => boolean) | undefined;
|
|
24
|
+
loadDetail: () => GrDataTableLoadDetail<TRow> | undefined;
|
|
25
|
+
/** Раскрыта не больше одной строки. */
|
|
26
|
+
accordion: () => boolean;
|
|
27
|
+
rowKeyValue: (row: TRow) => GrDataTableRowKey;
|
|
28
|
+
onExpandedChange: (keys: GrDataTableRowKey[]) => void;
|
|
29
|
+
onExpand: (row: TRow, key: GrDataTableRowKey) => void;
|
|
30
|
+
onCollapse: (row: TRow, key: GrDataTableRowKey) => void;
|
|
31
|
+
onDetailLoadError: (row: TRow, key: GrDataTableRowKey, error: unknown) => void;
|
|
32
|
+
}
|
|
33
|
+
export interface DataTableExpansion<TRow extends Record<string, unknown>> {
|
|
34
|
+
expandedKeys: ComputedRef<Set<GrDataTableRowKey>>;
|
|
35
|
+
isRowExpandable: (row: TRow) => boolean;
|
|
36
|
+
isRowExpanded: (row: TRow) => boolean;
|
|
37
|
+
toggleRow: (row: TRow) => void;
|
|
38
|
+
collapseAll: () => void;
|
|
39
|
+
detailStateOf: (row: TRow) => GrDataTableDetailState;
|
|
40
|
+
detailDataOf: (row: TRow) => unknown;
|
|
41
|
+
/** Повтор после отказа — и он же ручной перезапрос. */
|
|
42
|
+
retryDetail: (row: TRow) => void;
|
|
43
|
+
/** Сбросить загруженное: у ключа либо целиком. */
|
|
44
|
+
invalidateDetail: (key?: GrDataTableRowKey) => void;
|
|
45
|
+
}
|
|
46
|
+
export declare function useDataTableExpansion<TRow extends Record<string, unknown>>(options: UseDataTableExpansionOptions<TRow>): DataTableExpansion<TRow>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ComputedRef } from 'vue';
|
|
2
|
+
import type { GrDataColumn } from '../GrDataTable.vue';
|
|
3
|
+
/** Служебная колонка выбора в реестре ячеек: своего ключа у неё нет. */
|
|
4
|
+
export declare const SELECT_COLUMN_KEY = "__select__";
|
|
5
|
+
/**
|
|
6
|
+
* Раскладка закреплённых колонок: смещения липких ячеек и замер шапки.
|
|
7
|
+
*
|
|
8
|
+
* Единственный модуль таблицы, который целиком про DOM. Смещения нельзя
|
|
9
|
+
* вычислить из пропов: колонка может жить на авторазметке, и её ширина
|
|
10
|
+
* известна только после отрисовки — отсюда замер, а не `computed`.
|
|
11
|
+
*/
|
|
12
|
+
export interface UseDataTableLayoutOptions<TRow extends Record<string, unknown>> {
|
|
13
|
+
orderedColumns: () => GrDataColumn<TRow>[];
|
|
14
|
+
columnKeys: () => string[];
|
|
15
|
+
selectable: () => boolean;
|
|
16
|
+
resizableColumns: () => boolean;
|
|
17
|
+
headerCellEls: Map<string, HTMLElement>;
|
|
18
|
+
/** Пересчитать раскладку заново при смене этих значений. */
|
|
19
|
+
watchSources: () => unknown;
|
|
20
|
+
/** Измеренные ширины уезжают модулю ширин: ручка ресайза называет по ним значение. */
|
|
21
|
+
onMeasuredWidths: (widths: Record<string, number>) => void;
|
|
22
|
+
}
|
|
23
|
+
export interface DataTableLayout<TRow extends Record<string, unknown>> {
|
|
24
|
+
hasPinnedLeft: ComputedRef<boolean>;
|
|
25
|
+
pinnedStyleOf: (col: GrDataColumn<TRow>) => Record<string, string> | undefined;
|
|
26
|
+
pinnedCellClass: (col: GrDataColumn<TRow>, index: number) => string[];
|
|
27
|
+
measureLayout: () => void;
|
|
28
|
+
}
|
|
29
|
+
export declare function useDataTableLayout<TRow extends Record<string, unknown>>(options: UseDataTableLayoutOptions<TRow>): DataTableLayout<TRow>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GrDataTableRowKey } from '../GrDataTable.vue';
|
|
2
|
+
/**
|
|
3
|
+
* Ключ строки: значение из данных, а при его отсутствии — синтетический.
|
|
4
|
+
*
|
|
5
|
+
* Без синтетического строка получила бы `String(undefined ?? '')` — **один и
|
|
6
|
+
* тот же** ключ на всю таблицу: Vue переиспользовал бы DOM не по назначению, а
|
|
7
|
+
* выбор одной строки помечал бы выбранными все. Ключ привязан к идентичности
|
|
8
|
+
* объекта, поэтому переживает сортировку и не зависит от индекса.
|
|
9
|
+
*/
|
|
10
|
+
export interface UseDataTableRowKeysOptions<TRow extends Record<string, unknown>> {
|
|
11
|
+
rowKey: () => GrDataTableRowKey<TRow>;
|
|
12
|
+
}
|
|
13
|
+
export interface DataTableRowKeys<TRow extends Record<string, unknown>> {
|
|
14
|
+
rowKeyValue: (row: TRow) => string | number;
|
|
15
|
+
}
|
|
16
|
+
export declare function useDataTableRowKeys<TRow extends Record<string, unknown>>(options: UseDataTableRowKeysOptions<TRow>): DataTableRowKeys<TRow>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ComputedRef } from 'vue';
|
|
2
|
+
/**
|
|
3
|
+
* Выбор строк `GrDataTable`.
|
|
4
|
+
*
|
|
5
|
+
* Считается по **видимым и выбираемым** строкам: они же дают состояние
|
|
6
|
+
* галочки в шапке. Ключи строк, которых сейчас в наборе нет (отфильтрованы,
|
|
7
|
+
* на другой странице), из выбора не выпадают — «снять все» убирает только
|
|
8
|
+
* видимые.
|
|
9
|
+
*
|
|
10
|
+
* Как и сортировка, эмитов не знает: наружу сообщает `onSelectedChange`.
|
|
11
|
+
*/
|
|
12
|
+
export interface UseDataTableSelectionOptions<TRow extends Record<string, unknown>> {
|
|
13
|
+
/** Строки в текущем порядке — уже отсортированные. */
|
|
14
|
+
rows: () => TRow[];
|
|
15
|
+
/** Контролируемый список ключей. `undefined` — компонент помнит выбор сам. */
|
|
16
|
+
selected: () => Array<string | number> | undefined;
|
|
17
|
+
selectableRow: () => ((row: TRow) => boolean) | undefined;
|
|
18
|
+
rowKeyValue: (row: TRow) => string | number;
|
|
19
|
+
onSelectedChange: (keys: Array<string | number>) => void;
|
|
20
|
+
}
|
|
21
|
+
export interface DataTableSelection<TRow extends Record<string, unknown>> {
|
|
22
|
+
selectedKeys: ComputedRef<Set<string | number>>;
|
|
23
|
+
isRowSelectable: (row: TRow) => boolean;
|
|
24
|
+
isRowSelected: (row: TRow) => boolean;
|
|
25
|
+
/** Видимые выбираемые строки: по их числу шапка гасит «выбрать все». */
|
|
26
|
+
selectableRows: ComputedRef<TRow[]>;
|
|
27
|
+
allSelected: ComputedRef<boolean>;
|
|
28
|
+
someSelected: ComputedRef<boolean>;
|
|
29
|
+
toggleRow: (row: TRow) => void;
|
|
30
|
+
toggleAll: () => void;
|
|
31
|
+
}
|
|
32
|
+
export declare function useDataTableSelection<TRow extends Record<string, unknown>>(options: UseDataTableSelectionOptions<TRow>): DataTableSelection<TRow>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ComputedRef } from 'vue';
|
|
2
|
+
import type { GrDataColumn, GrDataTableSortCycle } from '../GrDataTable.vue';
|
|
3
|
+
import type { GrDataTableSortDir } from '../grDataTableSort';
|
|
4
|
+
/**
|
|
5
|
+
* Сортировка `GrDataTable`: состояние, порядок строк и обход состояний по клику.
|
|
6
|
+
*
|
|
7
|
+
* Модель эмитов не знает — о смене сообщает колбэком `onSortChange`, а
|
|
8
|
+
* `update:sortKey`/`update:sortDir`/`sortChange` остаются заботой компонента.
|
|
9
|
+
* Так же устроен `GrTree`: модель отдельно, эмиты связывает SFC.
|
|
10
|
+
*
|
|
11
|
+
* Сравнение значений, включая пустые и смешанные типы, живёт в
|
|
12
|
+
* `grDataTableSort.ts` и здесь только вызывается.
|
|
13
|
+
*/
|
|
14
|
+
export interface UseDataTableSortOptions<TRow extends Record<string, unknown>> {
|
|
15
|
+
rows: () => TRow[];
|
|
16
|
+
/** Контролируемый ключ. `undefined` — компонент помнит порядок сам. */
|
|
17
|
+
sortKey: () => string | undefined;
|
|
18
|
+
/** Контролируемое направление. */
|
|
19
|
+
sortDir: () => GrDataTableSortDir | undefined;
|
|
20
|
+
initialSortKey: () => string | undefined;
|
|
21
|
+
initialSortDir: () => GrDataTableSortDir;
|
|
22
|
+
/** Внешняя сортировка: `rows` приходят уже отсортированными. */
|
|
23
|
+
externalSort: () => boolean;
|
|
24
|
+
sortCycle: () => GrDataTableSortCycle;
|
|
25
|
+
/** Язык сравнения строк; не задан — сравнение по умолчанию рантайма. */
|
|
26
|
+
locale: () => string | undefined;
|
|
27
|
+
onSortChange: (key: string, dir: GrDataTableSortDir) => void;
|
|
28
|
+
}
|
|
29
|
+
export interface DataTableSort<TRow extends Record<string, unknown>> {
|
|
30
|
+
currentSortKey: ComputedRef<string>;
|
|
31
|
+
currentSortDir: ComputedRef<GrDataTableSortDir>;
|
|
32
|
+
sortedRows: ComputedRef<TRow[]>;
|
|
33
|
+
toggleSort: (col: GrDataColumn<TRow>) => void;
|
|
34
|
+
clearSort: () => void;
|
|
35
|
+
ariaSortFor: (col: GrDataColumn<TRow>) => 'ascending' | 'descending' | 'none' | undefined;
|
|
36
|
+
}
|
|
37
|
+
export declare function useDataTableSort<TRow extends Record<string, unknown>>(options: UseDataTableSortOptions<TRow>): DataTableSort<TRow>;
|
|
@@ -72,3 +72,26 @@ export declare const headerGaps: Record<GrDataTableSize, string>;
|
|
|
72
72
|
export declare const spinnerSizes: Record<GrDataTableSize, string>;
|
|
73
73
|
/** Стрелка сортировки берёт размер из шкалы `GrIcon` (`xs…lg` → `14…20px`). */
|
|
74
74
|
export declare const sortIconSizes: Record<GrDataTableSize, GrComponentSize>;
|
|
75
|
+
/**
|
|
76
|
+
* Второй ярус строки: подробности под ней.
|
|
77
|
+
*
|
|
78
|
+
* Фон мягче строки набора, а не ярче: подробности обязаны читаться как
|
|
79
|
+
* вложенное в строку, а не как следующая строка. Акцентная полоса слева
|
|
80
|
+
* связывает деталь с её строкой, когда между ними уже прокрутили.
|
|
81
|
+
*/
|
|
82
|
+
export declare const detailRowClass = "bg-[var(--gr-datatable-detail-bg,color-mix(in_srgb,var(--gr-muted)_45%,transparent))]";
|
|
83
|
+
export declare const detailCellClass = "border-t border-[var(--gr-brd)] border-l-2 border-l-[var(--gr-datatable-detail-accent,var(--gr-primary))]";
|
|
84
|
+
/** Содержимое липнет к левому краю: иначе при горизонтальной прокрутке его не видно. */
|
|
85
|
+
export declare const detailContentClass = "sticky left-0";
|
|
86
|
+
export declare const detailPaddings: Record<GrDataTableSize, string>;
|
|
87
|
+
/** Колонка кнопки раскрытия — той же ширины, что колонка выбора: шапка не должна съезжать. */
|
|
88
|
+
export declare const expandColumnWidths: Record<"xs" | "sm" | "md" | "lg", string>;
|
|
89
|
+
export declare const expandButtonClass = "inline-flex 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)]";
|
|
90
|
+
/**
|
|
91
|
+
* Поворот шеврона. Своего `motion-reduce:` здесь нет намеренно: движение пакет
|
|
92
|
+
* гасит одним глобальным блоком в `base.css`, а под `presetMini` этот вариант
|
|
93
|
+
* вдобавок не генерирует CSS вовсе (`docs/motion.md`).
|
|
94
|
+
*/
|
|
95
|
+
export declare const expandIconClass = "h-4 w-4 transition-transform duration-[var(--gr-duration-fast)]";
|
|
96
|
+
export declare const expandIconOpenClass = "rotate-90";
|
|
97
|
+
export declare const detailErrorClass = "flex flex-wrap items-center gap-2 text-[var(--gr-invalid-text)]";
|
|
@@ -17,7 +17,13 @@ export interface GrFormFieldProps {
|
|
|
17
17
|
error?: string | string[];
|
|
18
18
|
/** Подсказка под лейблом/над контролом (можно также через слот `#hint`). */
|
|
19
19
|
hint?: string;
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Помечает поле обязательным: маркер `*` в подписи и `aria-required` у контрола.
|
|
22
|
+
*
|
|
23
|
+
* Маркер помечен `aria-hidden`, поэтому объявляет обязательность именно
|
|
24
|
+
* контрол — а чем именно, решает его роль. Разбор случая `role="group"`,
|
|
25
|
+
* который `aria-required` не допускает, — на странице компонента.
|
|
26
|
+
*/
|
|
21
27
|
required?: boolean;
|
|
22
28
|
/** Всё поле только для чтения: контролы внутри перестают редактироваться. */
|
|
23
29
|
readonly?: boolean;
|