@feugene/granularity 0.47.0 → 0.49.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/{config-2vrOFn2f.js → config-AKpLyIGD.js} +2 -2
- package/dist/chunks/{config-2vrOFn2f.js.map → config-AKpLyIGD.js.map} +1 -1
- package/dist/chunks/config-BBtBQE3s.js +108 -0
- package/dist/chunks/config-BBtBQE3s.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-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-BscVxZR3.js → config-DF1ezU6y.js} +1 -1
- package/dist/chunks/{config-BscVxZR3.js.map → config-DF1ezU6y.js.map} +1 -1
- package/dist/chunks/config-MUkhktTP.js +267 -0
- package/dist/chunks/config-MUkhktTP.js.map +1 -0
- package/dist/chunks/{en-DjTnfTqM.js → en-CsQUoBS2.js} +14 -2
- package/dist/chunks/en-CsQUoBS2.js.map +1 -0
- package/dist/chunks/{es-Bc_t3FI8.js → es-9nbkPvdA.js} +14 -2
- package/dist/chunks/es-9nbkPvdA.js.map +1 -0
- package/dist/chunks/{es-DIFzSXSZ.js → es-DrUz5J6I.js} +3 -3
- package/dist/chunks/{es-DIFzSXSZ.js.map → es-DrUz5J6I.js.map} +1 -1
- package/dist/chunks/{generated-CQ4h6Ieq.js → generated-CxvC5O0V.js} +140 -0
- package/dist/chunks/{generated-CQ4h6Ieq.js.map → generated-CxvC5O0V.js.map} +1 -1
- package/dist/chunks/{grBadgeStyles-DV0DrAew.js → grBadgeStyles-D51AXbj5.js} +57 -1
- package/dist/chunks/grBadgeStyles-D51AXbj5.js.map +1 -0
- package/dist/chunks/{grChipStyles-DcDyxAL0.js → grChipStyles-CA9Wj1_E.js} +1 -1
- package/dist/chunks/{grChipStyles-DcDyxAL0.js.map → grChipStyles-CA9Wj1_E.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-AKukmYva.js → granular-provider-B6xomapW.js} +8 -6
- package/dist/chunks/granular-provider-B6xomapW.js.map +1 -0
- package/dist/chunks/{ru-Bb-co59W.js → ru-88i1WG0b.js} +14 -2
- package/dist/chunks/ru-88i1WG0b.js.map +1 -0
- package/dist/chunks/{safelist-x8USecK8.js → safelist-CSfynUC1.js} +5 -1
- package/dist/chunks/safelist-CSfynUC1.js.map +1 -0
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-C-uovdv8.js → GrAutocomplete-Chhw65pI.js} +2 -2
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-C-uovdv8.js.map → GrAutocomplete-Chhw65pI.js.map} +1 -1
- package/dist/components/GrAutocomplete/index.js +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/GrBadge/chunks/GrBadge-C42KLyUD.js +71 -0
- package/dist/components/GrBadge/chunks/GrBadge-C42KLyUD.js.map +1 -0
- package/dist/components/GrBadge/index.js +3 -3
- package/dist/components/GrBadge/styles.css +1 -1
- package/dist/components/GrChip/chunks/{GrChip-CKqyzYcv.js → GrChip-DoyS1Dr4.js} +1 -1
- package/dist/components/GrChip/chunks/{GrChip-CKqyzYcv.js.map → GrChip-DoyS1Dr4.js.map} +1 -1
- package/dist/components/GrChip/index.js +2 -2
- package/dist/components/GrDataTable/chunks/{GrDataTable-Dp9Fp_P5.js → GrDataTable-DQxYYgQk.js} +438 -160
- 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/GrInputTag/chunks/{GrInputTag-CO0YU-ok.js → GrInputTag-qnRdAZnn.js} +2 -2
- package/dist/components/GrInputTag/chunks/{GrInputTag-CO0YU-ok.js.map → GrInputTag-qnRdAZnn.js.map} +1 -1
- package/dist/components/GrInputTag/index.js +1 -1
- package/dist/components/GrOtpInput/chunks/GrOtpInput-B_Q-RDLw.js +419 -0
- package/dist/components/GrOtpInput/chunks/GrOtpInput-B_Q-RDLw.js.map +1 -0
- package/dist/components/GrOtpInput/index.js +3 -0
- package/dist/components/GrOtpInput/styles.css +1 -0
- package/dist/components/GrPagination/chunks/{GrPagination-BbaF5eXk.js → GrPagination-CMrLPzvL.js} +1 -1
- package/dist/components/GrPagination/chunks/{GrPagination-BbaF5eXk.js.map → GrPagination-CMrLPzvL.js.map} +1 -1
- package/dist/components/GrPagination/index.js +1 -1
- package/dist/components/GrSelect/chunks/{GrSelect-0iI4wdR_.js → GrSelect-DvSq-nV-.js} +2 -2
- package/dist/components/GrSelect/chunks/{GrSelect-0iI4wdR_.js.map → GrSelect-DvSq-nV-.js.map} +1 -1
- package/dist/components/GrSelect/index.js +1 -1
- package/dist/components/GrSwitch/chunks/{GrSwitch-CriHWT2A.js → GrSwitch-D7X42uIA.js} +61 -7
- package/dist/components/GrSwitch/chunks/GrSwitch-D7X42uIA.js.map +1 -0
- package/dist/components/GrSwitch/index.js +2 -2
- 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/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 +20 -19
- package/dist/theme.js +1 -1
- package/dist/tokens.js +1 -1
- 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/GrBadge/GrBadge.vue.d.ts +15 -1
- package/dist/types/components/GrBadge/grBadgeStyles.d.ts +57 -0
- package/dist/types/components/GrBadge/index.d.ts +1 -1
- package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +59 -0
- package/dist/types/components/GrDataTable/composables/useDataTableExpansion.d.ts +46 -0
- package/dist/types/components/GrDataTable/grDataTableStyles.d.ts +23 -0
- package/dist/types/components/GrOtpInput/GrOtpInput.vue.d.ts +164 -0
- package/dist/types/components/GrOtpInput/config.d.ts +1 -0
- package/dist/types/components/GrOtpInput/defaults.d.ts +15 -0
- package/dist/types/components/GrOtpInput/grOtpInputStyles.d.ts +62 -0
- package/dist/types/components/GrOtpInput/index.d.ts +9 -0
- package/dist/types/components/GrOtpInput/otpValue.d.ts +71 -0
- package/dist/types/components/GrOtpInput/safelist.d.ts +7 -0
- package/dist/types/components/GrSwitch/GrSwitch.vue.d.ts +42 -4
- package/dist/types/components/GrSwitch/defaults.d.ts +2 -0
- package/dist/types/components/GrSwitch/grSwitchStyles.d.ts +129 -25
- package/dist/types/components/GrSwitch/index.d.ts +1 -1
- package/dist/types/components/GrSwitch/safelist.d.ts +4 -3
- package/dist/types/components/GrTable/grTableStyles.d.ts +16 -3
- package/dist/types/granular-provider/shared.d.ts +1 -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/types/index.d.ts +1 -0
- package/dist/web-types.json +329 -8
- package/package.json +5 -1
- package/dist/chunks/config-B3J0alyY.js.map +0 -1
- package/dist/chunks/config-Yy67uWHY.js +0 -140
- package/dist/chunks/config-Yy67uWHY.js.map +0 -1
- package/dist/chunks/en-DjTnfTqM.js.map +0 -1
- package/dist/chunks/es-Bc_t3FI8.js.map +0 -1
- package/dist/chunks/grBadgeStyles-DV0DrAew.js.map +0 -1
- package/dist/chunks/grTableStyles-uuMPSOBR.js.map +0 -1
- package/dist/chunks/granular-provider-AKukmYva.js.map +0 -1
- package/dist/chunks/ru-Bb-co59W.js.map +0 -1
- package/dist/chunks/safelist-x8USecK8.js.map +0 -1
- package/dist/components/GrAvatar/chunks/GrAvatar-dWEXiCJG.js.map +0 -1
- package/dist/components/GrBadge/chunks/GrBadge-DBeQXEir.js +0 -47
- package/dist/components/GrBadge/chunks/GrBadge-DBeQXEir.js.map +0 -1
- package/dist/components/GrDataTable/chunks/GrDataTable-Dp9Fp_P5.js.map +0 -1
- package/dist/components/GrSwitch/chunks/GrSwitch-CriHWT2A.js.map +0 -1
|
@@ -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,10 +1,21 @@
|
|
|
1
1
|
export type { GrBadgeRadius, GrBadgeSize, GrBadgeTone } from './grBadgeStyles';
|
|
2
|
-
import { type GrBadgeRadius, type GrBadgeSize, type GrBadgeTone } from './grBadgeStyles';
|
|
2
|
+
import { type GrBadgeDotTone, type GrBadgeRadius, type GrBadgeSize, type GrBadgeTone } from './grBadgeStyles';
|
|
3
3
|
export interface GrBadgeProps {
|
|
4
4
|
tone?: GrBadgeTone;
|
|
5
5
|
dark?: boolean;
|
|
6
6
|
size?: GrBadgeSize;
|
|
7
7
|
radius?: GrBadgeRadius;
|
|
8
|
+
/**
|
|
9
|
+
* Точка-маркер перед подписью: «● Активен».
|
|
10
|
+
*
|
|
11
|
+
* Имя тона красит маркер отдельно от плашки — ради пары «тихая плашка +
|
|
12
|
+
* цветной маркер», из-за которой паттерн и существует. `true` берёт тон
|
|
13
|
+
* самого бейджа.
|
|
14
|
+
*
|
|
15
|
+
* На заливке (`dark`) маркер всегда цвета текста: тон там слился бы с
|
|
16
|
+
* подложкой, взятой из того же слоя.
|
|
17
|
+
*/
|
|
18
|
+
dot?: GrBadgeDotTone | boolean;
|
|
8
19
|
}
|
|
9
20
|
type __VLS_Slots = {
|
|
10
21
|
/** Содержимое метки. */
|
|
@@ -26,16 +37,19 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
26
37
|
dark: boolean;
|
|
27
38
|
size: undefined;
|
|
28
39
|
radius: undefined;
|
|
40
|
+
dot: boolean;
|
|
29
41
|
}>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<GrBadgeProps>, {
|
|
30
42
|
tone: undefined;
|
|
31
43
|
dark: boolean;
|
|
32
44
|
size: undefined;
|
|
33
45
|
radius: undefined;
|
|
46
|
+
dot: boolean;
|
|
34
47
|
}>>> & Readonly<{}>, {
|
|
35
48
|
tone: GrBadgeTone;
|
|
36
49
|
size: GrBadgeSize;
|
|
37
50
|
radius: GrBadgeRadius;
|
|
38
51
|
dark: boolean;
|
|
52
|
+
dot: GrBadgeDotTone | boolean;
|
|
39
53
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
40
54
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
41
55
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import type { GrComponentSize } from '../shared/sizes';
|
|
2
2
|
import type { GrTone } from '../shared/tones';
|
|
3
3
|
export type GrBadgeTone = GrTone;
|
|
4
|
+
/**
|
|
5
|
+
* Тон маркера — отдельным литеральным перечислением, а не `GrTone`.
|
|
6
|
+
*
|
|
7
|
+
* Компилятор SFC выводит рантайм-типы пропов из TypeScript, но `GrTone` это
|
|
8
|
+
* `typeof GR_TONES[number]`, и развернуть его в конструкторы он не умеет. У
|
|
9
|
+
* `dot?: GrTone | boolean` из объединения выживал один `Boolean`, и строковый
|
|
10
|
+
* тон отбраковывался предупреждением Vue у каждого потребителя — при том, что
|
|
11
|
+
* компонент работал. Литеральное объединение разрешается и даёт
|
|
12
|
+
* `type: [Boolean, String]`; так же написан `showTooltip` у `GrSlider`.
|
|
13
|
+
*
|
|
14
|
+
* От расхождения с `GR_TONES` держит `assertDotToneCoversTones` ниже: списки
|
|
15
|
+
* обязаны совпадать в обе стороны, иначе `vue-tsc` роняет сборку.
|
|
16
|
+
*/
|
|
17
|
+
export type GrBadgeDotTone = 'primary' | 'neutral' | 'success' | 'warning' | 'danger' | 'info' | 'slate' | 'azure';
|
|
18
|
+
type AssertMutual<A, B> = [A] extends [B] ? ([B] extends [A] ? true : never) : never;
|
|
19
|
+
export declare const assertDotToneCoversTones: AssertMutual<GrBadgeDotTone, GrTone>;
|
|
4
20
|
export type GrBadgeSize = GrComponentSize;
|
|
5
21
|
export type GrBadgeRadius = 'square' | 'semi' | 'round';
|
|
6
22
|
export declare const sizeClassBySize: Record<GrBadgeSize, string>;
|
|
@@ -42,3 +58,44 @@ export declare function grBadgeClass(options: {
|
|
|
42
58
|
size: GrBadgeSize;
|
|
43
59
|
radius: GrBadgeRadius;
|
|
44
60
|
}): string;
|
|
61
|
+
/**
|
|
62
|
+
* Точка-маркер перед подписью.
|
|
63
|
+
*
|
|
64
|
+
* Кружок мельче иконки и растёт медленнее: маркер обязан оставаться маркером,
|
|
65
|
+
* а не превращаться в третий элемент строки. Повтор значений на концах шкалы —
|
|
66
|
+
* тот же приём, что у `badgeIconSizeClassBySize`.
|
|
67
|
+
*/
|
|
68
|
+
export declare const badgeDotSizeClassBySize: Record<GrBadgeSize, string>;
|
|
69
|
+
/** Маркер не жмётся: подпись бейджа не переносится, сжиматься нечему. */
|
|
70
|
+
export declare const badgeDotClass = "shrink-0 rounded-[var(--gr-radius-full)]";
|
|
71
|
+
/**
|
|
72
|
+
* Маркер на мягкой подложке красится **тем же покомпонентным слоем**, что и
|
|
73
|
+
* заливка filled-бейджа, и это не экономия на токенах.
|
|
74
|
+
*
|
|
75
|
+
* Роль тона напрямую здесь не работает ни в одном виде, и обе ветки измерены:
|
|
76
|
+
* `--gr-{tone}` в светлой теме — яркая заливка под тёмный текст, как маркер она
|
|
77
|
+
* не берёт 3:1 **ни на одной** подложке (`success` 2.06–2.32, `warning`
|
|
78
|
+
* 2.27–2.56); `--gr-{tone}-solid` берёт светлую тему и заваливает тёмную
|
|
79
|
+
* (до 1.37). Слой `--gr-badge-{tone}-bg` как раз и означает «насыщенный вес,
|
|
80
|
+
* который читается в этой теме»: `-solid` в светлой, роль тона в тёмной.
|
|
81
|
+
*
|
|
82
|
+
* На нём проходят все 128 пар «тон маркера × тон бейджа × тема», включая
|
|
83
|
+
* одноимённую, — поэтому булев `dot` берёт тон самого бейджа, а не отдельный
|
|
84
|
+
* цвет. Гейт — `__tests__/grBadgeContrast.test.ts`.
|
|
85
|
+
*/
|
|
86
|
+
export declare const badgeDotToneClass: Record<GrBadgeTone, string>;
|
|
87
|
+
/**
|
|
88
|
+
* Маркер на **заливке** — цветом текста бейджа.
|
|
89
|
+
*
|
|
90
|
+
* Тон здесь не годится по построению: подложка filled-бейджа сама берётся из
|
|
91
|
+
* `--gr-badge-{tone}-bg`, и маркер того же тона слился бы с ней в один цвет.
|
|
92
|
+
* `currentColor` равен тексту бейджа, а он поверен на AA 4.5:1 — то есть
|
|
93
|
+
* заведомо проходит порог для графики.
|
|
94
|
+
*/
|
|
95
|
+
export declare const badgeDotCurrentColorClass = "bg-[currentColor]";
|
|
96
|
+
export declare function badgeDotClassFor(options: {
|
|
97
|
+
tone: GrBadgeTone;
|
|
98
|
+
dark: boolean;
|
|
99
|
+
size: GrBadgeSize;
|
|
100
|
+
}): string;
|
|
101
|
+
export {};
|
|
@@ -2,6 +2,6 @@ export { default } from './GrBadge.vue';
|
|
|
2
2
|
export { default as GrBadge } from './GrBadge.vue';
|
|
3
3
|
export { grBadgeConfig } from './config';
|
|
4
4
|
export type { GrBadgeConfigurableProps } from './defaults';
|
|
5
|
-
export type { GrBadgeRadius, GrBadgeSize, GrBadgeTone } from './grBadgeStyles';
|
|
5
|
+
export type { GrBadgeDotTone, GrBadgeRadius, GrBadgeSize, GrBadgeTone } from './grBadgeStyles';
|
|
6
6
|
export { grBadgeSafelist } from './safelist';
|
|
7
7
|
export type { GrBadgeProps } from './GrBadge.vue';
|
|
@@ -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,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>;
|
|
@@ -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)]";
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { type GrOtpInputSize } from './grOtpInputStyles';
|
|
2
|
+
import { type GrOtpInputType } from './otpValue';
|
|
3
|
+
export type { GrOtpInputSize } from './grOtpInputStyles';
|
|
4
|
+
export type { GrOtpInputType } from './otpValue';
|
|
5
|
+
export interface GrOtpInputProps {
|
|
6
|
+
/** Код целиком, без разделителей. */
|
|
7
|
+
modelValue?: string;
|
|
8
|
+
/** Число ячеек. */
|
|
9
|
+
length?: number;
|
|
10
|
+
/** Допустимый алфавит и раскладка мобильной клавиатуры. */
|
|
11
|
+
type?: GrOtpInputType;
|
|
12
|
+
/** Свой алфавит регуляркой на **один символ**. Перекрывает `type`. */
|
|
13
|
+
pattern?: string;
|
|
14
|
+
/** Разбивка на группы: `[3, 3]` рисует `123 – 456`. Сумма обязана равняться `length`. */
|
|
15
|
+
groups?: number[];
|
|
16
|
+
/** Точки вместо символов — сценарий PIN. На `modelValue` не влияет. */
|
|
17
|
+
masked?: boolean;
|
|
18
|
+
/** Знак в пустой ячейке. */
|
|
19
|
+
placeholder?: string;
|
|
20
|
+
size?: GrOtpInputSize;
|
|
21
|
+
autofocus?: boolean;
|
|
22
|
+
/** `autocomplete="one-time-code"`: код из SMS подставляется на iOS и macOS. */
|
|
23
|
+
oneTimeCode?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Приём кода из SMS на Android через WebOTP. Выключен: требует HTTPS и
|
|
26
|
+
* особого хвоста в тексте сообщения, который добавляет бэкенд.
|
|
27
|
+
*/
|
|
28
|
+
webOtp?: boolean;
|
|
29
|
+
/** Имя поля для нативной отправки формы. */
|
|
30
|
+
name?: string;
|
|
31
|
+
/** `id` формы, если поле лежит вне неё. */
|
|
32
|
+
form?: string;
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
readonly?: boolean;
|
|
35
|
+
invalid?: boolean;
|
|
36
|
+
required?: boolean;
|
|
37
|
+
ariaLabel?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface GrOtpInputEmits {
|
|
40
|
+
(e: 'update:modelValue', value: string): void;
|
|
41
|
+
(e: 'change', value: string): void;
|
|
42
|
+
(e: 'focus', event: FocusEvent): void;
|
|
43
|
+
(e: 'blur', event: FocusEvent): void;
|
|
44
|
+
/** Код набран целиком. Точка автосабмита. */
|
|
45
|
+
(e: 'complete', value: string): void;
|
|
46
|
+
}
|
|
47
|
+
type __VLS_Slots = {
|
|
48
|
+
/** Своё оформление ячейки. Размер и рамку по-прежнему держит компонент. */
|
|
49
|
+
cell?: (props: {
|
|
50
|
+
char: string;
|
|
51
|
+
index: number;
|
|
52
|
+
active: boolean;
|
|
53
|
+
filled: boolean;
|
|
54
|
+
masked: boolean;
|
|
55
|
+
}) => any;
|
|
56
|
+
/** Знак между группами. По умолчанию — тире. */
|
|
57
|
+
separator?: (props: {
|
|
58
|
+
index: number;
|
|
59
|
+
}) => any;
|
|
60
|
+
};
|
|
61
|
+
declare function focus(): void;
|
|
62
|
+
declare function blur(): void;
|
|
63
|
+
/** Штатный сценарий: сервер отверг код, поле чистится и снова ждёт ввода. */
|
|
64
|
+
declare function clear(): void;
|
|
65
|
+
declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<GrOtpInputProps>, {
|
|
66
|
+
modelValue: string;
|
|
67
|
+
length: undefined;
|
|
68
|
+
type: string;
|
|
69
|
+
pattern: undefined;
|
|
70
|
+
groups: undefined;
|
|
71
|
+
masked: undefined;
|
|
72
|
+
placeholder: string;
|
|
73
|
+
size: undefined;
|
|
74
|
+
autofocus: boolean;
|
|
75
|
+
oneTimeCode: boolean;
|
|
76
|
+
webOtp: boolean;
|
|
77
|
+
name: undefined;
|
|
78
|
+
form: undefined;
|
|
79
|
+
disabled: boolean;
|
|
80
|
+
readonly: boolean;
|
|
81
|
+
invalid: boolean;
|
|
82
|
+
required: boolean;
|
|
83
|
+
ariaLabel: undefined;
|
|
84
|
+
}>>, {
|
|
85
|
+
focus: typeof focus;
|
|
86
|
+
blur: typeof blur;
|
|
87
|
+
clear: typeof clear;
|
|
88
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
89
|
+
"update:modelValue": (value: string) => void;
|
|
90
|
+
change: (value: string) => void;
|
|
91
|
+
focus: (event: FocusEvent) => void;
|
|
92
|
+
blur: (event: FocusEvent) => void;
|
|
93
|
+
complete: (value: string) => void;
|
|
94
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<GrOtpInputProps>, {
|
|
95
|
+
modelValue: string;
|
|
96
|
+
length: undefined;
|
|
97
|
+
type: string;
|
|
98
|
+
pattern: undefined;
|
|
99
|
+
groups: undefined;
|
|
100
|
+
masked: undefined;
|
|
101
|
+
placeholder: string;
|
|
102
|
+
size: undefined;
|
|
103
|
+
autofocus: boolean;
|
|
104
|
+
oneTimeCode: boolean;
|
|
105
|
+
webOtp: boolean;
|
|
106
|
+
name: undefined;
|
|
107
|
+
form: undefined;
|
|
108
|
+
disabled: boolean;
|
|
109
|
+
readonly: boolean;
|
|
110
|
+
invalid: boolean;
|
|
111
|
+
required: boolean;
|
|
112
|
+
ariaLabel: undefined;
|
|
113
|
+
}>>> & Readonly<{
|
|
114
|
+
onBlur?: ((event: FocusEvent) => any) | undefined;
|
|
115
|
+
onChange?: ((value: string) => any) | undefined;
|
|
116
|
+
onFocus?: ((event: FocusEvent) => any) | undefined;
|
|
117
|
+
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
118
|
+
onComplete?: ((value: string) => any) | undefined;
|
|
119
|
+
}>, {
|
|
120
|
+
length: number;
|
|
121
|
+
disabled: boolean;
|
|
122
|
+
readonly: boolean;
|
|
123
|
+
form: string;
|
|
124
|
+
pattern: string;
|
|
125
|
+
type: GrOtpInputType;
|
|
126
|
+
size: GrOtpInputSize;
|
|
127
|
+
masked: boolean;
|
|
128
|
+
name: string;
|
|
129
|
+
invalid: boolean;
|
|
130
|
+
ariaLabel: string;
|
|
131
|
+
modelValue: string;
|
|
132
|
+
required: boolean;
|
|
133
|
+
placeholder: string;
|
|
134
|
+
groups: number[];
|
|
135
|
+
autofocus: boolean;
|
|
136
|
+
oneTimeCode: boolean;
|
|
137
|
+
webOtp: boolean;
|
|
138
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
139
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
140
|
+
declare const _default: typeof __VLS_export;
|
|
141
|
+
export default _default;
|
|
142
|
+
type __VLS_TypePropsToOption<T> = {
|
|
143
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
144
|
+
type: import('vue').PropType<Required<T>[K]>;
|
|
145
|
+
} : {
|
|
146
|
+
type: import('vue').PropType<T[K]>;
|
|
147
|
+
required: true;
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
type __VLS_WithDefaults<P, D> = {
|
|
151
|
+
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_PrettifyLocal<P[K] & {
|
|
152
|
+
default: D[K];
|
|
153
|
+
}> : P[K];
|
|
154
|
+
};
|
|
155
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
156
|
+
new (): {
|
|
157
|
+
$slots: S;
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
type __VLS_PrettifyLocal<T> = (T extends any ? {
|
|
161
|
+
[K in keyof T]: T[K];
|
|
162
|
+
} : {
|
|
163
|
+
[K in keyof T as K]: T[K];
|
|
164
|
+
}) & {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const grOtpInputConfig: import("@feugene/unocss-preset-granular/contract").GranularComponentDescriptor<"GrOtpInput">;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { GrComponentSize } from '../GrConfigProvider/context';
|
|
2
|
+
/**
|
|
3
|
+
* Пропы `GrOtpInput`, настраиваемые глобально через `componentDefaults`.
|
|
4
|
+
* Только оформление и поведение по умолчанию — см. `GrButton/defaults.ts`.
|
|
5
|
+
*/
|
|
6
|
+
export interface GrOtpInputConfigurableProps {
|
|
7
|
+
size: GrComponentSize;
|
|
8
|
+
length: number;
|
|
9
|
+
masked: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare module '../../composables/useGrComponentConfig' {
|
|
12
|
+
interface GrComponentDefaultsRegistry {
|
|
13
|
+
GrOtpInput: GrOtpInputConfigurableProps;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { GrComponentSize } from '../shared/sizes';
|
|
2
|
+
export type GrOtpInputSize = GrComponentSize;
|
|
3
|
+
/**
|
|
4
|
+
* `w-fit` тут не украшение. Гридовый или флексовый родитель **блокифицирует**
|
|
5
|
+
* `inline-flex`, и ряд растягивался на всю колонку: сами ячейки оставались на
|
|
6
|
+
* месте, а невидимое поле поверх них ловило клики далеко справа от кода.
|
|
7
|
+
*/
|
|
8
|
+
export declare const rootBaseClass = "relative inline-flex w-fit items-center";
|
|
9
|
+
export declare const rootGaps: Record<GrOtpInputSize, string>;
|
|
10
|
+
/**
|
|
11
|
+
* Настоящее поле лежит **поверх** ряда ячеек и невидимо: текст, каретка и
|
|
12
|
+
* подсветка выделения прозрачны, всё видимое рисуют ячейки.
|
|
13
|
+
*
|
|
14
|
+
* Оно остаётся полноценным `<input>`, и потому даром достаются вставка,
|
|
15
|
+
* автозаполнение кода из SMS, отмена, выделение и вся каретка со стрелками —
|
|
16
|
+
* см. `docs/components/GrOtpInput.md`.
|
|
17
|
+
*
|
|
18
|
+
* `z-index` не нужен: поле позиционировано, ячейки — нет, а позиционированный
|
|
19
|
+
* элемент и так красится поверх статичных соседей. Литерал слоя тут был бы
|
|
20
|
+
* лишней записью в шкале `docs/z-index.md`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const fieldClass = "absolute inset-0 w-full cursor-text bg-transparent text-transparent [caret-color:transparent] outline-none selection:bg-transparent disabled:cursor-not-allowed";
|
|
23
|
+
export declare const cellBaseClass = "relative inline-flex shrink-0 items-center justify-center rounded-[var(--gr-radius-control)] border [font-variant-numeric:tabular-nums] transition-colors duration-[var(--gr-duration-fast)]";
|
|
24
|
+
/**
|
|
25
|
+
* Сторона ячейки повторяет высоту `GrInput` на той же ступени: код стоит в
|
|
26
|
+
* форме рядом с полями, и ряд обязан садиться с ними в одну линию.
|
|
27
|
+
*
|
|
28
|
+
* Через хук, а не классом-числом: квадратная ячейка — решение оформления, и
|
|
29
|
+
* макет вправе сделать её шире.
|
|
30
|
+
*/
|
|
31
|
+
export declare const cellSizes: Record<GrOtpInputSize, string>;
|
|
32
|
+
export declare const cellIdleClass = "border-[var(--gr-brd)] bg-[var(--gr-bg)] text-[var(--gr-fg)]";
|
|
33
|
+
/** Активная ячейка — та, в которой стоит каретка, и только пока поле в фокусе. */
|
|
34
|
+
export declare const cellActiveClass = "border-[var(--gr-otp-input-active-brd,var(--gr-primary))] ring-2 ring-[var(--gr-ring)]";
|
|
35
|
+
/**
|
|
36
|
+
* Вердикт валидации красится своей ролью, а не декоративным `danger`: тема
|
|
37
|
+
* вправе развести подсветку по решению разработчика и ошибку формы.
|
|
38
|
+
*/
|
|
39
|
+
export declare const cellInvalidClass = "border-[var(--gr-invalid-brd)] bg-[var(--gr-bg)] text-[var(--gr-fg)]";
|
|
40
|
+
export declare const cellInvalidActiveClass = "ring-2 ring-[var(--gr-invalid-ring)]";
|
|
41
|
+
/**
|
|
42
|
+
* Недоступность гасится фоном, а не `opacity`: прозрачность разбавляет
|
|
43
|
+
* выверенные на AA токены текста и роняет контраст кода.
|
|
44
|
+
*/
|
|
45
|
+
export declare const cellDisabledClass = "border-[var(--gr-disabled-brd)] bg-[var(--gr-disabled-bg)] text-[var(--gr-disabled-fg)]";
|
|
46
|
+
export declare const placeholderClass = "text-[var(--gr-muted-fg)]";
|
|
47
|
+
/**
|
|
48
|
+
* Каретка рисуется своей, потому что настоящая скрыта вместе с текстом.
|
|
49
|
+
* Мигание — CSS-анимация, значит подчиняется глобальному клампу движения
|
|
50
|
+
* пакета (`docs/motion.md`), а не собственному таймеру.
|
|
51
|
+
*/
|
|
52
|
+
export declare const caretClass = "pointer-events-none absolute h-[1em] w-px bg-[var(--gr-otp-input-caret,var(--gr-primary))]";
|
|
53
|
+
export declare const separatorClass = "select-none px-0.5 text-[var(--gr-muted-fg)]";
|
|
54
|
+
export declare function grOtpInputRootClass(size: GrOtpInputSize): string;
|
|
55
|
+
type GrOtpInputCellClassOptions = {
|
|
56
|
+
size: GrOtpInputSize;
|
|
57
|
+
active: boolean;
|
|
58
|
+
invalid: boolean;
|
|
59
|
+
disabled: boolean;
|
|
60
|
+
};
|
|
61
|
+
export declare function grOtpInputCellClass(options: GrOtpInputCellClassOptions): string;
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ComponentExposed } from '../shared/instance';
|
|
2
|
+
import type GrOtpInputComponent from './GrOtpInput.vue';
|
|
3
|
+
export { default } from './GrOtpInput.vue';
|
|
4
|
+
export { default as GrOtpInput } from './GrOtpInput.vue';
|
|
5
|
+
export { grOtpInputConfig } from './config';
|
|
6
|
+
export type { GrOtpInputConfigurableProps } from './defaults';
|
|
7
|
+
export { grOtpInputSafelist } from './safelist';
|
|
8
|
+
export type { GrOtpInputEmits, GrOtpInputProps, GrOtpInputSize, GrOtpInputType } from './GrOtpInput.vue';
|
|
9
|
+
export type GrOtpInputInstance = ComponentExposed<typeof GrOtpInputComponent>;
|