@feugene/granularity 0.28.0 → 0.28.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{config-DONFPTFg.js → config-C0Eu8jpG.js} +4 -1
- package/dist/chunks/config-C0Eu8jpG.js.map +1 -0
- package/dist/chunks/{config-CWthWcWY.js → config-_jbgsFpw.js} +2 -1
- package/dist/chunks/config-_jbgsFpw.js.map +1 -0
- package/dist/chunks/{grDropdownMenuStyles-DG3aYHkT.js → grDropdownMenuStyles-Cf8OdR8S.js} +20 -3
- package/dist/chunks/grDropdownMenuStyles-Cf8OdR8S.js.map +1 -0
- package/dist/chunks/{granular-provider-BhBBIAl7.js → granular-provider-Dds_519x.js} +2 -2
- package/dist/chunks/{granular-provider-BhBBIAl7.js.map → granular-provider-Dds_519x.js.map} +1 -1
- package/dist/components/GrBreadcrumbs/chunks/{GrBreadcrumbs-BYbfo-49.js → GrBreadcrumbs-BKOvl8W1.js} +19 -3
- package/dist/components/GrBreadcrumbs/chunks/GrBreadcrumbs-BKOvl8W1.js.map +1 -0
- package/dist/components/GrBreadcrumbs/index.js +2 -2
- package/dist/components/GrContextMenu/chunks/{GrContextMenu-DDAUvrDK.js → GrContextMenu-BNQDbAsY.js} +1 -1
- package/dist/components/GrContextMenu/chunks/{GrContextMenu-DDAUvrDK.js.map → GrContextMenu-BNQDbAsY.js.map} +1 -1
- package/dist/components/GrContextMenu/index.js +1 -1
- package/dist/components/GrDelta/chunks/{GrDelta-04j9WmEY.js → GrDelta-BZwkgQW-.js} +0 -0
- package/dist/components/GrDelta/chunks/GrDelta-BZwkgQW-.js.map +1 -0
- package/dist/components/GrDelta/index.js +1 -1
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-5zoOL8Oj.js → GrDropdownMenu-Cg7qHV9J.js} +2 -2
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-5zoOL8Oj.js.map → GrDropdownMenu-Cg7qHV9J.js.map} +1 -1
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenuList-CT_1TQJo.js → GrDropdownMenuList-RW5IBvmu.js} +1 -1
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenuList-CT_1TQJo.js.map → GrDropdownMenuList-RW5IBvmu.js.map} +1 -1
- package/dist/components/GrDropdownMenu/index.js +3 -3
- package/dist/directives/clickOutside.js +83 -21
- package/dist/directives/clickOutside.js.map +1 -1
- package/dist/granular-provider-node.js +1 -1
- package/dist/granular-provider.js +1 -1
- package/dist/index.js +7 -7
- package/dist/types/components/GrBreadcrumbs/grBreadcrumbsStyles.d.ts +12 -0
- package/dist/types/components/GrDropdownMenu/grDropdownMenuStyles.d.ts +18 -2
- package/dist/types/internal/granularityFormat.d.ts +2 -2
- package/dist/web-types.json +1 -1
- package/package.json +85 -4
- package/dist/chunks/config-CWthWcWY.js.map +0 -1
- package/dist/chunks/config-DONFPTFg.js.map +0 -1
- package/dist/chunks/grDropdownMenuStyles-DG3aYHkT.js.map +0 -1
- package/dist/components/GrBreadcrumbs/chunks/GrBreadcrumbs-BYbfo-49.js.map +0 -1
- package/dist/components/GrDelta/chunks/GrDelta-04j9WmEY.js.map +0 -1
|
@@ -47,35 +47,98 @@ function resolveExclude(doc, exclude) {
|
|
|
47
47
|
return resolved;
|
|
48
48
|
}
|
|
49
49
|
var states = /* @__PURE__ */ new WeakMap();
|
|
50
|
+
/**
|
|
51
|
+
* Слушатель — один на документ и вид события, а не на элемент.
|
|
52
|
+
*
|
|
53
|
+
* Каждый элемент со своим слушателем — это десяток подписок на документе у
|
|
54
|
+
* страницы с десятком оверлеев, и полное переподключение на каждом обновлении
|
|
55
|
+
* хозяина: хук `updated` срабатывает на любой ререндер, а набор событий при
|
|
56
|
+
* этом обычно тот же. Здесь подписка живёт по счётчику потребителей, а элементы
|
|
57
|
+
* обходятся общим обработчиком.
|
|
58
|
+
*/
|
|
59
|
+
var documentElements = /* @__PURE__ */ new WeakMap();
|
|
60
|
+
var documentSubscriptions = /* @__PURE__ */ new WeakMap();
|
|
61
|
+
function subscriptionKey(type, capture) {
|
|
62
|
+
return `${type}|${capture ? "capture" : "bubble"}`;
|
|
63
|
+
}
|
|
64
|
+
function keysOf(options) {
|
|
65
|
+
if (!options.enabled || !options.handler) return [];
|
|
66
|
+
return options.events.map((type) => subscriptionKey(type, options.capture));
|
|
67
|
+
}
|
|
68
|
+
function dispatch(doc, event, capture) {
|
|
69
|
+
const elements = documentElements.get(doc);
|
|
70
|
+
if (!elements) return;
|
|
71
|
+
for (const el of [...elements]) {
|
|
72
|
+
const state = states.get(el);
|
|
73
|
+
if (!state) continue;
|
|
74
|
+
const { enabled, handler, exclude, events } = state.options;
|
|
75
|
+
if (!enabled || !handler) continue;
|
|
76
|
+
if (state.options.capture !== capture) continue;
|
|
77
|
+
if (!events.includes(event.type)) continue;
|
|
78
|
+
if ("button" in event && typeof event.button === "number" && event.button !== 0) continue;
|
|
79
|
+
if (!el.isConnected) continue;
|
|
80
|
+
if (isEventInside(el, event)) continue;
|
|
81
|
+
if (resolveExclude(state.doc, exclude).some((item) => isEventInside(item, event))) continue;
|
|
82
|
+
handler(event);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function subscribe(doc, key) {
|
|
86
|
+
let subscriptions = documentSubscriptions.get(doc);
|
|
87
|
+
if (!subscriptions) {
|
|
88
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
89
|
+
documentSubscriptions.set(doc, subscriptions);
|
|
90
|
+
}
|
|
91
|
+
const existing = subscriptions.get(key);
|
|
92
|
+
if (existing) {
|
|
93
|
+
existing.count += 1;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const [type, mode] = key.split("|");
|
|
97
|
+
const capture = mode === "capture";
|
|
98
|
+
const listener = (event) => dispatch(doc, event, capture);
|
|
99
|
+
subscriptions.set(key, {
|
|
100
|
+
listener,
|
|
101
|
+
count: 1
|
|
102
|
+
});
|
|
103
|
+
doc.addEventListener(type, listener, capture);
|
|
104
|
+
}
|
|
105
|
+
function unsubscribe(doc, key) {
|
|
106
|
+
const subscriptions = documentSubscriptions.get(doc);
|
|
107
|
+
const existing = subscriptions?.get(key);
|
|
108
|
+
if (!subscriptions || !existing) return;
|
|
109
|
+
existing.count -= 1;
|
|
110
|
+
if (existing.count > 0) return;
|
|
111
|
+
const [type, mode] = key.split("|");
|
|
112
|
+
doc.removeEventListener(type, existing.listener, mode === "capture");
|
|
113
|
+
subscriptions.delete(key);
|
|
114
|
+
}
|
|
50
115
|
function unbind(el) {
|
|
51
116
|
const state = states.get(el);
|
|
52
117
|
if (!state) return;
|
|
53
|
-
for (const
|
|
118
|
+
for (const key of state.keys) unsubscribe(state.doc, key);
|
|
119
|
+
documentElements.get(state.doc)?.delete(el);
|
|
54
120
|
states.delete(el);
|
|
55
121
|
}
|
|
56
122
|
function bind(el, value) {
|
|
57
|
-
const options = normalize(value);
|
|
58
123
|
const doc = el.ownerDocument;
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (!el.isConnected) return;
|
|
66
|
-
if (isEventInside(el, event)) return;
|
|
67
|
-
const excluded = resolveExclude(current.doc, exclude);
|
|
68
|
-
for (const ex of excluded) if (isEventInside(ex, event)) return;
|
|
69
|
-
handler(event);
|
|
70
|
-
};
|
|
71
|
-
const nextState = {
|
|
124
|
+
const previous = states.get(el);
|
|
125
|
+
if (previous && previous.doc !== doc) unbind(el);
|
|
126
|
+
const options = normalize(value);
|
|
127
|
+
const nextKeys = keysOf(options);
|
|
128
|
+
const prevKeys = states.get(el)?.keys ?? [];
|
|
129
|
+
states.set(el, {
|
|
72
130
|
options,
|
|
73
131
|
doc,
|
|
74
|
-
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
if (!
|
|
78
|
-
|
|
132
|
+
keys: nextKeys
|
|
133
|
+
});
|
|
134
|
+
let elements = documentElements.get(doc);
|
|
135
|
+
if (!elements) {
|
|
136
|
+
elements = /* @__PURE__ */ new Set();
|
|
137
|
+
documentElements.set(doc, elements);
|
|
138
|
+
}
|
|
139
|
+
elements.add(el);
|
|
140
|
+
for (const key of nextKeys) if (!prevKeys.includes(key)) subscribe(doc, key);
|
|
141
|
+
for (const key of prevKeys) if (!nextKeys.includes(key)) unsubscribe(doc, key);
|
|
79
142
|
}
|
|
80
143
|
/**
|
|
81
144
|
* `v-click-outside` — обработчик клика вне элемента (например, закрытие дропдауна/модалки).
|
|
@@ -85,7 +148,6 @@ var vClickOutside = {
|
|
|
85
148
|
bind(el, binding.value);
|
|
86
149
|
},
|
|
87
150
|
updated(el, binding) {
|
|
88
|
-
unbind(el);
|
|
89
151
|
bind(el, binding.value);
|
|
90
152
|
},
|
|
91
153
|
unmounted(el) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clickOutside.js","names":[],"sources":["../../src/directives/clickOutside.ts"],"sourcesContent":["import type { Directive } from 'vue'\n\nexport type ClickOutsideHandler = (event: MouseEvent | TouchEvent | PointerEvent) => void\n\nexport type ClickOutsideExclude = HTMLElement | string | (() => HTMLElement | null | undefined)\n\nexport type ClickOutsideBindingValue =\n | ClickOutsideHandler\n | {\n handler: ClickOutsideHandler\n /** По умолчанию `true`. */\n enabled?: boolean\n /** По умолчанию `true` (слушаем в capture, чтобы stopPropagation внутри не ломал закрытие). */\n capture?: boolean\n /** Список событий. По умолчанию `['click']`. */\n events?: Array<'click' | 'mousedown' | 'touchstart' | 'pointerdown'>\n /** Элементы/селекторы, клики по которым считаются \"внутри\". */\n exclude?: ClickOutsideExclude[]\n }\n\ntype NormalizedOptions = {\n enabled: boolean\n capture: boolean\n events: Array<'click' | 'mousedown' | 'touchstart' | 'pointerdown'>\n handler: ClickOutsideHandler | undefined\n exclude: ClickOutsideExclude[]\n}\n\nfunction normalize(value: ClickOutsideBindingValue | undefined): NormalizedOptions {\n if (typeof value === 'function') {\n return { enabled: true, capture: true, events: ['click'], handler: value, exclude: [] }\n }\n\n if (value && typeof value === 'object') {\n return {\n enabled: value.enabled ?? true,\n capture: value.capture ?? true,\n events: value.events?.length ? value.events : ['click'],\n handler: value.handler,\n exclude: value.exclude ?? [],\n }\n }\n\n return { enabled: false, capture: true, events: ['click'], handler: undefined, exclude: [] }\n}\n\nfunction isEventInside(el: HTMLElement, event: Event): boolean {\n const target = event.target as Node | null\n if (!target) return false\n\n const composedPath = (event as any).composedPath?.() as EventTarget[] | undefined\n if (Array.isArray(composedPath)) {\n return composedPath.includes(el)\n }\n\n return el.contains(target)\n}\n\nfunction resolveExclude(doc: Document, exclude: ClickOutsideExclude[]): HTMLElement[] {\n const resolved: HTMLElement[] = []\n\n for (const item of exclude) {\n if (typeof item === 'string') {\n const found = doc.querySelector(item)\n if (found instanceof HTMLElement) resolved.push(found)\n continue\n }\n\n if (typeof item === 'function') {\n const found = item()\n if (found instanceof HTMLElement) resolved.push(found)\n continue\n }\n\n if (item instanceof HTMLElement) {\n resolved.push(item)\n }\n }\n\n return resolved\n}\n\ntype InternalState = {\n options: NormalizedOptions\n doc: Document\n listener: (event: Event) => void\n}\n\nconst states = new WeakMap<HTMLElement, InternalState>()\n\nfunction unbind(el: HTMLElement) {\n const state = states.get(el)\n if (!state) return\n\n for (const event of state.options.events) {\n state.doc.removeEventListener(event, state.listener, state.options.capture)\n }\n\n states.delete(el)\n}\n\nfunction bind(el: HTMLElement, value: ClickOutsideBindingValue | undefined) {\n const options = normalize(value)\n const doc = el.ownerDocument\n\n const listener = (event: Event) => {\n const current = states.get(el)\n if (!current) return\n\n const { enabled, handler, exclude } = current.options\n if (!enabled || !handler) return\n\n if ('button' in (event as any) && typeof (event as any).button === 'number' && (event as any).button !== 0) {\n return\n }\n\n if (!el.isConnected) return\n\n if (isEventInside(el, event)) return\n\n const excluded = resolveExclude(current.doc, exclude)\n for (const ex of excluded) {\n if (isEventInside(ex, event)) return\n }\n\n handler(event as any)\n }\n\n const nextState: InternalState = { options, doc, listener }\n states.set(el, nextState)\n\n if (!options.enabled || !options.handler) return\n\n for (const event of options.events) {\n doc.addEventListener(event, listener, options.capture)\n }\n}\n\n/**\n * `v-click-outside` — обработчик клика вне элемента (например, закрытие дропдауна/модалки).\n */\nexport const vClickOutside: Directive<HTMLElement, ClickOutsideBindingValue> = {\n mounted(el, binding) {\n bind(el, binding.value)\n },\n updated(el, binding) {\n unbind(el)\n bind(el, binding.value)\n },\n unmounted(el) {\n unbind(el)\n },\n}\n"],"mappings":";AA4BA,SAAS,UAAU,OAAgE;CACjF,IAAI,OAAO,UAAU,YACnB,OAAO;EAAE,SAAS;EAAM,SAAS;EAAM,QAAQ,CAAC,OAAO;EAAG,SAAS;EAAO,SAAS,CAAC;CAAE;CAGxF,IAAI,SAAS,OAAO,UAAU,UAC5B,OAAO;EACL,SAAS,MAAM,WAAW;EAC1B,SAAS,MAAM,WAAW;EAC1B,QAAQ,MAAM,QAAQ,SAAS,MAAM,SAAS,CAAC,OAAO;EACtD,SAAS,MAAM;EACf,SAAS,MAAM,WAAW,CAAC;CAC7B;CAGF,OAAO;EAAE,SAAS;EAAO,SAAS;EAAM,QAAQ,CAAC,OAAO;EAAG,SAAS,KAAA;EAAW,SAAS,CAAC;CAAE;AAC7F;AAEA,SAAS,cAAc,IAAiB,OAAuB;CAC7D,MAAM,SAAS,MAAM;CACrB,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,eAAgB,MAAc,eAAe;CACnD,IAAI,MAAM,QAAQ,YAAY,GAC5B,OAAO,aAAa,SAAS,EAAE;CAGjC,OAAO,GAAG,SAAS,MAAM;AAC3B;AAEA,SAAS,eAAe,KAAe,SAA+C;CACpF,MAAM,WAA0B,CAAC;CAEjC,KAAK,MAAM,QAAQ,SAAS;EAC1B,IAAI,OAAO,SAAS,UAAU;GAC5B,MAAM,QAAQ,IAAI,cAAc,IAAI;GACpC,IAAI,iBAAiB,aAAa,SAAS,KAAK,KAAK;GACrD;EACF;EAEA,IAAI,OAAO,SAAS,YAAY;GAC9B,MAAM,QAAQ,KAAK;GACnB,IAAI,iBAAiB,aAAa,SAAS,KAAK,KAAK;GACrD;EACF;EAEA,IAAI,gBAAgB,aAClB,SAAS,KAAK,IAAI;CAEtB;CAEA,OAAO;AACT;AAQA,IAAM,yBAAS,IAAI,QAAoC;AAEvD,SAAS,OAAO,IAAiB;CAC/B,MAAM,QAAQ,OAAO,IAAI,EAAE;CAC3B,IAAI,CAAC,OAAO;CAEZ,KAAK,MAAM,SAAS,MAAM,QAAQ,QAChC,MAAM,IAAI,oBAAoB,OAAO,MAAM,UAAU,MAAM,QAAQ,OAAO;CAG5E,OAAO,OAAO,EAAE;AAClB;AAEA,SAAS,KAAK,IAAiB,OAA6C;CAC1E,MAAM,UAAU,UAAU,KAAK;CAC/B,MAAM,MAAM,GAAG;CAEf,MAAM,YAAY,UAAiB;EACjC,MAAM,UAAU,OAAO,IAAI,EAAE;EAC7B,IAAI,CAAC,SAAS;EAEd,MAAM,EAAE,SAAS,SAAS,YAAY,QAAQ;EAC9C,IAAI,CAAC,WAAW,CAAC,SAAS;EAE1B,IAAI,YAAa,SAAiB,OAAQ,MAAc,WAAW,YAAa,MAAc,WAAW,GACvG;EAGF,IAAI,CAAC,GAAG,aAAa;EAErB,IAAI,cAAc,IAAI,KAAK,GAAG;EAE9B,MAAM,WAAW,eAAe,QAAQ,KAAK,OAAO;EACpD,KAAK,MAAM,MAAM,UACf,IAAI,cAAc,IAAI,KAAK,GAAG;EAGhC,QAAQ,KAAY;CACtB;CAEA,MAAM,YAA2B;EAAE;EAAS;EAAK;CAAS;CAC1D,OAAO,IAAI,IAAI,SAAS;CAExB,IAAI,CAAC,QAAQ,WAAW,CAAC,QAAQ,SAAS;CAE1C,KAAK,MAAM,SAAS,QAAQ,QAC1B,IAAI,iBAAiB,OAAO,UAAU,QAAQ,OAAO;AAEzD;;;;AAKA,IAAa,gBAAkE;CAC7E,QAAQ,IAAI,SAAS;EACnB,KAAK,IAAI,QAAQ,KAAK;CACxB;CACA,QAAQ,IAAI,SAAS;EACnB,OAAO,EAAE;EACT,KAAK,IAAI,QAAQ,KAAK;CACxB;CACA,UAAU,IAAI;EACZ,OAAO,EAAE;CACX;AACF"}
|
|
1
|
+
{"version":3,"file":"clickOutside.js","names":[],"sources":["../../src/directives/clickOutside.ts"],"sourcesContent":["import type { Directive } from 'vue'\n\nexport type ClickOutsideHandler = (event: MouseEvent | TouchEvent | PointerEvent) => void\n\nexport type ClickOutsideExclude = HTMLElement | string | (() => HTMLElement | null | undefined)\n\nexport type ClickOutsideBindingValue =\n | ClickOutsideHandler\n | {\n handler: ClickOutsideHandler\n /** По умолчанию `true`. */\n enabled?: boolean\n /** По умолчанию `true` (слушаем в capture, чтобы stopPropagation внутри не ломал закрытие). */\n capture?: boolean\n /** Список событий. По умолчанию `['click']`. */\n events?: Array<'click' | 'mousedown' | 'touchstart' | 'pointerdown'>\n /** Элементы/селекторы, клики по которым считаются \"внутри\". */\n exclude?: ClickOutsideExclude[]\n }\n\ntype NormalizedOptions = {\n enabled: boolean\n capture: boolean\n events: Array<'click' | 'mousedown' | 'touchstart' | 'pointerdown'>\n handler: ClickOutsideHandler | undefined\n exclude: ClickOutsideExclude[]\n}\n\nfunction normalize(value: ClickOutsideBindingValue | undefined): NormalizedOptions {\n if (typeof value === 'function') {\n return { enabled: true, capture: true, events: ['click'], handler: value, exclude: [] }\n }\n\n if (value && typeof value === 'object') {\n return {\n enabled: value.enabled ?? true,\n capture: value.capture ?? true,\n events: value.events?.length ? value.events : ['click'],\n handler: value.handler,\n exclude: value.exclude ?? [],\n }\n }\n\n return { enabled: false, capture: true, events: ['click'], handler: undefined, exclude: [] }\n}\n\nfunction isEventInside(el: HTMLElement, event: Event): boolean {\n const target = event.target as Node | null\n if (!target) return false\n\n const composedPath = (event as any).composedPath?.() as EventTarget[] | undefined\n if (Array.isArray(composedPath)) {\n return composedPath.includes(el)\n }\n\n return el.contains(target)\n}\n\nfunction resolveExclude(doc: Document, exclude: ClickOutsideExclude[]): HTMLElement[] {\n const resolved: HTMLElement[] = []\n\n for (const item of exclude) {\n if (typeof item === 'string') {\n const found = doc.querySelector(item)\n if (found instanceof HTMLElement) resolved.push(found)\n continue\n }\n\n if (typeof item === 'function') {\n const found = item()\n if (found instanceof HTMLElement) resolved.push(found)\n continue\n }\n\n if (item instanceof HTMLElement) {\n resolved.push(item)\n }\n }\n\n return resolved\n}\n\ntype ElementState = {\n options: NormalizedOptions\n doc: Document\n /** Ключи подписок, которые этот элемент держит на своём документе. */\n keys: string[]\n}\n\nconst states = new WeakMap<HTMLElement, ElementState>()\n\n/**\n * Слушатель — один на документ и вид события, а не на элемент.\n *\n * Каждый элемент со своим слушателем — это десяток подписок на документе у\n * страницы с десятком оверлеев, и полное переподключение на каждом обновлении\n * хозяина: хук `updated` срабатывает на любой ререндер, а набор событий при\n * этом обычно тот же. Здесь подписка живёт по счётчику потребителей, а элементы\n * обходятся общим обработчиком.\n */\nconst documentElements = new WeakMap<Document, Set<HTMLElement>>()\nconst documentSubscriptions = new WeakMap<Document, Map<string, { listener: (event: Event) => void, count: number }>>()\n\nfunction subscriptionKey(type: string, capture: boolean): string {\n return `${type}|${capture ? 'capture' : 'bubble'}`\n}\n\nfunction keysOf(options: NormalizedOptions): string[] {\n if (!options.enabled || !options.handler) return []\n\n return options.events.map(type => subscriptionKey(type, options.capture))\n}\n\nfunction dispatch(doc: Document, event: Event, capture: boolean): void {\n const elements = documentElements.get(doc)\n if (!elements) return\n\n // Копия: обработчик закрывает оверлей, а тот на размонтировании правит набор.\n for (const el of [...elements]) {\n const state = states.get(el)\n if (!state) continue\n\n const { enabled, handler, exclude, events } = state.options\n if (!enabled || !handler) continue\n if (state.options.capture !== capture) continue\n if (!events.includes(event.type as NormalizedOptions['events'][number])) continue\n\n if ('button' in (event as any) && typeof (event as any).button === 'number' && (event as any).button !== 0) {\n continue\n }\n\n if (!el.isConnected) continue\n if (isEventInside(el, event)) continue\n\n const excluded = resolveExclude(state.doc, exclude)\n if (excluded.some(item => isEventInside(item, event))) continue\n\n handler(event as any)\n }\n}\n\nfunction subscribe(doc: Document, key: string): void {\n let subscriptions = documentSubscriptions.get(doc)\n if (!subscriptions) {\n subscriptions = new Map()\n documentSubscriptions.set(doc, subscriptions)\n }\n\n const existing = subscriptions.get(key)\n if (existing) {\n existing.count += 1\n return\n }\n\n const [type, mode] = key.split('|')\n const capture = mode === 'capture'\n const listener = (event: Event) => dispatch(doc, event, capture)\n\n subscriptions.set(key, { listener, count: 1 })\n doc.addEventListener(type, listener, capture)\n}\n\nfunction unsubscribe(doc: Document, key: string): void {\n const subscriptions = documentSubscriptions.get(doc)\n const existing = subscriptions?.get(key)\n if (!subscriptions || !existing) return\n\n existing.count -= 1\n if (existing.count > 0) return\n\n const [type, mode] = key.split('|')\n doc.removeEventListener(type, existing.listener, mode === 'capture')\n subscriptions.delete(key)\n}\n\nfunction unbind(el: HTMLElement) {\n const state = states.get(el)\n if (!state) return\n\n for (const key of state.keys) unsubscribe(state.doc, key)\n\n documentElements.get(state.doc)?.delete(el)\n states.delete(el)\n}\n\nfunction bind(el: HTMLElement, value: ClickOutsideBindingValue | undefined) {\n const doc = el.ownerDocument\n const previous = states.get(el)\n\n // Элемент, переехавший в другой документ (портал в отдельное окно), обязан\n // отпустить подписки прежнего: там его больше нет.\n if (previous && previous.doc !== doc) unbind(el)\n\n const options = normalize(value)\n const nextKeys = keysOf(options)\n const prevKeys = states.get(el)?.keys ?? []\n\n states.set(el, { options, doc, keys: nextKeys })\n\n let elements = documentElements.get(doc)\n if (!elements) {\n elements = new Set()\n documentElements.set(doc, elements)\n }\n elements.add(el)\n\n for (const key of nextKeys) if (!prevKeys.includes(key)) subscribe(doc, key)\n for (const key of prevKeys) if (!nextKeys.includes(key)) unsubscribe(doc, key)\n}\n\n/**\n * `v-click-outside` — обработчик клика вне элемента (например, закрытие дропдауна/модалки).\n */\nexport const vClickOutside: Directive<HTMLElement, ClickOutsideBindingValue> = {\n mounted(el, binding) {\n bind(el, binding.value)\n },\n updated(el, binding) {\n // Не `unbind` + `bind`: разницу подписок считает сам `bind`, а снятие с\n // последующей постановкой того же слушателя — лишняя работа на каждый\n // ререндер хозяина.\n bind(el, binding.value)\n },\n unmounted(el) {\n unbind(el)\n },\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-
|
|
1
|
+
import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-Dds_519x.js";
|
|
2
2
|
export { GRANULARITY_PROVIDER_ID, createGranularityProvider, granularityProvider as default, granularityProvider, granularityComponentConfigs, granularityDefaultThemes, granularityThemeNames };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-
|
|
1
|
+
import { a as granularityDefaultThemes, i as granularityComponentConfigs, n as GRANULARITY_PROVIDER_ID, o as granularityThemeNames, r as createGranularityProvider, t as granularityProvider } from "./chunks/granular-provider-Dds_519x.js";
|
|
2
2
|
export { GRANULARITY_PROVIDER_ID, createGranularityProvider, granularityProvider as default, granularityProvider, granularityComponentConfigs, granularityDefaultThemes, granularityThemeNames };
|
package/dist/index.js
CHANGED
|
@@ -35,8 +35,8 @@ import { t as GrBadgeWrap_default } from "./components/GrBadgeWrap/chunks/GrBadg
|
|
|
35
35
|
import { n as grBottomNavSafelist, t as grBottomNavConfig } from "./chunks/config-DM0lsduD.js";
|
|
36
36
|
import { t as GrBottomNav_default } from "./components/GrBottomNav/chunks/GrBottomNav-wtFatLjB.js";
|
|
37
37
|
import { t as GrLink_default } from "./components/GrLink/chunks/GrLink-DAGCFYO7.js";
|
|
38
|
-
import {
|
|
39
|
-
import { t as GrBreadcrumbs_default } from "./components/GrBreadcrumbs/chunks/GrBreadcrumbs-
|
|
38
|
+
import { g as resolveBreadcrumbsLayout, h as resolveBreadcrumbsFit, n as grBreadcrumbsSafelist, t as grBreadcrumbsConfig } from "./chunks/config-C0Eu8jpG.js";
|
|
39
|
+
import { t as GrBreadcrumbs_default } from "./components/GrBreadcrumbs/chunks/GrBreadcrumbs-BKOvl8W1.js";
|
|
40
40
|
import { n as useGrButtonGroup } from "./chunks/context-BfIQv7m1.js";
|
|
41
41
|
import { t as GrButton_default } from "./components/GrButton/chunks/GrButton-Bw2AH4uX.js";
|
|
42
42
|
import { t as grButtonSafelist } from "./chunks/safelist-BOq5Li7p.js";
|
|
@@ -79,14 +79,14 @@ import { a as extendDefaultParsers, n as coreResponseErrorParsers, r as createRe
|
|
|
79
79
|
import { t as GrConfirmDialog_default } from "./components/GrConfirmDialog/chunks/GrConfirmDialog-B9mIU78E.js";
|
|
80
80
|
import { t as grConfirmDialogConfig } from "./chunks/config-A-bBiotF.js";
|
|
81
81
|
import "./components/GrConfirmDialog/index.js";
|
|
82
|
-
import { a as GrDropdownMenuItem_default, c as GrDropdownMenuDivider_default, o as GrDropdownMenuGroup_default, s as GrDropdownMenuHeader_default, t as GrDropdownMenuList_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenuList-
|
|
83
|
-
import { t as GrContextMenu_default } from "./components/GrContextMenu/chunks/GrContextMenu-
|
|
82
|
+
import { a as GrDropdownMenuItem_default, c as GrDropdownMenuDivider_default, o as GrDropdownMenuGroup_default, s as GrDropdownMenuHeader_default, t as GrDropdownMenuList_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenuList-RW5IBvmu.js";
|
|
83
|
+
import { t as GrContextMenu_default } from "./components/GrContextMenu/chunks/GrContextMenu-BNQDbAsY.js";
|
|
84
84
|
import { t as grContextMenuConfig } from "./chunks/config-CPSxM7XE.js";
|
|
85
85
|
import { t as GrTable_default } from "./components/GrTable/chunks/GrTable-Zcdz2St_.js";
|
|
86
86
|
import { t as useDragSort } from "./chunks/useDragSort-0l47h4yb.js";
|
|
87
87
|
import { t as GrDataTable_default } from "./components/GrDataTable/chunks/GrDataTable-DU00V44y.js";
|
|
88
88
|
import { n as grDataTableSafelist, t as grDataTableConfig } from "./chunks/config-DeyT9dJl.js";
|
|
89
|
-
import { t as GrDelta_default } from "./components/GrDelta/chunks/GrDelta-
|
|
89
|
+
import { t as GrDelta_default } from "./components/GrDelta/chunks/GrDelta-BZwkgQW-.js";
|
|
90
90
|
import { n as grValueSafelist, t as grValueConfig } from "./chunks/config-Z5LeUXys.js";
|
|
91
91
|
import { t as GrValue_default } from "./components/GrValue/chunks/GrValue-ezkQM05Q.js";
|
|
92
92
|
import { n as deltaTone, t as deltaDirection } from "./chunks/deltaTone-B5OoS1vo.js";
|
|
@@ -109,8 +109,8 @@ import { t as GrDrawer_default } from "./components/GrDrawer/chunks/GrDrawer-BCr
|
|
|
109
109
|
import { t as GrDropdown_default } from "./components/GrDropdown/chunks/GrDropdown-13Wt9eB_.js";
|
|
110
110
|
import { n as grDropdownSafelist, t as grDropdownConfig } from "./chunks/config-uzUuosv7.js";
|
|
111
111
|
import "./components/GrDropdown/index.js";
|
|
112
|
-
import { n as GrDropdownMenuColumn_default, r as GrDropdownMenu_default, t as GrDropdownMenuColumns_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenu-
|
|
113
|
-
import { n as grDropdownMenuSafelist, t as grDropdownMenuConfig } from "./chunks/config-
|
|
112
|
+
import { n as GrDropdownMenuColumn_default, r as GrDropdownMenu_default, t as GrDropdownMenuColumns_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenu-Cg7qHV9J.js";
|
|
113
|
+
import { n as grDropdownMenuSafelist, t as grDropdownMenuConfig } from "./chunks/config-_jbgsFpw.js";
|
|
114
114
|
import { t as GrEmptyState_default } from "./components/GrEmptyState/chunks/GrEmptyState-D4T5pzXA.js";
|
|
115
115
|
import { n as grEmptyStateSafelist, t as grEmptyStateConfig } from "./chunks/config-CWtfxkM9.js";
|
|
116
116
|
import { n as fileKindOf, r as isPreviewableKind, t as GrFilePreview_default } from "./components/GrFilePreview/chunks/GrFilePreview-C9Z7hMK8.js";
|
|
@@ -12,6 +12,16 @@ export type GrBreadcrumbItem = {
|
|
|
12
12
|
* UnoCSS-сборки (`i-lucide-*` требует вашего `presetIcons`).
|
|
13
13
|
*/
|
|
14
14
|
icon?: string | Component;
|
|
15
|
+
/**
|
|
16
|
+
* Показывать только иконку: подпись прячется визуально, но остаётся в
|
|
17
|
+
* разметке и в дереве доступности. Классический «домик» в начале пути.
|
|
18
|
+
*
|
|
19
|
+
* Подпись не выбрасывается и не подменяется на `aria-label` намеренно: путь
|
|
20
|
+
* читают и поиском, и диктором, и пункт без имени для незрячего пустой.
|
|
21
|
+
* Без `icon` поле игнорируется — прятать подпись, ничего не показав взамен,
|
|
22
|
+
* значит стереть пункт.
|
|
23
|
+
*/
|
|
24
|
+
iconOnly?: boolean;
|
|
15
25
|
disabled?: boolean;
|
|
16
26
|
/** Доступное имя пункта, когда подписи недостаточно («Настройки» → «Настройки проекта»). */
|
|
17
27
|
ariaLabel?: string;
|
|
@@ -46,6 +56,8 @@ export declare const breadcrumbsCurrentClass = "inline-flex items-center gap-1 m
|
|
|
46
56
|
export declare const breadcrumbsItemWrapClass = "flex items-center min-w-0";
|
|
47
57
|
export declare const breadcrumbsItemIconClass = "inline-block h-4 w-4 shrink-0";
|
|
48
58
|
export declare const breadcrumbsLabelClass = "truncate";
|
|
59
|
+
/** Подпись пункта-иконки: не видна, но читается диктором и поиском. */
|
|
60
|
+
export declare const breadcrumbsLabelHiddenClass = "sr-only";
|
|
49
61
|
/**
|
|
50
62
|
* Кнопка «…»: раскрывает схлопнутую середину пути на месте. Оформлена как
|
|
51
63
|
* приглушённая ссылка, чтобы не выбиваться из ряда.
|
|
@@ -24,8 +24,24 @@ export declare const itemShortcutClass = "ml-auto pl-4 text-[length:var(--gr-tex
|
|
|
24
24
|
export declare const headerClass = "px-4 py-2 text-[length:var(--gr-text-xs)] leading-[var(--gr-leading-xs)] tracking-wide text-[var(--gr-muted-fg)]";
|
|
25
25
|
export declare const listBaseClass = "w-full";
|
|
26
26
|
export declare const dividersClass = "divide-y divide-[var(--gr-brd)]";
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Линия у края панели рисуется псевдоэлементом с инсетом, а не рамкой бокса.
|
|
29
|
+
*
|
|
30
|
+
* Список лежит в поле панели — 1 px рамки плюс 4 px `p-1`, — а угол скруглён на
|
|
31
|
+
* `--gr-radius-xl` (16 px). На глубине 5 px дуга ещё идёт: штрих рамки занимает
|
|
32
|
+
* там `x ∈ [4.4, 5.8]`, и правило во всю ширину, начинаясь на `x = 5`, упирается
|
|
33
|
+
* не в вертикальный край, а в дугу. Вместо двух самостоятельных линий у каждого
|
|
34
|
+
* угла виден клин, в который они сходятся.
|
|
35
|
+
*
|
|
36
|
+
* Инсет тот же, что у `GrDropdownMenuDivider :inset` (8 px), и уводит концы из
|
|
37
|
+
* полосы радиуса. Пункты при этом остаются во всю ширину: их ширина — часть
|
|
38
|
+
* попадания подсветки в поле панели, и сжимать список целиком нельзя.
|
|
39
|
+
*
|
|
40
|
+
* Та же арифметика уже учтена у `itemBaseClass`; здесь она доведена до линий.
|
|
41
|
+
*/
|
|
42
|
+
export declare const borderEdgeClass = "relative";
|
|
43
|
+
export declare const borderTopClass = "before:absolute before:inset-x-2 before:top-0 before:h-px before:bg-[var(--gr-brd)] before:content-empty";
|
|
44
|
+
export declare const borderBottomClass = "after:absolute after:inset-x-2 after:bottom-0 after:h-px after:bg-[var(--gr-brd)] after:content-empty";
|
|
29
45
|
export declare const columnsBaseClass = "w-full grid divide-x divide-[var(--gr-brd)]";
|
|
30
46
|
export declare const columnBaseClass = "px-3 py-2 flex items-center";
|
|
31
47
|
export declare const dividerClass = "border-t border-[var(--gr-brd)]";
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* приложением с i18n и без него не возникает.
|
|
8
8
|
*
|
|
9
9
|
* Инстансы `Intl` кэшируются: их построение примерно на порядок дороже самого
|
|
10
|
-
* форматирования. Кэш ограничен
|
|
11
|
-
*
|
|
10
|
+
* форматирования. Кэш ограничен — иначе сгенерированные на лету опции растили
|
|
11
|
+
* бы его без предела, — и вытесняет по давности чтения.
|
|
12
12
|
*/
|
|
13
13
|
/**
|
|
14
14
|
* Локаль приходит из настроек приложения, а `Intl` бросает на некорректном
|
package/dist/web-types.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
|
|
3
3
|
"name": "@feugene/granularity",
|
|
4
|
-
"version": "0.28.
|
|
4
|
+
"version": "0.28.2",
|
|
5
5
|
"framework": "vue",
|
|
6
6
|
"js-types-syntax": "typescript",
|
|
7
7
|
"description-markup": "markdown",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feugene/granularity",
|
|
3
3
|
"description": "Granularity design system package with Vue 3 components, consumed via the `@feugene/unocss-preset-granular` preset.",
|
|
4
|
-
"version": "0.28.
|
|
4
|
+
"version": "0.28.2",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Evgeniy Fureev",
|
|
@@ -69,6 +69,10 @@
|
|
|
69
69
|
"types": "./dist/types/components/GrAvatar/index.d.ts",
|
|
70
70
|
"import": "./dist/components/GrAvatar/index.js"
|
|
71
71
|
},
|
|
72
|
+
"./components/GrAvatarGroup": {
|
|
73
|
+
"types": "./dist/types/components/GrAvatar/index.d.ts",
|
|
74
|
+
"import": "./dist/components/GrAvatar/index.js"
|
|
75
|
+
},
|
|
72
76
|
"./components/GrBadge": {
|
|
73
77
|
"types": "./dist/types/components/GrBadge/index.d.ts",
|
|
74
78
|
"import": "./dist/components/GrBadge/index.js"
|
|
@@ -121,6 +125,10 @@
|
|
|
121
125
|
"types": "./dist/types/components/GrCollapse/index.d.ts",
|
|
122
126
|
"import": "./dist/components/GrCollapse/index.js"
|
|
123
127
|
},
|
|
128
|
+
"./components/GrCollapseItem": {
|
|
129
|
+
"types": "./dist/types/components/GrCollapse/index.d.ts",
|
|
130
|
+
"import": "./dist/components/GrCollapse/index.js"
|
|
131
|
+
},
|
|
124
132
|
"./components/GrColorPicker": {
|
|
125
133
|
"types": "./dist/types/components/GrColorPicker/index.d.ts",
|
|
126
134
|
"import": "./dist/components/GrColorPicker/index.js"
|
|
@@ -157,10 +165,26 @@
|
|
|
157
165
|
"types": "./dist/types/components/GrDialog/index.d.ts",
|
|
158
166
|
"import": "./dist/components/GrDialog/index.js"
|
|
159
167
|
},
|
|
168
|
+
"./components/GrDialogCloseButton": {
|
|
169
|
+
"types": "./dist/types/components/GrDialog/index.d.ts",
|
|
170
|
+
"import": "./dist/components/GrDialog/index.js"
|
|
171
|
+
},
|
|
172
|
+
"./components/GrDialogFooter": {
|
|
173
|
+
"types": "./dist/types/components/GrDialog/index.d.ts",
|
|
174
|
+
"import": "./dist/components/GrDialog/index.js"
|
|
175
|
+
},
|
|
176
|
+
"./components/GrDialogHeader": {
|
|
177
|
+
"types": "./dist/types/components/GrDialog/index.d.ts",
|
|
178
|
+
"import": "./dist/components/GrDialog/index.js"
|
|
179
|
+
},
|
|
160
180
|
"./components/GrDialogService": {
|
|
161
181
|
"types": "./dist/types/components/GrDialogService/index.d.ts",
|
|
162
182
|
"import": "./dist/components/GrDialogService/index.js"
|
|
163
183
|
},
|
|
184
|
+
"./components/GrDialogServiceHost": {
|
|
185
|
+
"types": "./dist/types/components/GrDialogService/index.d.ts",
|
|
186
|
+
"import": "./dist/components/GrDialogService/index.js"
|
|
187
|
+
},
|
|
164
188
|
"./components/GrDivider": {
|
|
165
189
|
"types": "./dist/types/components/GrDivider/index.d.ts",
|
|
166
190
|
"import": "./dist/components/GrDivider/index.js"
|
|
@@ -177,6 +201,34 @@
|
|
|
177
201
|
"types": "./dist/types/components/GrDropdownMenu/index.d.ts",
|
|
178
202
|
"import": "./dist/components/GrDropdownMenu/index.js"
|
|
179
203
|
},
|
|
204
|
+
"./components/GrDropdownMenuColumn": {
|
|
205
|
+
"types": "./dist/types/components/GrDropdownMenu/index.d.ts",
|
|
206
|
+
"import": "./dist/components/GrDropdownMenu/index.js"
|
|
207
|
+
},
|
|
208
|
+
"./components/GrDropdownMenuColumns": {
|
|
209
|
+
"types": "./dist/types/components/GrDropdownMenu/index.d.ts",
|
|
210
|
+
"import": "./dist/components/GrDropdownMenu/index.js"
|
|
211
|
+
},
|
|
212
|
+
"./components/GrDropdownMenuDivider": {
|
|
213
|
+
"types": "./dist/types/components/GrDropdownMenu/index.d.ts",
|
|
214
|
+
"import": "./dist/components/GrDropdownMenu/index.js"
|
|
215
|
+
},
|
|
216
|
+
"./components/GrDropdownMenuGroup": {
|
|
217
|
+
"types": "./dist/types/components/GrDropdownMenu/index.d.ts",
|
|
218
|
+
"import": "./dist/components/GrDropdownMenu/index.js"
|
|
219
|
+
},
|
|
220
|
+
"./components/GrDropdownMenuHeader": {
|
|
221
|
+
"types": "./dist/types/components/GrDropdownMenu/index.d.ts",
|
|
222
|
+
"import": "./dist/components/GrDropdownMenu/index.js"
|
|
223
|
+
},
|
|
224
|
+
"./components/GrDropdownMenuItem": {
|
|
225
|
+
"types": "./dist/types/components/GrDropdownMenu/index.d.ts",
|
|
226
|
+
"import": "./dist/components/GrDropdownMenu/index.js"
|
|
227
|
+
},
|
|
228
|
+
"./components/GrDropdownMenuList": {
|
|
229
|
+
"types": "./dist/types/components/GrDropdownMenu/index.d.ts",
|
|
230
|
+
"import": "./dist/components/GrDropdownMenu/index.js"
|
|
231
|
+
},
|
|
180
232
|
"./components/GrEmptyState": {
|
|
181
233
|
"types": "./dist/types/components/GrEmptyState/index.d.ts",
|
|
182
234
|
"import": "./dist/components/GrEmptyState/index.js"
|
|
@@ -193,6 +245,10 @@
|
|
|
193
245
|
"types": "./dist/types/components/GrForm/index.d.ts",
|
|
194
246
|
"import": "./dist/components/GrForm/index.js"
|
|
195
247
|
},
|
|
248
|
+
"./components/GrFormErrorBanner": {
|
|
249
|
+
"types": "./dist/types/components/GrResponseErrorBanner/index.d.ts",
|
|
250
|
+
"import": "./dist/components/GrResponseErrorBanner/index.js"
|
|
251
|
+
},
|
|
196
252
|
"./components/GrFormField": {
|
|
197
253
|
"types": "./dist/types/components/GrFormField/index.d.ts",
|
|
198
254
|
"import": "./dist/components/GrFormField/index.js"
|
|
@@ -237,6 +293,10 @@
|
|
|
237
293
|
"types": "./dist/types/components/GrList/index.d.ts",
|
|
238
294
|
"import": "./dist/components/GrList/index.js"
|
|
239
295
|
},
|
|
296
|
+
"./components/GrListItem": {
|
|
297
|
+
"types": "./dist/types/components/GrList/index.d.ts",
|
|
298
|
+
"import": "./dist/components/GrList/index.js"
|
|
299
|
+
},
|
|
240
300
|
"./components/GrLoading": {
|
|
241
301
|
"types": "./dist/types/components/GrLoading/index.d.ts",
|
|
242
302
|
"import": "./dist/components/GrLoading/index.js"
|
|
@@ -301,6 +361,14 @@
|
|
|
301
361
|
"types": "./dist/types/components/GrSidebar/index.d.ts",
|
|
302
362
|
"import": "./dist/components/GrSidebar/index.js"
|
|
303
363
|
},
|
|
364
|
+
"./components/GrSidebarGroup": {
|
|
365
|
+
"types": "./dist/types/components/GrSidebar/index.d.ts",
|
|
366
|
+
"import": "./dist/components/GrSidebar/index.js"
|
|
367
|
+
},
|
|
368
|
+
"./components/GrSidebarItem": {
|
|
369
|
+
"types": "./dist/types/components/GrSidebar/index.d.ts",
|
|
370
|
+
"import": "./dist/components/GrSidebar/index.js"
|
|
371
|
+
},
|
|
304
372
|
"./components/GrSkeleton": {
|
|
305
373
|
"types": "./dist/types/components/GrSkeleton/index.d.ts",
|
|
306
374
|
"import": "./dist/components/GrSkeleton/index.js"
|
|
@@ -333,6 +401,10 @@
|
|
|
333
401
|
"types": "./dist/types/components/GrTable/index.d.ts",
|
|
334
402
|
"import": "./dist/components/GrTable/index.js"
|
|
335
403
|
},
|
|
404
|
+
"./components/GrTabPanel": {
|
|
405
|
+
"types": "./dist/types/components/GrTabPanels/index.d.ts",
|
|
406
|
+
"import": "./dist/components/GrTabPanels/index.js"
|
|
407
|
+
},
|
|
336
408
|
"./components/GrTabPanels": {
|
|
337
409
|
"types": "./dist/types/components/GrTabPanels/index.d.ts",
|
|
338
410
|
"import": "./dist/components/GrTabPanels/index.js"
|
|
@@ -349,6 +421,10 @@
|
|
|
349
421
|
"types": "./dist/types/components/GrTimeline/index.d.ts",
|
|
350
422
|
"import": "./dist/components/GrTimeline/index.js"
|
|
351
423
|
},
|
|
424
|
+
"./components/GrTimelineItem": {
|
|
425
|
+
"types": "./dist/types/components/GrTimeline/index.d.ts",
|
|
426
|
+
"import": "./dist/components/GrTimeline/index.js"
|
|
427
|
+
},
|
|
352
428
|
"./components/GrToaster": {
|
|
353
429
|
"types": "./dist/types/components/GrToaster/index.d.ts",
|
|
354
430
|
"import": "./dist/components/GrToaster/index.js"
|
|
@@ -365,6 +441,10 @@
|
|
|
365
441
|
"types": "./dist/types/components/GrTreeSelect/index.d.ts",
|
|
366
442
|
"import": "./dist/components/GrTreeSelect/index.js"
|
|
367
443
|
},
|
|
444
|
+
"./components/GrUploadErrorBanner": {
|
|
445
|
+
"types": "./dist/types/components/GrResponseErrorBanner/index.d.ts",
|
|
446
|
+
"import": "./dist/components/GrResponseErrorBanner/index.js"
|
|
447
|
+
},
|
|
368
448
|
"./components/GrValue": {
|
|
369
449
|
"types": "./dist/types/components/GrValue/index.d.ts",
|
|
370
450
|
"import": "./dist/components/GrValue/index.js"
|
|
@@ -508,7 +588,7 @@
|
|
|
508
588
|
},
|
|
509
589
|
"peerDependencies": {
|
|
510
590
|
"@feugene/fint-i18n": "^0.6.0",
|
|
511
|
-
"@feugene/unocss-preset-granular": "^0.
|
|
591
|
+
"@feugene/unocss-preset-granular": "^0.10.1",
|
|
512
592
|
"@floating-ui/dom": "^1.8.0",
|
|
513
593
|
"vue": "^3.5.0"
|
|
514
594
|
},
|
|
@@ -523,8 +603,8 @@
|
|
|
523
603
|
"devDependencies": {
|
|
524
604
|
"@antfu/eslint-config": "^9.1.0",
|
|
525
605
|
"@feugene/fint-i18n": "^0.6.0",
|
|
526
|
-
"@feugene/granularity-test-kit": "^0.
|
|
527
|
-
"@feugene/unocss-preset-granular": "^0.
|
|
606
|
+
"@feugene/granularity-test-kit": "^0.5.0",
|
|
607
|
+
"@feugene/unocss-preset-granular": "^0.10.1",
|
|
528
608
|
"@floating-ui/dom": "^1.8.0",
|
|
529
609
|
"@iconify-json/lucide": "^1.2.117",
|
|
530
610
|
"@types/node": "^25.9.5",
|
|
@@ -553,6 +633,7 @@
|
|
|
553
633
|
"generate:tokens": "node --experimental-strip-types scripts/generate-tokens.mjs",
|
|
554
634
|
"lint": "eslint . --cache",
|
|
555
635
|
"lint:fix": "eslint . --cache --fix",
|
|
636
|
+
"sizes": "node scripts/report-entry-sizes.mjs",
|
|
556
637
|
"test": "vitest --config vitest.config.ts",
|
|
557
638
|
"test:coverage": "vitest run --config vitest.config.ts --coverage",
|
|
558
639
|
"test:run": "vitest run --config vitest.config.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-CWthWcWY.js","names":[],"sources":["../../src/components/GrDropdownMenu/safelist.ts","../../src/components/GrDropdownMenu/config.ts"],"sourcesContent":["import { splitClassTokens } from '../shared/classTokens'\n\nimport {\n alignClass,\n borderBottomClass,\n borderTopClass,\n colsClass,\n columnBaseClass,\n columnsBaseClass,\n dividerClass,\n dividerInsetClass,\n dividersClass,\n headerClass,\n itemBaseClass,\n itemDisabledClass,\n itemIndicatorClass,\n itemInteractiveClass,\n itemShortcutClass,\n itemVariantClass,\n listBaseClass,\n textAlignClass,\n} from './grDropdownMenuStyles'\n\n/**\n * Классы каталога живут в `.ts`-хелпере, а его бандлер волен вынести в общий\n * `dist/chunks/` — вне области скана компонента. Симптом промаха тут особенно\n * незаметный: размеры пунктов на месте, а выравнивание, колонки и цвета\n * пропали. Гейт — `src/__tests__/safelist.test.ts`.\n */\nexport const grDropdownMenuSafelist = [...new Set([\n ...Object.values(alignClass).flatMap(splitClassTokens),\n ...Object.values(textAlignClass).flatMap(splitClassTokens),\n ...Object.values(colsClass).flatMap(splitClassTokens),\n ...Object.values(itemVariantClass).flatMap(splitClassTokens),\n ...splitClassTokens(itemBaseClass),\n ...splitClassTokens(itemInteractiveClass),\n ...splitClassTokens(itemDisabledClass),\n ...splitClassTokens(itemIndicatorClass),\n ...splitClassTokens(itemShortcutClass),\n ...splitClassTokens(headerClass),\n ...splitClassTokens(listBaseClass),\n ...splitClassTokens(dividersClass),\n ...splitClassTokens(borderTopClass),\n ...splitClassTokens(borderBottomClass),\n ...splitClassTokens(columnsBaseClass),\n ...splitClassTokens(columnBaseClass),\n ...splitClassTokens(dividerClass),\n ...splitClassTokens(dividerInsetClass),\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grDropdownMenuSafelist } from './safelist'\n\nexport const grDropdownMenuConfig = defineGranularComponent(import.meta.url, {\n name: 'GrDropdownMenu',\n dependencies: ['GrDropdown'],\n safelist: grDropdownMenuSafelist,\n})\n"],"mappings":";;;;;;;;;;AA6BA,IAAa,yBAAyB,CAAC,mBAAG,IAAI,IAAI;CAC9C,GAAG,OAAO,OAAO,UAAU,CAAC,CAAC,QAAQ,gBAAgB;CACrD,GAAG,OAAO,OAAO,cAAc,CAAC,CAAC,QAAQ,gBAAgB;CACzD,GAAG,OAAO,OAAO,SAAS,CAAC,CAAC,QAAQ,gBAAgB;CACpD,GAAG,OAAO,OAAO,gBAAgB,CAAC,CAAC,QAAQ,gBAAgB;CAC3D,GAAG,iBAAiB,aAAa;CACjC,GAAG,iBAAiB,oBAAoB;CACxC,GAAG,iBAAiB,iBAAiB;CACrC,GAAG,iBAAiB,kBAAkB;CACtC,GAAG,iBAAiB,iBAAiB;CACrC,GAAG,iBAAiB,WAAW;CAC/B,GAAG,iBAAiB,aAAa;CACjC,GAAG,iBAAiB,aAAa;CACjC,GAAG,iBAAiB,cAAc;CAClC,GAAG,iBAAiB,iBAAiB;CACrC,GAAG,iBAAiB,gBAAgB;CACpC,GAAG,iBAAiB,eAAe;CACnC,GAAG,iBAAiB,YAAY;CAChC,GAAG,iBAAiB,iBAAiB;AACzC,CAAC,CAAC;;;AC5CF,IAAa,uBAAuB,wBAAwB,OAAO,KAAK,KAAK;CAC3E,MAAM;CACN,cAAc,CAAC,YAAY;CAC3B,UAAU;AACZ,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-DONFPTFg.js","names":[],"sources":["../../src/components/GrBreadcrumbs/grBreadcrumbsStyles.ts","../../src/components/GrBreadcrumbs/safelist.ts","../../src/components/GrBreadcrumbs/config.ts"],"sourcesContent":["import type { Component } from 'vue'\n\nimport type { GrComponentSize } from '../shared/sizes'\n\nexport type GrBreadcrumbsSize = GrComponentSize\n\n/** Пункт пути. Кроме `label` всё опционально: последний пункт обычно без ссылки. */\nexport type GrBreadcrumbItem = {\n label: string\n href?: string\n /** Цель роутерной ссылки: уезжает в `GrLink` через `attrs` вместе с `as`. */\n to?: unknown\n /**\n * Иконка перед подписью — декоративна. Vue-компонент либо класс иконки вашей\n * UnoCSS-сборки (`i-lucide-*` требует вашего `presetIcons`).\n */\n icon?: string | Component\n disabled?: boolean\n /** Доступное имя пункта, когда подписи недостаточно («Настройки» → «Настройки проекта»). */\n ariaLabel?: string\n}\n\nexport const breadcrumbsRootClass = 'w-full min-w-0'\nexport const breadcrumbsListClass = 'flex items-center gap-1 m-0 p-0 [list-style:none]'\n\n/**\n * Перенос — умолчание: длинный путь уезжает на вторую строку и остаётся читаемым.\n * В режиме `autoCollapse` строка одна, иначе переполнения не случится никогда и\n * мерить будет нечего: список просто перенесётся.\n *\n * Исключение — раскрытый вручную путь: в одну строку он бы не влез (её нехватка и\n * вызвала схлопывание), `overflow: hidden` срезал бы хвост вместе с текущей\n * страницей, а фокус на раскрытом пункте молча уводил бы скролл контейнера.\n * Поэтому раскрытие возвращает перенос.\n */\nexport const breadcrumbsListWrapClass = 'flex-wrap'\nexport const breadcrumbsListNowrapClass = 'flex-nowrap overflow-hidden'\n\n/** Кегль строки пути. Шкала общая с `GrLink`: путь — это ряд ссылок. */\nexport const breadcrumbsSizeClassBySize: Record<GrBreadcrumbsSize, string> = {\n xs: 'text-[length:var(--gr-text-xs)] leading-[var(--gr-leading-xs)]',\n sm: 'text-[length:var(--gr-text-sm)] leading-[var(--gr-leading-sm)]',\n md: 'text-[length:var(--gr-text-sm)] leading-[var(--gr-leading-sm)]',\n lg: 'text-[length:var(--gr-text-base)] leading-[var(--gr-leading-base)]',\n}\n\nexport const breadcrumbsSeparatorClass = 'select-none text-[var(--gr-muted-fg)]'\n\n/** Текущая страница: не ссылка, но и не «выключенный» текст — обычный акцент подписи. */\nexport const breadcrumbsCurrentClass = 'inline-flex items-center gap-1 min-w-0 font-600 text-[var(--gr-fg)]'\n\n/**\n * Обёртка пункта — flex, а не блок с линейным боксом.\n *\n * Базовая линия `inline-flex` берётся от первого flex-элемента: у пункта\n * с иконкой это блочная иконка, и линейный бокс раздувается на высоту\n * подстрочных выносных. Пункт с иконкой выходил на 3px выше соседей, а при\n * `align-items: center` списка это смещало его содержимое на полтора пикселя.\n */\nexport const breadcrumbsItemWrapClass = 'flex items-center min-w-0'\n\nexport const breadcrumbsItemIconClass = 'inline-block h-4 w-4 shrink-0'\n\nexport const breadcrumbsLabelClass = 'truncate'\n\n/**\n * Кнопка «…»: раскрывает схлопнутую середину пути на месте. Оформлена как\n * приглушённая ссылка, чтобы не выбиваться из ряда.\n */\nexport const breadcrumbsEllipsisClass = 'inline-flex items-center rounded-[var(--gr-radius-sm)] px-1 text-[var(--gr-muted-fg)] hover:text-[var(--gr-fg)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]'\n\nexport type GrBreadcrumbsLinkComponent = string | Component\n\n/**\n * Раскладка пути: какие пункты видны и где стоит кнопка раскрытия.\n *\n * Чистая функция, потому что вся её сложность — арифметика границ, и проверять\n * её монтированием компонента дороже, чем таблицей входов.\n */\nexport type GrBreadcrumbsLayoutEntry =\n | { kind: 'item', item: GrBreadcrumbItem, index: number }\n | { kind: 'ellipsis', hiddenCount: number }\n\n/**\n * Сколько пунктов хвоста влезает в доступную ширину.\n *\n * Порог по числу пунктов (`maxItems`) на узком экране предсказывает плохо: три\n * коротких пункта влезают, два длинных — нет. Здесь решение принимается по\n * измеренным ширинам.\n *\n * Голова не ужимается: `itemsBeforeCollapse` — обычно один корневой пункт, и он\n * дёшев. Хвост ужимается до упора, но **не меньше одного**: последний пункт\n * отвечает на вопрос «где я сейчас», и прятать его бессмысленно — путь\n * превратился бы в «Главная / …».\n *\n * Возврат — число пунктов хвоста; `items.length` означает «влезло всё».\n */\nexport function resolveBreadcrumbsFit(options: {\n itemWidths: number[]\n separatorWidth: number\n ellipsisWidth: number\n available: number\n itemsBeforeCollapse: number\n /** Зазор списка (`gap`). Стоит между каждой парой соседей, включая разделители. */\n gapWidth?: number\n}): number {\n const { itemWidths, separatorWidth, ellipsisWidth, available, itemsBeforeCollapse, gapWidth = 0 } = options\n const total = itemWidths.length\n\n if (total === 0) return 0\n\n const sum = (from: number, to: number): number =>\n itemWidths.slice(from, to).reduce((acc, width) => acc + width, 0)\n\n /**\n * Ширина строки из `parts` видимых блоков: сами блоки, разделители между ними\n * и зазоры. Элементов в списке `2 * parts - 1` (блоки и разделители вперемешку),\n * значит зазоров на один меньше — без них расчёт систематически оптимистичен и\n * путь подрезается уже после схлопывания.\n */\n const rowWidth = (content: number, parts: number): number =>\n content\n + Math.max(0, parts - 1) * separatorWidth\n + Math.max(0, 2 * parts - 2) * gapWidth\n\n if (rowWidth(sum(0, total), total) <= available) return total\n\n const before = Math.max(0, Math.min(itemsBeforeCollapse, total))\n\n for (let after = total - before - 1; after > 1; after--) {\n const content = sum(0, before) + ellipsisWidth + sum(total - after, total)\n\n if (rowWidth(content, before + 1 + after) <= available) return after\n }\n\n return 1\n}\n\nexport function resolveBreadcrumbsLayout(options: {\n items: GrBreadcrumbItem[]\n maxItems?: number\n itemsBeforeCollapse: number\n itemsAfterCollapse: number\n expanded: boolean\n}): GrBreadcrumbsLayoutEntry[] {\n const { items, maxItems, itemsBeforeCollapse, itemsAfterCollapse, expanded } = options\n const all: GrBreadcrumbsLayoutEntry[] = items.map((item, index) => ({ kind: 'item', item, index }))\n\n if (expanded || !maxItems || maxItems < 1 || items.length <= maxItems)\n return all\n\n // Хвост важнее головы: «где я сейчас» читается справа, поэтому при нехватке\n // места сначала жертвуем серединой, а не концом.\n const before = Math.max(0, Math.min(itemsBeforeCollapse, items.length))\n const after = Math.max(0, Math.min(itemsAfterCollapse, items.length - before))\n const hiddenCount = items.length - before - after\n\n if (hiddenCount <= 1)\n return all\n\n return [\n ...all.slice(0, before),\n { kind: 'ellipsis', hiddenCount },\n ...all.slice(items.length - after),\n ]\n}\n","import { splitClassTokens } from '../shared/classTokens'\nimport {\n breadcrumbsCurrentClass,\n breadcrumbsEllipsisClass,\n breadcrumbsItemIconClass,\n breadcrumbsItemWrapClass,\n breadcrumbsLabelClass,\n breadcrumbsListClass,\n breadcrumbsListNowrapClass,\n breadcrumbsListWrapClass,\n breadcrumbsRootClass,\n breadcrumbsSeparatorClass,\n breadcrumbsSizeClassBySize,\n} from './grBreadcrumbsStyles'\n\n// Всё, что живёт в `grBreadcrumbsStyles.ts`: и мапа размеров, и строковые\n// литералы. Хелпер уезжает в общий `dist/chunks/`, вне области скана\n// компонента — гейт `src/__tests__/safelist.test.ts`.\nexport const grBreadcrumbsSafelist = [...new Set([\n ...Object.values(breadcrumbsSizeClassBySize).flatMap(splitClassTokens),\n ...splitClassTokens(breadcrumbsRootClass),\n ...splitClassTokens(breadcrumbsListClass),\n ...splitClassTokens(breadcrumbsListWrapClass),\n ...splitClassTokens(breadcrumbsListNowrapClass),\n ...splitClassTokens(breadcrumbsSeparatorClass),\n ...splitClassTokens(breadcrumbsCurrentClass),\n ...splitClassTokens(breadcrumbsItemIconClass),\n ...splitClassTokens(breadcrumbsItemWrapClass),\n ...splitClassTokens(breadcrumbsLabelClass),\n ...splitClassTokens(breadcrumbsEllipsisClass),\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grBreadcrumbsSafelist } from './safelist'\n\nexport const grBreadcrumbsConfig = defineGranularComponent(import.meta.url, {\n name: 'GrBreadcrumbs',\n safelist: grBreadcrumbsSafelist,\n dependencies: ['GrLink'],\n})\n"],"mappings":";;;AAsBA,IAAa,uBAAuB;AACpC,IAAa,uBAAuB;;;;;;;;;;;AAYpC,IAAa,2BAA2B;AACxC,IAAa,6BAA6B;;AAG1C,IAAa,6BAAgE;CAC3E,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAa,4BAA4B;;AAGzC,IAAa,0BAA0B;;;;;;;;;AAUvC,IAAa,2BAA2B;AAExC,IAAa,2BAA2B;AAExC,IAAa,wBAAwB;;;;;AAMrC,IAAa,2BAA2B;;;;;;;;;;;;;;;AA4BxC,SAAgB,sBAAsB,SAQ3B;CACT,MAAM,EAAE,YAAY,gBAAgB,eAAe,WAAW,qBAAqB,WAAW,MAAM;CACpG,MAAM,QAAQ,WAAW;CAEzB,IAAI,UAAU,GAAG,OAAO;CAExB,MAAM,OAAO,MAAc,OACzB,WAAW,MAAM,MAAM,EAAE,CAAC,CAAC,QAAQ,KAAK,UAAU,MAAM,OAAO,CAAC;;;;;;;CAQlE,MAAM,YAAY,SAAiB,UACjC,UACE,KAAK,IAAI,GAAG,QAAQ,CAAC,IAAI,iBACzB,KAAK,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI;CAEjC,IAAI,SAAS,IAAI,GAAG,KAAK,GAAG,KAAK,KAAK,WAAW,OAAO;CAExD,MAAM,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,qBAAqB,KAAK,CAAC;CAE/D,KAAK,IAAI,QAAQ,QAAQ,SAAS,GAAG,QAAQ,GAAG,SAG9C,IAAI,SAFY,IAAI,GAAG,MAAM,IAAI,gBAAgB,IAAI,QAAQ,OAAO,KAAK,GAEnD,SAAS,IAAI,KAAK,KAAK,WAAW,OAAO;CAGjE,OAAO;AACT;AAEA,SAAgB,yBAAyB,SAMV;CAC7B,MAAM,EAAE,OAAO,UAAU,qBAAqB,oBAAoB,aAAa;CAC/E,MAAM,MAAkC,MAAM,KAAK,MAAM,WAAW;EAAE,MAAM;EAAQ;EAAM;CAAM,EAAE;CAElG,IAAI,YAAY,CAAC,YAAY,WAAW,KAAK,MAAM,UAAU,UAC3D,OAAO;CAIT,MAAM,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,qBAAqB,MAAM,MAAM,CAAC;CACtE,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,oBAAoB,MAAM,SAAS,MAAM,CAAC;CAC7E,MAAM,cAAc,MAAM,SAAS,SAAS;CAE5C,IAAI,eAAe,GACjB,OAAO;CAET,OAAO;EACL,GAAG,IAAI,MAAM,GAAG,MAAM;EACtB;GAAE,MAAM;GAAY;EAAY;EAChC,GAAG,IAAI,MAAM,MAAM,SAAS,KAAK;CACnC;AACF;;;ACnJA,IAAa,wBAAwB,CAAC,mBAAG,IAAI,IAAI;CAC/C,GAAG,OAAO,OAAO,0BAA0B,CAAC,CAAC,QAAQ,gBAAgB;CACrE,GAAG,iBAAiB,oBAAoB;CACxC,GAAG,iBAAiB,oBAAoB;CACxC,GAAG,iBAAiB,wBAAwB;CAC5C,GAAG,iBAAiB,0BAA0B;CAC9C,GAAG,iBAAiB,yBAAyB;CAC7C,GAAG,iBAAiB,uBAAuB;CAC3C,GAAG,iBAAiB,wBAAwB;CAC5C,GAAG,iBAAiB,wBAAwB;CAC5C,GAAG,iBAAiB,qBAAqB;CACzC,GAAG,iBAAiB,wBAAwB;AAC9C,CAAC,CAAC;;;AC1BF,IAAa,sBAAsB,wBAAwB,OAAO,KAAK,KAAK;CAC1E,MAAM;CACN,UAAU;CACV,cAAc,CAAC,QAAQ;AACzB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"grDropdownMenuStyles-DG3aYHkT.js","names":[],"sources":["../../src/components/GrDropdownMenu/grDropdownMenuStyles.ts"],"sourcesContent":["export type GrDropdownMenuItemAlign = 'left' | 'center' | 'right'\nexport type GrDropdownMenuItemVariant = 'default' | 'danger'\nexport type GrDropdownMenuHeaderAlign = GrDropdownMenuItemAlign\nexport type GrDropdownMenuColumnAlign = GrDropdownMenuItemAlign\nexport type GrDropdownMenuColumnsCount = 2 | 3 | 4\n\nexport const alignClass: Record<GrDropdownMenuItemAlign, string> = {\n left: 'justify-start text-left',\n center: 'justify-center text-center',\n right: 'justify-end text-right',\n}\n\nexport const textAlignClass: Record<GrDropdownMenuHeaderAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n}\n\nexport const colsClass: Record<GrDropdownMenuColumnsCount, string> = {\n 2: 'grid-cols-2',\n 3: 'grid-cols-3',\n 4: 'grid-cols-4',\n}\n\n/**\n * Радиус здесь не украшение: фон подсветки лежит на самом пункте, а панель\n * `GrDropdown` скруглена на 16 px и содержимое не обрезает. Прямоугольник во всю\n * ширину заливал бы угловые сегменты, вырезанные этим радиусом. Восемь\n * пикселей — та же ступень, что у опций `GrSelect` и `GrAutocomplete`; внутренний\n * угол панели после рамки и поля ≈ 11 px, так что подсветка до скругления не\n * достаёт. Радиус в базовом классе, а не отдельной константой: hover, disabled и\n * кольцо фокуса висят на одном элементе.\n */\nexport const itemBaseClass = 'w-full min-h-10 px-4 py-2.5 rounded-[var(--gr-radius-md)] flex items-center gap-2 text-[length:var(--gr-text-sm)] leading-[var(--gr-leading-sm)] transition-colors duration-[var(--gr-duration-fast)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]'\n\n// Насыщенный тон как цвет текста запрещён — для текста есть `-text`-роль.\nexport const itemVariantClass: Record<GrDropdownMenuItemVariant, string> = {\n default: 'text-[var(--gr-fg)]',\n danger: 'text-[var(--gr-danger-text)]',\n}\n\nexport const itemInteractiveClass = 'cursor-pointer hover:bg-[var(--gr-accent)] hover:text-[var(--gr-accent-fg)]'\n\n// Disabled гасится фоном, а не `opacity`: прозрачность разбавляет выверенные на\n// AA токены текста. `pointer-events-none` оставлен — он же гасит hover.\nexport const itemDisabledClass = 'cursor-not-allowed pointer-events-none bg-[var(--gr-muted)] text-[var(--gr-muted-fg)]'\n\nexport const itemIndicatorClass = 'h-3.5 w-3.5 shrink-0'\nexport const itemShortcutClass = 'ml-auto pl-4 text-[length:var(--gr-text-xs)] leading-[var(--gr-leading-xs)] text-[var(--gr-muted-fg)]'\n\nexport const headerClass = 'px-4 py-2 text-[length:var(--gr-text-xs)] leading-[var(--gr-leading-xs)] tracking-wide text-[var(--gr-muted-fg)]'\n\nexport const listBaseClass = 'w-full'\nexport const dividersClass = 'divide-y divide-[var(--gr-brd)]'\nexport const borderTopClass = 'border-t border-[var(--gr-brd)]'\nexport const borderBottomClass = 'border-b border-[var(--gr-brd)]'\n\nexport const columnsBaseClass = 'w-full grid divide-x divide-[var(--gr-brd)]'\nexport const columnBaseClass = 'px-3 py-2 flex items-center'\n\nexport const dividerClass = 'border-t border-[var(--gr-brd)]'\nexport const dividerInsetClass = 'mx-2'\n\nexport function grDropdownMenuItemClass(options: {\n align: GrDropdownMenuItemAlign\n variant: GrDropdownMenuItemVariant\n disabled: boolean\n}): string {\n return [\n itemBaseClass,\n alignClass[options.align],\n options.disabled ? itemDisabledClass : itemVariantClass[options.variant],\n options.disabled ? '' : itemInteractiveClass,\n ].filter(Boolean).join(' ')\n}\n\nexport function grDropdownMenuListClass(options: {\n dividers: boolean\n borderTop: boolean\n borderBottom: boolean\n}): string {\n return [\n listBaseClass,\n options.dividers ? dividersClass : '',\n options.borderTop ? borderTopClass : '',\n options.borderBottom ? borderBottomClass : '',\n ].filter(Boolean).join(' ')\n}\n"],"mappings":";AAMA,IAAa,aAAsD;CACjE,MAAM;CACN,QAAQ;CACR,OAAO;AACT;AAEA,IAAa,iBAA4D;CACvE,MAAM;CACN,QAAQ;CACR,OAAO;AACT;AAEA,IAAa,YAAwD;CACnE,GAAG;CACH,GAAG;CACH,GAAG;AACL;;;;;;;;;;AAWA,IAAa,gBAAgB;AAG7B,IAAa,mBAA8D;CACzE,SAAS;CACT,QAAQ;AACV;AAEA,IAAa,uBAAuB;AAIpC,IAAa,oBAAoB;AAEjC,IAAa,qBAAqB;AAClC,IAAa,oBAAoB;AAEjC,IAAa,cAAc;AAE3B,IAAa,gBAAgB;AAC7B,IAAa,gBAAgB;AAC7B,IAAa,iBAAiB;AAC9B,IAAa,oBAAoB;AAEjC,IAAa,mBAAmB;AAChC,IAAa,kBAAkB;AAE/B,IAAa,eAAe;AAC5B,IAAa,oBAAoB;AAEjC,SAAgB,wBAAwB,SAI7B;CACT,OAAO;EACL;EACA,WAAW,QAAQ;EACnB,QAAQ,WAAW,oBAAoB,iBAAiB,QAAQ;EAChE,QAAQ,WAAW,KAAK;CAC1B,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AAC5B;AAEA,SAAgB,wBAAwB,SAI7B;CACT,OAAO;EACL;EACA,QAAQ,WAAW,gBAAgB;EACnC,QAAQ,YAAY,iBAAiB;EACrC,QAAQ,eAAe,oBAAoB;CAC7C,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AAC5B"}
|