@feugene/granularity 0.43.0 → 0.45.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 (78) hide show
  1. package/README.md +2 -2
  2. package/dist/chunks/config-BkQ2jvXv.js +49 -0
  3. package/dist/chunks/config-BkQ2jvXv.js.map +1 -0
  4. package/dist/chunks/config-ChnYtO4o.js +28 -0
  5. package/dist/chunks/config-ChnYtO4o.js.map +1 -0
  6. package/dist/chunks/{en-C_QkUTRL.js → en-DiHzFact.js} +3 -1
  7. package/dist/chunks/en-DiHzFact.js.map +1 -0
  8. package/dist/chunks/{es-DemSEhZE.js → es-1ZL6NtkB.js} +3 -1
  9. package/dist/chunks/es-1ZL6NtkB.js.map +1 -0
  10. package/dist/chunks/{es-B4t_3Wnh.js → es-CeKkMxZ_.js} +3 -3
  11. package/dist/chunks/{es-B4t_3Wnh.js.map → es-CeKkMxZ_.js.map} +1 -1
  12. package/dist/chunks/{generated-VcxJTo_q.js → generated-DAKeOOqm.js} +45 -3
  13. package/dist/chunks/{generated-VcxJTo_q.js.map → generated-DAKeOOqm.js.map} +1 -1
  14. package/dist/chunks/{granular-provider-BohXQcNt.js → granular-provider-D_8_l-gM.js} +4 -0
  15. package/dist/chunks/granular-provider-D_8_l-gM.js.map +1 -0
  16. package/dist/chunks/{ru-CLUErjhY.js → ru-Dr2RYn0P.js} +3 -1
  17. package/dist/chunks/ru-Dr2RYn0P.js.map +1 -0
  18. package/dist/chunks/useScrollSpy-CIJpw0RI.js +360 -0
  19. package/dist/chunks/useScrollSpy-CIJpw0RI.js.map +1 -0
  20. package/dist/chunks/useTree-BebEiBcL.js +525 -0
  21. package/dist/chunks/useTree-BebEiBcL.js.map +1 -0
  22. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-CwCBMh4h.js → GrJsonViewer-CdlWMGnF.js} +1 -1
  23. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-CwCBMh4h.js.map → GrJsonViewer-CdlWMGnF.js.map} +1 -1
  24. package/dist/components/GrJsonViewer/index.js +1 -1
  25. package/dist/components/GrScrollSpy/chunks/GrScrollSpy-CQCH3zLC.js +207 -0
  26. package/dist/components/GrScrollSpy/chunks/GrScrollSpy-CQCH3zLC.js.map +1 -0
  27. package/dist/components/GrScrollSpy/index.js +3 -0
  28. package/dist/components/GrTree/chunks/{GrTree-CkHzgYg1.js → GrTree-DnDGW0xO.js} +103 -540
  29. package/dist/components/GrTree/chunks/GrTree-DnDGW0xO.js.map +1 -0
  30. package/dist/components/GrTree/index.js +2 -2
  31. package/dist/components/GrTree/styles.css +1 -1
  32. package/dist/components/GrTreeSections/chunks/GrTreeSections-D2PQ87mw.js +147 -0
  33. package/dist/components/GrTreeSections/chunks/GrTreeSections-D2PQ87mw.js.map +1 -0
  34. package/dist/components/GrTreeSections/index.js +3 -0
  35. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DUsv3_mF.js → GrTreeSelect-DzheDCuZ.js} +1 -1
  36. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DUsv3_mF.js.map → GrTreeSelect-DzheDCuZ.js.map} +1 -1
  37. package/dist/components/GrTreeSelect/index.js +1 -1
  38. package/dist/composables/useScrollSpy.js +2 -0
  39. package/dist/composables/useTree.js +2 -0
  40. package/dist/granular-provider-node.js +1 -1
  41. package/dist/granular-provider.js +1 -1
  42. package/dist/i18n/all.js +1 -1
  43. package/dist/i18n/index.js +1 -1
  44. package/dist/index.js +10 -4
  45. package/dist/theme.js +1 -1
  46. package/dist/tokens.js +1 -1
  47. package/dist/types/components/GrScrollSpy/GrScrollSpy.vue.d.ts +105 -0
  48. package/dist/types/components/GrScrollSpy/config.d.ts +1 -0
  49. package/dist/types/components/GrScrollSpy/grScrollSpyStyles.d.ts +26 -0
  50. package/dist/types/components/GrScrollSpy/index.d.ts +9 -0
  51. package/dist/types/components/GrScrollSpy/safelist.d.ts +1 -0
  52. package/dist/types/components/GrScrollSpy/scrollSpyItems.d.ts +44 -0
  53. package/dist/types/components/GrTree/grTreeProps.d.ts +8 -1
  54. package/dist/types/components/GrTree/grTreeStyles.d.ts +12 -0
  55. package/dist/types/components/GrTree/index.d.ts +3 -2
  56. package/dist/types/components/GrTreeSections/GrTreeSections.vue.d.ts +71 -0
  57. package/dist/types/components/GrTreeSections/config.d.ts +1 -0
  58. package/dist/types/components/GrTreeSections/grTreeSectionsStyles.d.ts +8 -0
  59. package/dist/types/components/GrTreeSections/index.d.ts +8 -0
  60. package/dist/types/components/GrTreeSections/safelist.d.ts +1 -0
  61. package/dist/types/composables/internal/scrollSpyGeometry.d.ts +67 -0
  62. package/dist/types/{components/GrTree/grTreeDataAdapter.d.ts → composables/internal/treeAdapter.d.ts} +3 -3
  63. package/dist/types/{components/GrTree/grTreeChecking.d.ts → composables/internal/treeChecking.d.ts} +1 -1
  64. package/dist/types/composables/useScrollSpy.d.ts +59 -0
  65. package/dist/types/composables/useTree.d.ts +107 -0
  66. package/dist/types/granular-provider/shared.d.ts +2 -0
  67. package/dist/types/i18n/messages/en.d.ts +6 -0
  68. package/dist/types/i18n/messages/es.d.ts +6 -0
  69. package/dist/types/i18n/messages/ru.d.ts +6 -0
  70. package/dist/types/index.d.ts +6 -0
  71. package/dist/web-types.json +238 -3
  72. package/package.json +17 -1
  73. package/dist/chunks/en-C_QkUTRL.js.map +0 -1
  74. package/dist/chunks/es-DemSEhZE.js.map +0 -1
  75. package/dist/chunks/granular-provider-BohXQcNt.js.map +0 -1
  76. package/dist/chunks/ru-CLUErjhY.js.map +0 -1
  77. package/dist/components/GrTree/chunks/GrTree-CkHzgYg1.js.map +0 -1
  78. package/dist/types/components/GrTree/grTreeStore.d.ts +0 -71
@@ -0,0 +1,9 @@
1
+ import type { ComponentExposed } from '../shared/instance';
2
+ import type GrScrollSpyComponent from './GrScrollSpy.vue';
3
+ export { default } from './GrScrollSpy.vue';
4
+ export { default as GrScrollSpy } from './GrScrollSpy.vue';
5
+ export type { GrScrollSpyEmits, GrScrollSpyProps } from './GrScrollSpy.vue';
6
+ export type { GrScrollSpySection } from './scrollSpyItems';
7
+ export { grScrollSpyConfig } from './config';
8
+ export { grScrollSpySafelist } from './safelist';
9
+ export type GrScrollSpyInstance = ComponentExposed<typeof GrScrollSpyComponent>;
@@ -0,0 +1 @@
1
+ export declare const grScrollSpySafelist: string[];
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Арифметика пунктов оглавления: всё, что следует из того, что пункт —
3
+ * **ссылка**, а не из положения прокрутки. Положение живёт в
4
+ * `composables/internal/scrollSpyGeometry.ts`.
5
+ */
6
+ /** Раздел в оглавлении. */
7
+ export interface GrScrollSpySection {
8
+ id: string;
9
+ label: string;
10
+ /** Уровень вложенности, 1 — верхний. Влияет на отступ и цепочку предков. */
11
+ level?: number;
12
+ }
13
+ /**
14
+ * Значение пропа `offset` в CSS-длину для инлайновой переменной.
15
+ *
16
+ * Строка уходит как есть и намеренно не валидируется: `4rem`,
17
+ * `var(--gr-navbar-height)`, `calc(…)` обязаны работать — иначе проп проигрывает
18
+ * голому `style`. Отрицательное зажимается в ноль: линия активации выше верха
19
+ * скроллпорта смысла не имеет.
20
+ */
21
+ export declare function scrollSpyOffsetLength(value: number | string | undefined): string | undefined;
22
+ /**
23
+ * Наш ли это клик.
24
+ *
25
+ * Пункт остаётся `<a href="#id">` ровно ради того, что браузер умеет с ссылкой
26
+ * сам: `Cmd`-клик открывает в новой вкладке, средняя кнопка — тоже. Перехватив
27
+ * их, компонент отнял бы у пользователя работающее поведение и ничего не дал
28
+ * взамен.
29
+ */
30
+ export declare function anchorClickHandled(event: {
31
+ button: number;
32
+ metaKey: boolean;
33
+ ctrlKey: boolean;
34
+ shiftKey: boolean;
35
+ altKey: boolean;
36
+ defaultPrevented: boolean;
37
+ }): boolean;
38
+ /**
39
+ * Предки активного пункта — те разделы выше по списку, чей уровень мельче.
40
+ *
41
+ * Считается по документному порядку массива, а не по дереву: дерево позволило
42
+ * бы объявить вложенность, противоречащую порядку разделов на странице.
43
+ */
44
+ export declare function ancestorSectionIds(sections: readonly GrScrollSpySection[], activeId: string | null): Set<string>;
@@ -9,6 +9,7 @@ export type GrTreePropsMap = {
9
9
  isLeaf?: string;
10
10
  };
11
11
  export type GrTreeFilterNodeMethod<T extends object = any> = (value: string, data: T, node?: GrTreeNode<T>) => boolean;
12
+ export type GrTreeBranchLine = 'line' | 'elbow';
12
13
  export type GrTreeBranchLineColor<T extends object = any> = string | ((node: GrTreeNode<T>) => string | undefined | null);
13
14
  export type GrTreeVisibleRow<T extends object> = {
14
15
  node: GrTreeNode<T>;
@@ -89,7 +90,13 @@ export type GrTreeViewProps<T extends object> = {
89
90
  /** Иконка раскрытого узла. Не задана — та же встроенная стрелка, повёрнутая. */
90
91
  collapseIcon?: string | Component;
91
92
  toggleIconRotate?: boolean;
92
- branchLine?: boolean;
93
+ /**
94
+ * Направляющие уровней. `true` — то же, что `'line'`: одна вертикаль на
95
+ * уровень. `'elbow'` добавляет горизонтальное колено к строке и обрывает
96
+ * линию на середине последнего ребёнка — так видно не только уровень, но и
97
+ * то, какие ветки ещё продолжаются.
98
+ */
99
+ branchLine?: boolean | GrTreeBranchLine;
93
100
  branchLineColor?: GrTreeBranchLineColor<T>;
94
101
  branchLineActiveColor?: GrTreeBranchLineColor<T>;
95
102
  rowClass?: GrTreeNodeClass<T>;
@@ -20,3 +20,15 @@ export type GrTreeSizeVars = {
20
20
  '--gr-tree-font-size': string;
21
21
  };
22
22
  export declare const treeSizeVars: Record<GrTreeSize, GrTreeSizeVars>;
23
+ /**
24
+ * Готовые виды дерева — наборы значений тех же `--gr-tree-*`, что задаёт
25
+ * `size`. Не проп: второй канал спорил бы с размером за одни переменные, а
26
+ * набор с ним композируется — потребитель раскладывает его в `style` и при
27
+ * необходимости переопределяет по одной строке.
28
+ *
29
+ * Шрифт и значки в набор не входят: семейства у дерева своего токена нет, а
30
+ * значки — это `expandIcon`/`collapseIcon` и слот строки, то есть решение
31
+ * потребителя, а не вида.
32
+ */
33
+ export type GrTreeView = 'explorer' | 'rail' | 'outline';
34
+ export declare const grTreeViewVars: Record<GrTreeView, Record<string, string>>;
@@ -2,9 +2,10 @@ export { default } from './GrTree.vue';
2
2
  export { default as GrTree } from './GrTree.vue';
3
3
  export type { GrTreeAllowDropType, GrTreeInstance, GrTreeKey, GrTreeNode, GrTreeNodeDropType, GrTreeNodeTarget, } from './grTreeTypes';
4
4
  export type { GrTreeBranchLineColor, GrTreeFilterNodeMethod, GrTreeLoad, GrTreeNodeClass, GrTreeProps, GrTreePropsMap, GrTreeSelectionProps, GrTreeVisibleRow, } from './grTreeProps';
5
- export type { GrTreeCheckState } from './grTreeChecking';
5
+ export type { GrTreeCheckState } from '../../composables/internal/treeChecking';
6
6
  export { grTreeConfig } from './config';
7
7
  export type { GrTreeConfigurableProps } from './defaults';
8
- export type { GrTreeSize } from './grTreeStyles';
8
+ export { grTreeViewVars } from './grTreeStyles';
9
+ export type { GrTreeSize, GrTreeView } from './grTreeStyles';
9
10
  export { grTreeSafelist } from './safelist';
10
11
  export type { GrTreeEmits } from './GrTree.vue';
@@ -0,0 +1,71 @@
1
+ import type { GrTreeKey, GrTreeNode } from '../GrTree/grTreeTypes';
2
+ import type { GrTreeBranchLine, GrTreeDataProps, GrTreePropsMap } from '../GrTree/grTreeProps';
3
+ import type { GrComponentSize } from '../shared/sizes';
4
+ /**
5
+ * GrTreeSections — дерево, у которого верхний уровень стал рубрикой.
6
+ *
7
+ * Внутри это не одно дерево с заголовками между строк, а **несколько деревьев**:
8
+ * `role="tree"` требует, чтобы его детьми были `treeitem`, и заголовок посреди
9
+ * них либо ломал бы паттерн, либо врал диктору, оставаясь строкой. Заголовки
10
+ * между отдельными деревьями законны, и каждая группа объявляется сама собой.
11
+ *
12
+ * Отсюда же граница: клавиатурное кольцо у каждой группы своё, `Tab` переходит
13
+ * между ними. Это верно по существу — группы независимы.
14
+ */
15
+ export interface GrTreeSectionsProps<TData extends object = any> {
16
+ /** Данные обычного дерева. Корни становятся заголовками, их дети — деревьями. */
17
+ data: TData[];
18
+ nodeKey?: GrTreeDataProps<TData>['nodeKey'];
19
+ props?: GrTreePropsMap;
20
+ size?: GrComponentSize;
21
+ /** Уровень заголовка группы под структуру страницы. */
22
+ headingLevel?: 2 | 3 | 4 | 5 | 6;
23
+ /** Показывать число узлов первого уровня в группе. */
24
+ showCount?: boolean;
25
+ showCheckbox?: boolean;
26
+ checkStrictly?: boolean;
27
+ branchLine?: boolean | GrTreeBranchLine;
28
+ indent?: number;
29
+ defaultExpandedKeys?: GrTreeKey[];
30
+ currentKey?: GrTreeKey;
31
+ checkedKeys?: GrTreeKey[];
32
+ }
33
+ export interface GrTreeSectionsEmits {
34
+ (e: 'update:currentKey', key: GrTreeKey | undefined): void;
35
+ (e: 'update:checkedKeys', keys: GrTreeKey[]): void;
36
+ (e: 'nodeClick', data: any, node: GrTreeNode<any>): void;
37
+ }
38
+ declare const __VLS_export: <T extends Record<string, any> = any>(__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<{
39
+ props: import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & __VLS_PrettifyLocal<GrTreeSectionsProps<T> & {
40
+ onNodeClick?: ((data: any, node: GrTreeNode<any>) => any) | undefined;
41
+ "onUpdate:currentKey"?: ((key: GrTreeKey | undefined) => any) | undefined;
42
+ "onUpdate:checkedKeys"?: ((keys: GrTreeKey[]) => any) | undefined;
43
+ }> & (typeof globalThis extends {
44
+ __VLS_PROPS_FALLBACK: infer P;
45
+ } ? P : {});
46
+ expose: (exposed: {}) => void;
47
+ attrs: any;
48
+ slots: {
49
+ /** Заголовок группы целиком — вместо подписи корневого узла. */
50
+ heading?: (props: {
51
+ data: T;
52
+ label: string;
53
+ count: number;
54
+ }) => unknown;
55
+ /** Строка внутри группы, как у `GrTree`. */
56
+ default?: (props: {
57
+ node: GrTreeNode<T>;
58
+ data: T;
59
+ }) => unknown;
60
+ };
61
+ emit: GrTreeSectionsEmits;
62
+ }>) => import("vue").VNode & {
63
+ __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
64
+ };
65
+ declare const _default: typeof __VLS_export;
66
+ export default _default;
67
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
68
+ [K in keyof T]: T[K];
69
+ } : {
70
+ [K in keyof T as K]: T[K];
71
+ }) & {};
@@ -0,0 +1 @@
1
+ export declare const grTreeSectionsConfig: import("@feugene/unocss-preset-granular/contract").GranularComponentDescriptor<"GrTreeSections">;
@@ -0,0 +1,8 @@
1
+ export declare const treeSectionsRootClass = "flex flex-col gap-4";
2
+ /**
3
+ * Заголовок группы набирается капителью и отделяется линией: он объявляет
4
+ * рубрику, а не узел, и должен читаться иначе, чем строки под ним.
5
+ */
6
+ export declare const treeSectionsHeadClass = "flex items-baseline gap-2 pb-1 text-[length:var(--gr-text-xs)] leading-[var(--gr-leading-xs)] uppercase tracking-wider text-[var(--gr-muted-fg)] border-b border-[var(--gr-brd)]";
7
+ export declare const treeSectionsCountClass = "ml-auto text-[var(--gr-muted-fg)] [font-variant-numeric:tabular-nums]";
8
+ export declare const treeSectionsGroupClass = "flex flex-col gap-1";
@@ -0,0 +1,8 @@
1
+ import type { ComponentExposed } from '../shared/instance';
2
+ import type GrTreeSectionsComponent from './GrTreeSections.vue';
3
+ export { default } from './GrTreeSections.vue';
4
+ export { default as GrTreeSections } from './GrTreeSections.vue';
5
+ export type { GrTreeSectionsEmits, GrTreeSectionsProps } from './GrTreeSections.vue';
6
+ export { grTreeSectionsConfig } from './config';
7
+ export { grTreeSectionsSafelist } from './safelist';
8
+ export type GrTreeSectionsInstance = ComponentExposed<typeof GrTreeSectionsComponent>;
@@ -0,0 +1 @@
1
+ export declare const grTreeSectionsSafelist: string[];
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Арифметика положения чтения: чистые функции без DOM и без реактивности.
3
+ *
4
+ * Вынесена отдельно по той же причине, что и геометрия перестановки в
5
+ * `dragSortGeometry.ts`: ошибка здесь проявляется не исключением, а
6
+ * «подсветился не тот раздел», и поймать это можно только тестом на числах. В
7
+ * jsdom проверить нечем вовсе — там нет ни прокрутки, ни раскладки.
8
+ *
9
+ * Композабл `useScrollSpy` сводит `DOMRect` к числам и зовёт эти функции; что
10
+ * значит активный раздел для разметки, решает уже компонент.
11
+ */
12
+ /** Верх раздела в координатах вьюпорта. */
13
+ export interface ScrollSpyRect {
14
+ id: string;
15
+ top: number;
16
+ }
17
+ /**
18
+ * Какой раздел читают сейчас.
19
+ *
20
+ * Правило — «последний, чей верх выше линии», а не «самый видимый». Максимум
21
+ * доли пересечения ошибается двумя способами: длинный раздел выигрывает у
22
+ * короткого независимо от того, что читают, и подсветка отскакивает назад,
23
+ * когда следующий раздел только показался снизу. Здесь ответ — заголовок,
24
+ * ближайший сверху к линии чтения.
25
+ *
26
+ * Порядок массива на ответ не влияет: выбор идёт по геометрии. Это снимает
27
+ * класс дефектов, где объявленный список разошёлся с порядком разделов на
28
+ * странице — подсветку в таком случае невозможно отладить.
29
+ *
30
+ * `atEnd` побеждает правило линии, и без него последний раздел недостижим:
31
+ * раздел короче остатка скроллпорта никогда не доводит свой верх до линии,
32
+ * потому что прокрутка кончается раньше.
33
+ */
34
+ export declare function activeSectionId(rects: readonly ScrollSpyRect[], line: number, atEnd: boolean): string | null;
35
+ /**
36
+ * `rootMargin` наблюдателя: верх корня поджимается на отступ, и тогда его край
37
+ * совпадает с линией активации.
38
+ *
39
+ * Единицы только `px`: `rootMargin` произвольных длин не принимает, поэтому
40
+ * отступ приходит сюда уже замеренным.
41
+ */
42
+ export declare function scrollSpyRootMargin(offsetPx: number): string;
43
+ /**
44
+ * Куда прокрутить скроллпорт, чтобы верх раздела встал на линию активации.
45
+ *
46
+ * Своя арифметика вместо `scrollIntoView` — по трём независимым причинам:
47
+ * тот двигает всех предков (у карусели это стоило прыжка страницы на каждом
48
+ * шаге автопрокрутки), не умеет наш отступ, и в jsdom отсутствует вовсе, то
49
+ * есть клик стал бы непроверяемым.
50
+ */
51
+ export declare function scrollSpyTargetTop(scrollTop: number, sectionTop: number, portTop: number, offset: number, maxScrollTop: number): number;
52
+ /**
53
+ * Прокручивается ли предок.
54
+ *
55
+ * Читается вычисленный `overflow-y`, а не объявленный: при
56
+ * `overflow-x: hidden; overflow-y: visible` спецификация превращает вычисленный
57
+ * `overflow-y` в `auto`, то есть предок действительно становится скроллпортом.
58
+ */
59
+ export declare function isScrollableOverflow(overflowY: string): boolean;
60
+ /**
61
+ * Доехали ли до дна.
62
+ *
63
+ * `maxScrollTop > 1` — обязательное условие, а не перестраховка: содержимое
64
+ * короче скроллпорта даёт «дно» на нулевой прокрутке, и правило `atEnd`
65
+ * подсветило бы последний раздел на странице, где позиции чтения нет вовсе.
66
+ */
67
+ export declare function isScrolledToEnd(scrollTop: number, maxScrollTop: number): boolean;
@@ -1,5 +1,5 @@
1
- import type { GrTreeKey } from './grTreeTypes';
2
- import type { GrTreeDataProps } from './grTreeProps';
1
+ import type { GrTreeKey } from '../../components/GrTree/grTreeTypes';
2
+ import type { GrTreeDataProps } from '../../components/GrTree/grTreeProps';
3
3
  export type GrTreeDataAdapterOptions<T extends object> = Pick<GrTreeDataProps<T>, 'props' | 'nodeKey'>;
4
4
  export type GrTreeDataAdapter<T extends object> = {
5
5
  hasNodeKey: () => boolean;
@@ -13,4 +13,4 @@ export type GrTreeDataAdapter<T extends object> = {
13
13
  getNodeKey: (data: T, index: number, parentKey: GrTreeKey | undefined) => GrTreeKey;
14
14
  getExplicitNodeKey: (data: T) => GrTreeKey | undefined;
15
15
  };
16
- export declare function createGrTreeDataAdapter<T extends Record<string, any> = any>(options: GrTreeDataAdapterOptions<T>): GrTreeDataAdapter<T>;
16
+ export declare function createGrTreeDataAdapter<T extends object>(options: GrTreeDataAdapterOptions<T>): GrTreeDataAdapter<T>;
@@ -1,4 +1,4 @@
1
- import type { GrTreeKey, GrTreeNode } from './grTreeTypes';
1
+ import type { GrTreeKey, GrTreeNode } from '../../components/GrTree/grTreeTypes';
2
2
  /**
3
3
  * Состояние отметки узла. `half` — часть потомков отмечена: в ARIA это
4
4
  * `aria-checked="mixed"`.
@@ -0,0 +1,59 @@
1
+ import type { Ref } from 'vue';
2
+ /**
3
+ * Отслеживание того, до какого раздела дочитали.
4
+ *
5
+ * Композабл владеет всем, что следует из **положения прокрутки**: линией
6
+ * активации, выбором раздела, прокруткой к нему и закрепом на время этой
7
+ * прокрутки. Всё, что следует из того, что пункт оглавления является
8
+ * **ссылкой** — разметка, `aria-current`, модификаторы клика, — остаётся у
9
+ * компонента `GrScrollSpy`.
10
+ *
11
+ * ```ts
12
+ * const spy = useScrollSpy({
13
+ * sections: () => ids.value,
14
+ * offset: () => headerHeight.value,
15
+ * onChange: id => emit('activeChange', id),
16
+ * })
17
+ * ```
18
+ */
19
+ export interface UseScrollSpyOptions {
20
+ /**
21
+ * Идентификаторы разделов. Порядок задаёт порядок пунктов у потребителя, но
22
+ * на ответ не влияет: активный выбирается по геометрии.
23
+ */
24
+ sections: () => readonly string[];
25
+ /**
26
+ * Элемент раздела. По умолчанию — `document.getElementById`.
27
+ *
28
+ * Дефолт не догадка: идентификаторы разделов и есть цели ссылок `#id`, то
29
+ * есть DOM-id по определению жанра.
30
+ */
31
+ elementFor?: (id: string) => HTMLElement | null | undefined;
32
+ /** Скроллпорт. Не задан — ищется от первого раздела, не найден — документ. */
33
+ scroller?: () => HTMLElement | null | undefined;
34
+ /**
35
+ * Отступ линии активации от верха скроллпорта, **в пикселях**.
36
+ *
37
+ * Именно число, а не CSS-длина: резолв `4rem` или `var(...)` требует
38
+ * `getComputedStyle`, то есть DOM, — а композабл обязан оставаться
39
+ * проверяемым без него. Длину резолвит потребитель.
40
+ */
41
+ offset?: () => number;
42
+ /** Наблюдение выключено: `active` сбрасывается в `null`. */
43
+ disabled?: () => boolean;
44
+ /** Активный сменился. Зовётся на смене, а не на каждой записи наблюдателя. */
45
+ onChange?: (id: string | null, previous: string | null) => void;
46
+ }
47
+ export interface UseScrollSpyReturn {
48
+ /** Активный раздел. `null` — линия ещё не дошла до первого. */
49
+ active: Readonly<Ref<string | null>>;
50
+ /** Прокрутить к разделу и закрепить его активным до следующей прокрутки. */
51
+ scrollTo: (id: string, options?: {
52
+ behavior?: ScrollBehavior;
53
+ }) => void;
54
+ /** Перечитать отступ, скроллпорт и геометрию. */
55
+ refresh: () => void;
56
+ /** Закрепить активным вручную: страницу прокручивает не оглавление. */
57
+ pin: (id: string | null) => void;
58
+ }
59
+ export declare function useScrollSpy(options: UseScrollSpyOptions): UseScrollSpyReturn;
@@ -0,0 +1,107 @@
1
+ import type { ComputedRef, MaybeRefOrGetter, Ref, ShallowRef } from 'vue';
2
+ import type { GrTreeKey, GrTreeNode, GrTreeNodeDropType, GrTreeNodeTarget } from '../components/GrTree/grTreeTypes';
3
+ import type { GrTreeDataAdapter } from './internal/treeAdapter';
4
+ import type { GrTreeDataProps, GrTreeLoad, GrTreePropsMap, GrTreeVisibleRow } from '../components/GrTree/grTreeProps';
5
+ import type { GrTreeCheckState, GrTreeCheckStates } from './internal/treeChecking';
6
+ export type GrTreeModel<T extends object> = {
7
+ roots: GrTreeNode<T>[];
8
+ byKey: Map<GrTreeKey, GrTreeNode<T>>;
9
+ byData: WeakMap<T, GrTreeNode<T>>;
10
+ };
11
+ export type GrTreeFilterInfo = {
12
+ isActive: boolean;
13
+ subtreeHasMatch: Map<GrTreeKey, boolean>;
14
+ matchedKeys: Set<GrTreeKey>;
15
+ autoExpandKeys: Set<GrTreeKey>;
16
+ };
17
+ export type UseTreeOptions<T extends object> = {
18
+ data: MaybeRefOrGetter<GrTreeDataProps<T>['data']>;
19
+ defaultExpandedKeys?: MaybeRefOrGetter<GrTreeDataProps<T>['defaultExpandedKeys']>;
20
+ defaultExpandAll?: MaybeRefOrGetter<boolean | undefined>;
21
+ /**
22
+ * Совпал ли узел с запросом фильтра.
23
+ *
24
+ * Обычная функция, а не `MaybeRefOrGetter`: `toValue` не отличает геттер от
25
+ * значения-функции и вызвал бы её вместо того, чтобы вернуть. Реактивность
26
+ * при этом не теряется — потребитель читает своё состояние внутри вызова.
27
+ */
28
+ /**
29
+ * Совпал ли узел с запросом. Вернуть `undefined` — оставить решение модели
30
+ * (подстрочный матч по подписи).
31
+ */
32
+ filterNodeMethod?: (value: string, data: T, node: GrTreeNode<T>) => boolean | undefined;
33
+ defaultCheckedKeys?: MaybeRefOrGetter<GrTreeKey[] | undefined>;
34
+ /** Внешние отмеченные ключи (`v-model:checked-keys`), если потребитель их ведёт. */
35
+ checkedKeys?: MaybeRefOrGetter<GrTreeKey[] | undefined>;
36
+ checkStrictly?: MaybeRefOrGetter<boolean | undefined>;
37
+ lazy?: MaybeRefOrGetter<boolean | undefined>;
38
+ /** Загрузка детей ветки. Обычная функция — по той же причине, что `filterNodeMethod`. */
39
+ load?: GrTreeLoad<T>;
40
+ /** Форма данных: поля детей, подписи и признака листа. */
41
+ props?: GrTreePropsMap;
42
+ /** Поле-идентификатор узла. */
43
+ nodeKey?: GrTreeDataProps<T>['nodeKey'];
44
+ /**
45
+ * Готовый адаптер. Не задан — собирается из `props` и `nodeKey`.
46
+ *
47
+ * Необязателен намеренно: фабрика адаптера наружу не публикуется, и
48
+ * требовать её значило бы сделать композабл невызываемым вне пакета.
49
+ * Компонент передаёт свой, потому что уже собрал его для себя.
50
+ */
51
+ adapter?: GrTreeDataAdapter<T>;
52
+ /**
53
+ * Цвет направляющей уровня для узла. Не задан — `branchColors` у строк
54
+ * остаётся пустым: направляющие рисует потребитель, и модель о них не знает.
55
+ *
56
+ * Обычная функция, а не `MaybeRefOrGetter`: `toValue` не отличает геттер от
57
+ * значения-функции и вызвал бы её вместо того, чтобы вернуть.
58
+ */
59
+ branchColorFor?: (node: GrTreeNode<T>) => string | undefined | null;
60
+ };
61
+ export type UseTreeReturn<T extends object> = {
62
+ filterValue: Ref<string>;
63
+ expandedKeys: ShallowRef<Set<GrTreeKey>>;
64
+ checkedKeys: ShallowRef<Set<GrTreeKey>>;
65
+ checkStates: ComputedRef<GrTreeCheckStates>;
66
+ loadingKeys: ShallowRef<Set<GrTreeKey>>;
67
+ loadedKeys: ShallowRef<Set<GrTreeKey>>;
68
+ loadedChildren: ShallowRef<Map<GrTreeKey, T[]>>;
69
+ currentKey: Ref<GrTreeKey | undefined>;
70
+ /**
71
+ * Видимые строки одним плоским списком в порядке отображения — то, из чего
72
+ * строится разметка. Иерархию несут `node.level`, `posInSet` и `setSize`:
73
+ * в плоском DOM группы нет, и структуру диктору сообщают они.
74
+ */
75
+ visibleRows: ComputedRef<GrTreeVisibleRow<T>[]>;
76
+ treeModel: ComputedRef<GrTreeModel<T>>;
77
+ filterInfo: ComputedRef<GrTreeFilterInfo>;
78
+ filter: (value: string) => void;
79
+ isExpandedKey: (key: GrTreeKey) => boolean;
80
+ setExpandedKey: (key: GrTreeKey, expanded: boolean) => void;
81
+ toggleExpand: (node: GrTreeNode<T>) => void;
82
+ setCurrentKey: (key?: GrTreeKey) => void;
83
+ getCurrentKey: () => GrTreeKey | undefined;
84
+ getCurrentNode: () => GrTreeNode<T> | undefined;
85
+ setCurrentNode: (node?: GrTreeNodeTarget<T>) => boolean;
86
+ getNode: (key: GrTreeKey) => GrTreeNode<T> | undefined;
87
+ canMoveNode: (node: GrTreeNodeTarget<T>, referenceNode: GrTreeNodeTarget<T>, dropType: GrTreeNodeDropType) => boolean;
88
+ moveNode: (node: GrTreeNodeTarget<T>, referenceNode: GrTreeNodeTarget<T>, dropType: GrTreeNodeDropType) => GrTreeNode<T> | undefined;
89
+ appendNode: (data: T, parent: GrTreeNodeTarget<T>) => GrTreeNode<T> | undefined;
90
+ removeNode: (node: GrTreeNodeTarget<T>) => boolean;
91
+ insertNodeBefore: (data: T, referenceNode: GrTreeNodeTarget<T>) => GrTreeNode<T> | undefined;
92
+ insertNodeAfter: (data: T, referenceNode: GrTreeNodeTarget<T>) => GrTreeNode<T> | undefined;
93
+ getCheckState: (key: GrTreeKey) => GrTreeCheckState;
94
+ setChecked: (node: GrTreeNodeTarget<T>, checked: boolean) => GrTreeNode<T> | undefined;
95
+ toggleChecked: (node: GrTreeNode<T>) => GrTreeNode<T> | undefined;
96
+ getCheckedKeys: (options?: {
97
+ leafOnly?: boolean;
98
+ }) => GrTreeKey[];
99
+ setCheckedKeys: (keys: GrTreeKey[]) => void;
100
+ getHalfCheckedKeys: () => GrTreeKey[];
101
+ /** Лист ли узел с точки зрения раскрытия: в ленивом режиме решают данные и факт загрузки. */
102
+ isLeafNode: (node: GrTreeNode<T>) => boolean;
103
+ isLoadingKey: (key: GrTreeKey) => boolean;
104
+ /** Грузит детей ветки, если это нужно и ещё не делалось. */
105
+ ensureLoaded: (node: GrTreeNode<T>) => void;
106
+ };
107
+ export declare function useTree<T extends object>(options: UseTreeOptions<T>): UseTreeReturn<T>;
@@ -70,6 +70,7 @@ export declare const granularityComponentConfigs: {
70
70
  GrRadioGroup: GranularComponentDescriptor<"GrRadioGroup">;
71
71
  GrRating: GranularComponentDescriptor<"GrRating">;
72
72
  GrResponseErrorBanner: GranularComponentDescriptor<"GrResponseErrorBanner">;
73
+ GrScrollSpy: GranularComponentDescriptor<"GrScrollSpy">;
73
74
  GrSegmented: GranularComponentDescriptor<"GrSegmented">;
74
75
  GrSelect: GranularComponentDescriptor<"GrSelect">;
75
76
  GrSidebar: GranularComponentDescriptor<"GrSidebar">;
@@ -89,6 +90,7 @@ export declare const granularityComponentConfigs: {
89
90
  GrTooltip: GranularComponentDescriptor<"GrTooltip">;
90
91
  GrTransfer: GranularComponentDescriptor<"GrTransfer">;
91
92
  GrTree: GranularComponentDescriptor<"GrTree">;
93
+ GrTreeSections: GranularComponentDescriptor<"GrTreeSections">;
92
94
  GrTreeSelect: GranularComponentDescriptor<"GrTreeSelect">;
93
95
  GrValue: GranularComponentDescriptor<"GrValue">;
94
96
  };
@@ -176,6 +176,9 @@ export declare const en: {
176
176
  navbar: {
177
177
  openMenu: string;
178
178
  };
179
+ scrollSpy: {
180
+ label: string;
181
+ };
179
182
  responseError: {
180
183
  networkTitle: string;
181
184
  networkMessage: string;
@@ -566,6 +569,9 @@ export declare const en: {
566
569
  navbar: {
567
570
  openMenu: string;
568
571
  };
572
+ scrollSpy: {
573
+ label: string;
574
+ };
569
575
  responseError: {
570
576
  networkTitle: string;
571
577
  networkMessage: string;
@@ -170,6 +170,9 @@ export declare const es: {
170
170
  navbar: {
171
171
  openMenu: string;
172
172
  };
173
+ scrollSpy: {
174
+ label: string;
175
+ };
173
176
  responseError: {
174
177
  networkTitle: string;
175
178
  networkMessage: string;
@@ -562,6 +565,9 @@ export declare const es: {
562
565
  navbar: {
563
566
  openMenu: string;
564
567
  };
568
+ scrollSpy: {
569
+ label: string;
570
+ };
565
571
  responseError: {
566
572
  networkTitle: string;
567
573
  networkMessage: string;
@@ -171,6 +171,9 @@ export declare const ru: {
171
171
  navbar: {
172
172
  openMenu: string;
173
173
  };
174
+ scrollSpy: {
175
+ label: string;
176
+ };
174
177
  responseError: {
175
178
  networkTitle: string;
176
179
  networkMessage: string;
@@ -565,6 +568,9 @@ export declare const ru: {
565
568
  navbar: {
566
569
  openMenu: string;
567
570
  };
571
+ scrollSpy: {
572
+ label: string;
573
+ };
568
574
  responseError: {
569
575
  networkTitle: string;
570
576
  networkMessage: string;
@@ -57,6 +57,7 @@ export * from './components/GrRadio';
57
57
  export * from './components/GrRadioGroup';
58
58
  export * from './components/GrRating';
59
59
  export * from './components/GrResponseErrorBanner';
60
+ export * from './components/GrScrollSpy';
60
61
  export * from './components/GrSegmented';
61
62
  export * from './components/GrSelect';
62
63
  export * from './components/GrSidebar';
@@ -76,6 +77,7 @@ export * from './components/GrToaster';
76
77
  export * from './components/GrTooltip';
77
78
  export * from './components/GrTransfer';
78
79
  export * from './components/GrTree';
80
+ export * from './components/GrTreeSections';
79
81
  export * from './components/GrTreeSelect';
80
82
  export * from './components/GrValue';
81
83
  export { useDismissible } from './composables/useDismissible';
@@ -86,6 +88,10 @@ export { usePortalTarget } from './composables/usePortalTarget';
86
88
  export type { PortalTarget } from './composables/usePortalTarget';
87
89
  export { useOverlayLayer } from './composables/useOverlayLayer';
88
90
  export type { OverlayLayerHandle, UseOverlayLayerOptions } from './composables/useOverlayLayer';
91
+ export { useTree } from './composables/useTree';
92
+ export type { GrTreeFilterInfo, GrTreeModel, UseTreeOptions, UseTreeReturn, } from './composables/useTree';
93
+ export { useScrollSpy } from './composables/useScrollSpy';
94
+ export type { UseScrollSpyOptions, UseScrollSpyReturn } from './composables/useScrollSpy';
89
95
  export { useRovingFocus } from './composables/useRovingFocus';
90
96
  export type { GrRovingEdge, GrRovingOrientation, UseRovingFocusOptions, UseRovingFocusReturn, } from './composables/useRovingFocus';
91
97
  export * from './composables/useGrComponentConfig';