@feugene/granularity 0.33.0 → 0.34.1
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-uzUuosv7.js → config-CT4lP6S4.js} +6 -5
- package/dist/chunks/config-CT4lP6S4.js.map +1 -0
- package/dist/chunks/{config-vYMJ3Cr1.js → config-CYthTVK2.js} +2 -2
- package/dist/chunks/config-CYthTVK2.js.map +1 -0
- package/dist/chunks/{config-CPSxM7XE.js → config-CsCUuukB.js} +1 -0
- package/dist/chunks/config-CsCUuukB.js.map +1 -0
- package/dist/chunks/{config-DnF472Ox.js → config-DOYz_SVK.js} +2 -2
- package/dist/chunks/{config-DnF472Ox.js.map → config-DOYz_SVK.js.map} +1 -1
- package/dist/chunks/{config-T3-DMXYm.js → config-DUNH02Fg.js} +2 -2
- package/dist/chunks/config-DUNH02Fg.js.map +1 -0
- package/dist/chunks/{config-BTwYMQaz2.js → config-DVCNvhIG2.js} +4 -3
- package/dist/chunks/config-DVCNvhIG2.js.map +1 -0
- package/dist/chunks/{generated-CSyPsWtM.js → generated-Bk-f6NsN.js} +21 -0
- package/dist/chunks/{generated-CSyPsWtM.js.map → generated-Bk-f6NsN.js.map} +1 -1
- package/dist/chunks/grDropdownStyles-DLToHWMX.js +5 -0
- package/dist/chunks/grDropdownStyles-DLToHWMX.js.map +1 -0
- package/dist/chunks/grPopoverStyles-CYAeO3Ov.js +110 -0
- package/dist/chunks/grPopoverStyles-CYAeO3Ov.js.map +1 -0
- package/dist/chunks/{grSelectStyles-Cdtd10eY.js → grSelectStyles-D9EQ-pgK.js} +2 -1
- package/dist/chunks/grSelectStyles-D9EQ-pgK.js.map +1 -0
- package/dist/chunks/{granular-provider-CrQua8PT.js → granular-provider-BAy4APOX.js} +6 -6
- package/dist/chunks/{granular-provider-CrQua8PT.js.map → granular-provider-BAy4APOX.js.map} +1 -1
- package/dist/chunks/{overlayTransition-0Fj5tQbq.js → overlayPanelSurface-BKeMhRx4.js} +24 -1
- package/dist/chunks/overlayPanelSurface-BKeMhRx4.js.map +1 -0
- package/dist/chunks/{focusables-BkzK42SQ.js → useFocusTrap-D9bIPNF6.js} +123 -1
- package/dist/chunks/useFocusTrap-D9bIPNF6.js.map +1 -0
- package/dist/chunks/{useMenuItemsFocus-B6TldmGf.js → useMenuItemsFocus-B7Bl_aFA.js} +1 -1
- package/dist/chunks/{useMenuItemsFocus-B6TldmGf.js.map → useMenuItemsFocus-B7Bl_aFA.js.map} +1 -1
- package/dist/chunks/{useModalOverlay-D__CqLGn.js → useModalOverlay-BnAGZpcI.js} +1 -1
- package/dist/chunks/{useModalOverlay-D__CqLGn.js.map → useModalOverlay-BnAGZpcI.js.map} +1 -1
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-CoQjEF8h.js → GrAutocomplete-BQsSE7sj.js} +2 -2
- package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-CoQjEF8h.js.map → GrAutocomplete-BQsSE7sj.js.map} +1 -1
- package/dist/components/GrAutocomplete/index.js +2 -2
- package/dist/components/GrColorPicker/chunks/{GrColorPicker-p2XH_8cE.js → GrColorPicker-CIgdPXHn.js} +2 -1
- package/dist/components/GrColorPicker/chunks/GrColorPicker-CIgdPXHn.js.map +1 -0
- package/dist/components/GrColorPicker/index.js +1 -1
- package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-BXbh3q7O.js → GrCommandPalette-BZHUKlux.js} +1 -1
- package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-BXbh3q7O.js.map → GrCommandPalette-BZHUKlux.js.map} +1 -1
- package/dist/components/GrCommandPalette/index.js +1 -1
- package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-CUP43q__.js → GrConfirmDialog-jRDs_E6C.js} +1 -1
- package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-CUP43q__.js.map → GrConfirmDialog-jRDs_E6C.js.map} +1 -1
- package/dist/components/GrConfirmDialog/index.js +1 -1
- package/dist/components/GrContextMenu/chunks/{GrContextMenu-ClkVjdcP.js → GrContextMenu-DlFWm0eW.js} +17 -3
- package/dist/components/GrContextMenu/chunks/GrContextMenu-DlFWm0eW.js.map +1 -0
- package/dist/components/GrContextMenu/index.js +2 -2
- package/dist/components/GrDialog/chunks/{GrDialog-BiMJ9_T4.js → GrDialog-C01Hhk6G.js} +1 -1
- package/dist/components/GrDialog/chunks/{GrDialog-BiMJ9_T4.js.map → GrDialog-C01Hhk6G.js.map} +1 -1
- package/dist/components/GrDialog/index.js +1 -1
- package/dist/components/GrDialogService/chunks/{GrDialogService-BxNK6crD.js → GrDialogService-CmsJNUmM.js} +7 -2
- package/dist/components/GrDialogService/chunks/{GrDialogService-BxNK6crD.js.map → GrDialogService-CmsJNUmM.js.map} +1 -1
- package/dist/components/GrDialogService/index.js +1 -1
- package/dist/components/GrDrawer/chunks/{GrDrawer-Ce2l3zaG.js → GrDrawer-xfoy-MCj.js} +1 -1
- package/dist/components/GrDrawer/chunks/{GrDrawer-Ce2l3zaG.js.map → GrDrawer-xfoy-MCj.js.map} +1 -1
- package/dist/components/GrDrawer/index.js +1 -1
- package/dist/components/GrDropdown/chunks/GrDropdown-7r772-Cq.js +180 -0
- package/dist/components/GrDropdown/chunks/GrDropdown-7r772-Cq.js.map +1 -0
- package/dist/components/GrDropdown/index.js +2 -2
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-GOzuAXsi.js → GrDropdownMenu-DNurbsWc.js} +1 -1
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-GOzuAXsi.js.map → GrDropdownMenu-DNurbsWc.js.map} +1 -1
- package/dist/components/GrDropdownMenu/index.js +1 -1
- package/dist/components/GrFileUpload/chunks/{GrFileUpload-NsHkRRIa.js → GrFileUpload-LL8RZvC0.js} +10 -0
- package/dist/components/GrFileUpload/chunks/GrFileUpload-LL8RZvC0.js.map +1 -0
- package/dist/components/GrFileUpload/index.js +1 -1
- package/dist/components/GrImageViewer/chunks/{GrImageViewer-CG4vUBg_.js → GrImageViewer--BU8yrfx.js} +1 -1
- package/dist/components/GrImageViewer/chunks/{GrImageViewer-CG4vUBg_.js.map → GrImageViewer--BU8yrfx.js.map} +1 -1
- package/dist/components/GrImageViewer/index.js +1 -1
- package/dist/components/GrModal/chunks/{GrModal-D0mf1SAx.js → GrModal-_JrDhon-.js} +1 -1
- package/dist/components/GrModal/chunks/{GrModal-D0mf1SAx.js.map → GrModal-_JrDhon-.js.map} +1 -1
- package/dist/components/GrModal/index.js +1 -1
- package/dist/components/GrPagination/chunks/{GrPagination-FiiXzVyv.js → GrPagination-gBoWVHk6.js} +1 -1
- package/dist/components/GrPagination/chunks/{GrPagination-FiiXzVyv.js.map → GrPagination-gBoWVHk6.js.map} +1 -1
- package/dist/components/GrPagination/index.js +1 -1
- package/dist/components/GrPopover/chunks/{GrPopover-faJanmGs.js → GrPopover-DEFxDffj.js} +87 -13
- package/dist/components/GrPopover/chunks/GrPopover-DEFxDffj.js.map +1 -0
- package/dist/components/GrPopover/index.js +2 -2
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-C6QGC7QJ.js → GrPromptDialog-CailXSqW.js} +1 -1
- package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-C6QGC7QJ.js.map → GrPromptDialog-CailXSqW.js.map} +1 -1
- package/dist/components/GrPromptDialog/index.js +1 -1
- package/dist/components/GrSelect/chunks/{GrSelect-Dt8iqruc.js → GrSelect-CZqV1Eg4.js} +2 -2
- package/dist/components/GrSelect/chunks/{GrSelect-Dt8iqruc.js.map → GrSelect-CZqV1Eg4.js.map} +1 -1
- package/dist/components/GrSelect/index.js +2 -2
- package/dist/components/GrTabs/chunks/{GrTabs-ugDnkk-2.js → GrTabs-UsO4j8zv.js} +5 -0
- package/dist/components/GrTabs/chunks/GrTabs-UsO4j8zv.js.map +1 -0
- package/dist/components/GrTabs/index.js +1 -1
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-BHwgGJcT.js → GrTreeSelect-DOXcpWq2.js} +2 -2
- package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-BHwgGJcT.js.map → GrTreeSelect-DOXcpWq2.js.map} +1 -1
- package/dist/components/GrTreeSelect/index.js +2 -2
- package/dist/composables/useFloating.js +31 -11
- package/dist/composables/useFloating.js.map +1 -1
- package/dist/composables/useFocusTrap.js +1 -123
- package/dist/granular-provider-node.js +1 -1
- package/dist/granular-provider.js +1 -1
- package/dist/index.js +26 -26
- package/dist/theme.js +1 -1
- package/dist/tokens.js +1 -1
- package/dist/types/components/GrAutocomplete/grAutocompleteStyles.d.ts +1 -1
- package/dist/types/components/GrDropdown/GrDropdown.vue.d.ts +5 -5
- package/dist/types/components/GrDropdown/grDropdownStyles.d.ts +8 -2
- package/dist/types/components/GrDropdownMenu/GrDropdownMenu.vue.d.ts +2 -2
- package/dist/types/components/GrPopover/GrPopover.vue.d.ts +54 -4
- package/dist/types/components/GrPopover/grPopoverStyles.d.ts +38 -11
- package/dist/types/components/GrSelect/grSelectStyles.d.ts +1 -1
- package/dist/types/components/GrTreeSelect/grTreeSelectStyles.d.ts +1 -1
- package/dist/types/components/shared/overlayOrigin.d.ts +22 -0
- package/dist/types/components/shared/overlayPanelSurface.d.ts +21 -0
- package/dist/types/composables/useFloating.d.ts +15 -0
- package/dist/web-types.json +40 -4
- package/package.json +1 -1
- package/dist/chunks/config-BTwYMQaz2.js.map +0 -1
- package/dist/chunks/config-CPSxM7XE.js.map +0 -1
- package/dist/chunks/config-T3-DMXYm.js.map +0 -1
- package/dist/chunks/config-uzUuosv7.js.map +0 -1
- package/dist/chunks/config-vYMJ3Cr1.js.map +0 -1
- package/dist/chunks/focusables-BkzK42SQ.js.map +0 -1
- package/dist/chunks/grDropdownStyles-V7TRiCXn.js +0 -24
- package/dist/chunks/grDropdownStyles-V7TRiCXn.js.map +0 -1
- package/dist/chunks/grPopoverStyles-Djh5RNhn.js +0 -59
- package/dist/chunks/grPopoverStyles-Djh5RNhn.js.map +0 -1
- package/dist/chunks/grSelectStyles-Cdtd10eY.js.map +0 -1
- package/dist/chunks/overlayTransition-0Fj5tQbq.js.map +0 -1
- package/dist/components/GrColorPicker/chunks/GrColorPicker-p2XH_8cE.js.map +0 -1
- package/dist/components/GrContextMenu/chunks/GrContextMenu-ClkVjdcP.js.map +0 -1
- package/dist/components/GrDropdown/chunks/GrDropdown-13Wt9eB_.js +0 -239
- package/dist/components/GrDropdown/chunks/GrDropdown-13Wt9eB_.js.map +0 -1
- package/dist/components/GrFileUpload/chunks/GrFileUpload-NsHkRRIa.js.map +0 -1
- package/dist/components/GrPopover/chunks/GrPopover-faJanmGs.js.map +0 -1
- package/dist/components/GrTabs/chunks/GrTabs-ugDnkk-2.js.map +0 -1
- package/dist/composables/useFocusTrap.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFloating.js","names":[],"sources":["../../src/composables/useFloating.ts"],"sourcesContent":["import type { CSSProperties, Ref } from 'vue'\nimport type { Middleware, Placement, VirtualElement } from '@floating-ui/dom'\nimport { autoUpdate, computePosition, flip, offset as offsetMiddleware, shift, size as sizeMiddleware } from '@floating-ui/dom'\nimport { nextTick, onBeforeUnmount, ref, watch } from 'vue'\n\nimport { floatingLayerZIndex } from './internal/overlayStack'\n\nexport type UseFloatingPlacement = Placement\n\n/**\n * Device pixel ratio плавающего элемента. Нужен, чтобы округлять координаты к сетке\n * физических пикселей (см. `roundByDPR`) — иначе субпиксельные `left/top` дают размытый\n * текст/границы панели на не-целочисленных позициях и HiDPI-экранах. Подход перенят у\n * официального `@floating-ui/vue` (`useFloating` → `roundByDPR`), чтобы не тянуть весь\n * пакет ради одной утилиты.\n */\nfunction getDpr(element: HTMLElement): number {\n if (typeof window === 'undefined')\n return 1\n\n const win = element.ownerDocument?.defaultView ?? window\n return win.devicePixelRatio || 1\n}\n\nfunction roundByDpr(element: HTMLElement, value: number): number {\n const dpr = getDpr(element)\n return Math.round(value * dpr) / dpr\n}\n\n/**\n * Прямоугольник в координатах вьюпорта — якорь, которого нет в DOM.\n *\n * Точка курсора описывается прямоугольником `0×0`. Размеры необязательны именно\n * поэтому: контекстное меню, открытое с клавиатуры, встаёт у **прямоугольника**\n * сфокусированной строки, а не у её угла, и переворачивается вместе с ней.\n */\nexport interface GrFloatingAnchorRect {\n x: number\n y: number\n /** По умолчанию 0. */\n width?: number\n /** По умолчанию 0. */\n height?: number\n}\n\n/** Ссылка позиционирования: элемент, виртуальный якорь или ничего. */\nexport type UseFloatingReference = HTMLElement | VirtualElement | null\n\n/**\n * Виртуальный якорь: объект создаётся один раз, координаты читает геттер на\n * каждом измерении.\n *\n * Стабильность объекта здесь не стилистика, а условие работы: `useFloating`\n * пересоздаёт подписку `autoUpdate` при смене самой ссылки, поэтому новый объект\n * на каждое движение курсора рвал бы и заводил её заново. С одним объектом смена\n * точки — это просто `update()`.\n */\nexport function createFloatingAnchor(\n get: () => GrFloatingAnchorRect | null | undefined,\n options: { contextElement?: () => Element | null | undefined } = {},\n): VirtualElement {\n return {\n getBoundingClientRect() {\n const rect = get() ?? { x: 0, y: 0 }\n const width = rect.width ?? 0\n const height = rect.height ?? 0\n\n return {\n x: rect.x,\n y: rect.y,\n width,\n height,\n top: rect.y,\n left: rect.x,\n right: rect.x + width,\n bottom: rect.y + height,\n }\n },\n get contextElement() {\n return options.contextElement?.() ?? undefined\n },\n }\n}\n\nexport interface UseFloatingOptions {\n /**\n * Предпочитаемое место панели относительно триггера. По умолчанию `bottom-start`.\n * Можно передать функцию-геттер, если место зависит от реактивного пропа\n * (например, `align`) — она вызывается заново при каждом пересчёте позиции.\n */\n placement?: UseFloatingPlacement | (() => UseFloatingPlacement)\n /** Зазор между триггером и панелью, px. По умолчанию `8`. */\n offsetPx?: number\n /** Минимальный отступ от края viewport при flip/shift, px. По умолчанию `8`. */\n boundaryPadding?: number\n /**\n * Согласовать ширину панели с шириной триггера (актуально для Select/TreeSelect).\n * Не годится для Dropdown/Tooltip, где ширина панели определяется контентом.\n * - `true` — точная ширина (`width = ширина триггера`);\n * - `'min'` — панель растёт по контенту (`width: max-content`), но не уже триггера\n * (`min-width = ширина триггера`) — режим `GrSelect view=\"link\"`;\n * - функция-геттер — как и `placement`, для реактивной зависимости от пропа.\n *\n * С виртуальным якорем не работает: ширина точки равна нулю.\n */\n matchWidth?: boolean | 'min' | (() => boolean | 'min')\n /**\n * CSS-переменная шкалы слоёв (см. `styles/tokens.css`). По умолчанию\n * `--gr-z-dropdown`. Действует, пока панель открыта вне модального окна: над\n * окном высоту задаёт стек слоёв (см. {@link floatingZIndex}).\n */\n zIndexVar?: string\n}\n\nexport interface UseFloatingReturn {\n /** Готовый объект для `:style` на плавающем элементе. */\n floatingStyle: Ref<CSSProperties>\n /**\n * Итоговое место панели ПОСЛЕ применения `flip` — может отличаться от запрошенного\n * `placement`, если места не хватило и панель перевернуло на противоположную сторону.\n * Полезно для выбора `transform-origin`/направления transition в потребителе.\n */\n resolvedPlacement: Ref<Placement>\n /** Принудительный пересчёт позиции (например, после изменения контента панели). */\n update: () => void\n}\n\n/**\n * Единый движок позиционирования floating-панелей (Dropdown/Select/TreeSelect/Tooltip)\n * поверх `@floating-ui/dom`: flip (переворот при нехватке места), shift (клэмп к границам\n * viewport), опциональный `size`-мидлвар для растягивания по ширине триггера.\n *\n * Пересчёт положения при скролле/ресайзе делает `autoUpdate` из `@floating-ui/dom` —\n * он сам использует `ResizeObserver`/`IntersectionObserver` и пассивные слушатели вместо\n * наивного враппера на каждый `scroll`/`resize`, поэтому отдельный rAF-throttling здесь\n * не нужен (в отличие от прежней ручной реализации в `GrSelect`/`GrDropdown`).\n *\n * Требует, чтобы `floatingEl` был примонтирован в DOM на момент открытия (обычно —\n * `<teleport to=\"body\">` + `v-show`, а не `v-if`): позиционирование не может измерить\n * элемент, которого нет в дереве.\n */\nexport function useFloating(\n // Объединение, а не `Ref<HTMLElement | VirtualElement | null>`: аксессорный\n // `Ref` проверяется контравариантно по записи, и расширение элементного типа\n // отняло бы у шести нынешних потребителей право передавать свой `Ref` как есть.\n reference: Ref<HTMLElement | null> | (() => UseFloatingReference),\n floatingEl: Ref<HTMLElement | null>,\n open: Ref<boolean>,\n options: UseFloatingOptions = {},\n): UseFloatingReturn {\n const readReference: () => UseFloatingReference\n = typeof reference === 'function' ? reference : () => reference.value\n\n const floatingStyle = ref<CSSProperties>({\n position: 'fixed',\n top: '0px',\n left: '0px',\n })\n function resolveRequestedPlacement(): Placement {\n return typeof options.placement === 'function' ? options.placement() : options.placement ?? 'bottom-start'\n }\n\n function resolveMatchWidth(): boolean | 'min' {\n return typeof options.matchWidth === 'function' ? options.matchWidth() : options.matchWidth ?? false\n }\n\n const resolvedPlacement = ref<Placement>(resolveRequestedPlacement())\n\n let stopAutoUpdate: (() => void) | null = null\n\n async function update(): Promise<void> {\n const reference = readReference()\n const floating = floatingEl.value\n if (!reference || !floating)\n return\n\n const middleware: Middleware[] = [\n offsetMiddleware(options.offsetPx ?? 8),\n flip({ padding: options.boundaryPadding ?? 8 }),\n shift({ padding: options.boundaryPadding ?? 8 }),\n ]\n\n const matchWidth = resolveMatchWidth()\n if (matchWidth) {\n middleware.push(\n sizeMiddleware({\n apply({ rects, elements }) {\n if (matchWidth === 'min') {\n Object.assign(elements.floating.style, {\n width: 'max-content',\n minWidth: `${rects.reference.width}px`,\n })\n return\n }\n\n Object.assign(elements.floating.style, {\n width: `${rects.reference.width}px`,\n minWidth: '',\n })\n },\n }),\n )\n }\n\n const { x, y, placement } = await computePosition(reference, floating, {\n placement: resolveRequestedPlacement(),\n strategy: 'fixed',\n middleware,\n })\n\n resolvedPlacement.value = placement\n floatingStyle.value = {\n position: 'fixed',\n left: `${roundByDpr(floating, x)}px`,\n top: `${roundByDpr(floating, y)}px`,\n zIndex: floatingLayerZIndex(options.zIndexVar ?? '--gr-z-dropdown'),\n }\n }\n\n function stop(): void {\n stopAutoUpdate?.()\n stopAutoUpdate = null\n }\n\n function start(): void {\n stop()\n const reference = readReference()\n const floating = floatingEl.value\n if (!reference || !floating)\n return\n\n // `autoUpdate` подписывается на `ResizeObserver`/`IntersectionObserver` для\n // последующих пересчётов, но не гарантирует немедленный вызов `update` —\n // особенно в средах без этих API (например, jsdom в тестах). Считаем позицию\n // сразу, чтобы панель не «мигала» в 0,0 до первого scroll/resize.\n void update()\n stopAutoUpdate = autoUpdate(reference, floating, () => void update())\n }\n\n // На какую ссылку подписан текущий `autoUpdate`. Отличает смену самого якоря\n // (подписку пересоздать) от смены его координат (достаточно `update()`): у\n // виртуального якоря объект один на всё время жизни.\n let subscribedTo: UseFloatingReference = null\n\n watch(\n [open, () => readReference()],\n ([isOpen, nextReference]) => {\n if (!isOpen || !nextReference) {\n stop()\n subscribedTo = null\n return\n }\n\n if (nextReference === subscribedTo && stopAutoUpdate)\n return\n\n // `floatingEl` монтируется в том же тике, что и `open` переключается\n // (v-show уже в DOM, но teleport/переход могут ещё не отработать) —\n // ждём тик, чтобы `getBoundingClientRect` не читал нулевые размеры.\n // Перепроверка `open`: панель могли закрыть, пока `start()` ждал в\n // очереди, — `stop()` уже отработал, и снимать подписку было бы некому.\n void nextTick(() => {\n if (!open.value)\n return\n subscribedTo = readReference()\n start()\n })\n },\n { immediate: true },\n )\n\n onBeforeUnmount(stop)\n\n return {\n floatingStyle,\n resolvedPlacement,\n update: () => void update(),\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useFloating.js","names":[],"sources":["../../src/composables/useFloating.ts"],"sourcesContent":["import type { CSSProperties, Ref } from 'vue'\nimport type { Middleware, Placement, VirtualElement } from '@floating-ui/dom'\nimport { autoUpdate, computePosition, flip, offset as offsetMiddleware, shift, size as sizeMiddleware } from '@floating-ui/dom'\nimport { nextTick, onBeforeUnmount, ref, watch } from 'vue'\n\nimport { floatingLayerZIndex } from './internal/overlayStack'\n\nexport type UseFloatingPlacement = Placement\n\n/**\n * Кастомное свойство, в которое слой пишет доступное место по вертикали —\n * расстояние от панели до края вьюпорта на той стороне, куда её в итоге\n * поставило.\n *\n * Свойство ставится на сам плавающий элемент при каждом пересчёте позиции, в\n * том числе на скролле и ресайзе. Слой **сообщает замер, а не применяет его**:\n * ограничивать ли себя этим числом и что при этом скроллить — решает панель,\n * потому что скролл принадлежит её содержимому.\n *\n * Ширину так публиковать незачем: её потолок статичен (`calc(100vw - 1rem)`) и\n * замера не требует. Высота статичной быть не может — доступное место зависит\n * от того, где стоит триггер.\n */\nexport const floatingAvailableHeightVar = '--gr-floating-available-height'\n\n/**\n * Device pixel ratio плавающего элемента. Нужен, чтобы округлять координаты к сетке\n * физических пикселей (см. `roundByDPR`) — иначе субпиксельные `left/top` дают размытый\n * текст/границы панели на не-целочисленных позициях и HiDPI-экранах. Подход перенят у\n * официального `@floating-ui/vue` (`useFloating` → `roundByDPR`), чтобы не тянуть весь\n * пакет ради одной утилиты.\n */\nfunction getDpr(element: HTMLElement): number {\n if (typeof window === 'undefined')\n return 1\n\n const win = element.ownerDocument?.defaultView ?? window\n return win.devicePixelRatio || 1\n}\n\nfunction roundByDpr(element: HTMLElement, value: number): number {\n const dpr = getDpr(element)\n return Math.round(value * dpr) / dpr\n}\n\n/**\n * Прямоугольник в координатах вьюпорта — якорь, которого нет в DOM.\n *\n * Точка курсора описывается прямоугольником `0×0`. Размеры необязательны именно\n * поэтому: контекстное меню, открытое с клавиатуры, встаёт у **прямоугольника**\n * сфокусированной строки, а не у её угла, и переворачивается вместе с ней.\n */\nexport interface GrFloatingAnchorRect {\n x: number\n y: number\n /** По умолчанию 0. */\n width?: number\n /** По умолчанию 0. */\n height?: number\n}\n\n/** Ссылка позиционирования: элемент, виртуальный якорь или ничего. */\nexport type UseFloatingReference = HTMLElement | VirtualElement | null\n\n/**\n * Виртуальный якорь: объект создаётся один раз, координаты читает геттер на\n * каждом измерении.\n *\n * Стабильность объекта здесь не стилистика, а условие работы: `useFloating`\n * пересоздаёт подписку `autoUpdate` при смене самой ссылки, поэтому новый объект\n * на каждое движение курсора рвал бы и заводил её заново. С одним объектом смена\n * точки — это просто `update()`.\n */\nexport function createFloatingAnchor(\n get: () => GrFloatingAnchorRect | null | undefined,\n options: { contextElement?: () => Element | null | undefined } = {},\n): VirtualElement {\n return {\n getBoundingClientRect() {\n const rect = get() ?? { x: 0, y: 0 }\n const width = rect.width ?? 0\n const height = rect.height ?? 0\n\n return {\n x: rect.x,\n y: rect.y,\n width,\n height,\n top: rect.y,\n left: rect.x,\n right: rect.x + width,\n bottom: rect.y + height,\n }\n },\n get contextElement() {\n return options.contextElement?.() ?? undefined\n },\n }\n}\n\nexport interface UseFloatingOptions {\n /**\n * Предпочитаемое место панели относительно триггера. По умолчанию `bottom-start`.\n * Можно передать функцию-геттер, если место зависит от реактивного пропа\n * (например, `align`) — она вызывается заново при каждом пересчёте позиции.\n */\n placement?: UseFloatingPlacement | (() => UseFloatingPlacement)\n /** Зазор между триггером и панелью, px. По умолчанию `8`. */\n offsetPx?: number\n /** Минимальный отступ от края viewport при flip/shift, px. По умолчанию `8`. */\n boundaryPadding?: number\n /**\n * Согласовать ширину панели с шириной триггера (актуально для Select/TreeSelect).\n * Не годится для Dropdown/Tooltip, где ширина панели определяется контентом.\n * - `true` — точная ширина (`width = ширина триггера`);\n * - `'min'` — панель растёт по контенту (`width: max-content`), но не уже триггера\n * (`min-width = ширина триггера`) — режим `GrSelect view=\"link\"`;\n * - функция-геттер — как и `placement`, для реактивной зависимости от пропа.\n *\n * С виртуальным якорем не работает: ширина точки равна нулю.\n */\n matchWidth?: boolean | 'min' | (() => boolean | 'min')\n /**\n * CSS-переменная шкалы слоёв (см. `styles/tokens.css`). По умолчанию\n * `--gr-z-dropdown`. Действует, пока панель открыта вне модального окна: над\n * окном высоту задаёт стек слоёв (см. {@link floatingZIndex}).\n */\n zIndexVar?: string\n}\n\nexport interface UseFloatingReturn {\n /** Готовый объект для `:style` на плавающем элементе. */\n floatingStyle: Ref<CSSProperties>\n /**\n * Итоговое место панели ПОСЛЕ применения `flip` — может отличаться от запрошенного\n * `placement`, если места не хватило и панель перевернуло на противоположную сторону.\n * Полезно для выбора `transform-origin`/направления transition в потребителе.\n */\n resolvedPlacement: Ref<Placement>\n /** Принудительный пересчёт позиции (например, после изменения контента панели). */\n update: () => void\n}\n\n/**\n * Единый движок позиционирования floating-панелей (Dropdown/Select/TreeSelect/Tooltip)\n * поверх `@floating-ui/dom`: flip (переворот при нехватке места), shift (клэмп к границам\n * viewport), опциональный `size`-мидлвар для растягивания по ширине триггера.\n *\n * Пересчёт положения при скролле/ресайзе делает `autoUpdate` из `@floating-ui/dom` —\n * он сам использует `ResizeObserver`/`IntersectionObserver` и пассивные слушатели вместо\n * наивного враппера на каждый `scroll`/`resize`, поэтому отдельный rAF-throttling здесь\n * не нужен (в отличие от прежней ручной реализации в `GrSelect`/`GrDropdown`).\n *\n * Требует, чтобы `floatingEl` был примонтирован в DOM на момент открытия (обычно —\n * `<teleport to=\"body\">` + `v-show`, а не `v-if`): позиционирование не может измерить\n * элемент, которого нет в дереве.\n */\nexport function useFloating(\n // Объединение, а не `Ref<HTMLElement | VirtualElement | null>`: аксессорный\n // `Ref` проверяется контравариантно по записи, и расширение элементного типа\n // отняло бы у шести нынешних потребителей право передавать свой `Ref` как есть.\n reference: Ref<HTMLElement | null> | (() => UseFloatingReference),\n floatingEl: Ref<HTMLElement | null>,\n open: Ref<boolean>,\n options: UseFloatingOptions = {},\n): UseFloatingReturn {\n const readReference: () => UseFloatingReference\n = typeof reference === 'function' ? reference : () => reference.value\n\n const floatingStyle = ref<CSSProperties>({\n position: 'fixed',\n top: '0px',\n left: '0px',\n })\n function resolveRequestedPlacement(): Placement {\n return typeof options.placement === 'function' ? options.placement() : options.placement ?? 'bottom-start'\n }\n\n function resolveMatchWidth(): boolean | 'min' {\n return typeof options.matchWidth === 'function' ? options.matchWidth() : options.matchWidth ?? false\n }\n\n const resolvedPlacement = ref<Placement>(resolveRequestedPlacement())\n\n let stopAutoUpdate: (() => void) | null = null\n\n async function update(): Promise<void> {\n const reference = readReference()\n const floating = floatingEl.value\n if (!reference || !floating)\n return\n\n const middleware: Middleware[] = [\n offsetMiddleware(options.offsetPx ?? 8),\n flip({ padding: options.boundaryPadding ?? 8 }),\n shift({ padding: options.boundaryPadding ?? 8 }),\n ]\n\n const matchWidth = resolveMatchWidth()\n middleware.push(\n sizeMiddleware({\n padding: options.boundaryPadding ?? 8,\n apply({ rects, elements, availableHeight }) {\n // Сколько места осталось до края вьюпорта на той стороне, куда панель\n // в итоге встала. Считается после `flip`, поэтому сторона уже\n // окончательная. Слой только сообщает замер — решает панель.\n elements.floating.style.setProperty(\n floatingAvailableHeightVar,\n `${Math.max(0, Math.round(availableHeight))}px`,\n )\n\n if (!matchWidth)\n return\n\n if (matchWidth === 'min') {\n Object.assign(elements.floating.style, {\n width: 'max-content',\n minWidth: `${rects.reference.width}px`,\n })\n return\n }\n\n Object.assign(elements.floating.style, {\n width: `${rects.reference.width}px`,\n minWidth: '',\n })\n },\n }),\n )\n\n const { x, y, placement } = await computePosition(reference, floating, {\n placement: resolveRequestedPlacement(),\n strategy: 'fixed',\n middleware,\n })\n\n resolvedPlacement.value = placement\n floatingStyle.value = {\n position: 'fixed',\n left: `${roundByDpr(floating, x)}px`,\n top: `${roundByDpr(floating, y)}px`,\n zIndex: floatingLayerZIndex(options.zIndexVar ?? '--gr-z-dropdown'),\n }\n }\n\n function stop(): void {\n stopAutoUpdate?.()\n stopAutoUpdate = null\n }\n\n function start(): void {\n stop()\n const reference = readReference()\n const floating = floatingEl.value\n if (!reference || !floating)\n return\n\n // `autoUpdate` подписывается на `ResizeObserver`/`IntersectionObserver` для\n // последующих пересчётов, но не гарантирует немедленный вызов `update` —\n // особенно в средах без этих API (например, jsdom в тестах). Считаем позицию\n // сразу, чтобы панель не «мигала» в 0,0 до первого scroll/resize.\n void update()\n stopAutoUpdate = autoUpdate(reference, floating, () => void update())\n }\n\n // На какую ссылку подписан текущий `autoUpdate`. Отличает смену самого якоря\n // (подписку пересоздать) от смены его координат (достаточно `update()`): у\n // виртуального якоря объект один на всё время жизни.\n let subscribedTo: UseFloatingReference = null\n\n watch(\n [open, () => readReference()],\n ([isOpen, nextReference]) => {\n if (!isOpen || !nextReference) {\n stop()\n subscribedTo = null\n return\n }\n\n if (nextReference === subscribedTo && stopAutoUpdate)\n return\n\n // `floatingEl` монтируется в том же тике, что и `open` переключается\n // (v-show уже в DOM, но teleport/переход могут ещё не отработать) —\n // ждём тик, чтобы `getBoundingClientRect` не читал нулевые размеры.\n // Перепроверка `open`: панель могли закрыть, пока `start()` ждал в\n // очереди, — `stop()` уже отработал, и снимать подписку было бы некому.\n void nextTick(() => {\n if (!open.value)\n return\n subscribedTo = readReference()\n start()\n })\n },\n { immediate: true },\n )\n\n onBeforeUnmount(stop)\n\n return {\n floatingStyle,\n resolvedPlacement,\n update: () => void update(),\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,124 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { nextTick, onScopeDispose, watch } from "vue";
|
|
3
|
-
//#region src/composables/useFocusTrap.ts
|
|
4
|
-
/**
|
|
5
|
-
* Ловушка фокуса: пока активна, Tab ходит по кругу внутри слоя, а фокус,
|
|
6
|
-
* утёкший наружу, возвращается обратно.
|
|
7
|
-
*
|
|
8
|
-
* Реализована на `keydown` и `focusin`, **без sentinel-узлов**: распространённый
|
|
9
|
-
* подход с двумя focus-guard кнопками по краям кладёт в разметку интерактивные
|
|
10
|
-
* элементы, а внутрь контейнера с ARIA-ролью их класть нельзя — роль объявляет
|
|
11
|
-
* потомков презентационными (axe: `nested-interactive`).
|
|
12
|
-
*
|
|
13
|
-
* Слой из ловушки не выводится: порядок окон, Esc и `inert` — забота
|
|
14
|
-
* `useOverlayLayer`. Композиция такая:
|
|
15
|
-
*
|
|
16
|
-
* ```ts
|
|
17
|
-
* const layer = useOverlayLayer(open, close, { modal: true, root: panelRef })
|
|
18
|
-
* useFocusTrap(panelRef, {
|
|
19
|
-
* active: () => open.value && isTopmost.value,
|
|
20
|
-
* containers: layer.rootsAbove,
|
|
21
|
-
* })
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
function useFocusTrap(container, options = {}) {
|
|
25
|
-
let previouslyFocused = null;
|
|
26
|
-
let listening = false;
|
|
27
|
-
let lastFocusedInside = null;
|
|
28
|
-
function roots() {
|
|
29
|
-
const extra = options.containers?.() ?? [];
|
|
30
|
-
return [container.value, ...extra].filter((root) => Boolean(root));
|
|
31
|
-
}
|
|
32
|
-
function contains(target) {
|
|
33
|
-
if (!target) return false;
|
|
34
|
-
return roots().some((root) => root === target || root.contains(target));
|
|
35
|
-
}
|
|
36
|
-
function focusables() {
|
|
37
|
-
return getFocusableElementsIn(roots());
|
|
38
|
-
}
|
|
39
|
-
function focusInitial() {
|
|
40
|
-
if (contains(document.activeElement)) return;
|
|
41
|
-
const requested = options.initialFocus?.();
|
|
42
|
-
if (requested && isFocusable(requested)) {
|
|
43
|
-
requested.focus();
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const [first] = focusables();
|
|
47
|
-
if (first) {
|
|
48
|
-
first.focus();
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
(options.fallbackFocus?.() ?? container.value)?.focus();
|
|
52
|
-
}
|
|
53
|
-
function onKeydown(event) {
|
|
54
|
-
if (event.key !== "Tab") return;
|
|
55
|
-
if (!contains(document.activeElement)) return;
|
|
56
|
-
const items = focusables();
|
|
57
|
-
if (items.length === 0) {
|
|
58
|
-
event.preventDefault();
|
|
59
|
-
(options.fallbackFocus?.() ?? container.value)?.focus();
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
const first = items[0];
|
|
63
|
-
const last = items[items.length - 1];
|
|
64
|
-
const active = document.activeElement;
|
|
65
|
-
if ((active ? items.indexOf(active) : -1) === -1) {
|
|
66
|
-
event.preventDefault();
|
|
67
|
-
(event.shiftKey ? last : first).focus();
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (event.shiftKey && active === first) {
|
|
71
|
-
event.preventDefault();
|
|
72
|
-
last.focus();
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
if (!event.shiftKey && active === last) {
|
|
76
|
-
event.preventDefault();
|
|
77
|
-
first.focus();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function onFocusIn(event) {
|
|
81
|
-
const target = event.target;
|
|
82
|
-
if (contains(target)) {
|
|
83
|
-
lastFocusedInside = target;
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
if (lastFocusedInside && contains(lastFocusedInside) && isFocusable(lastFocusedInside)) {
|
|
87
|
-
lastFocusedInside.focus();
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
focusInitial();
|
|
91
|
-
}
|
|
92
|
-
function activate() {
|
|
93
|
-
if (listening) return;
|
|
94
|
-
if (typeof document === "undefined") return;
|
|
95
|
-
listening = true;
|
|
96
|
-
previouslyFocused = document.activeElement ?? null;
|
|
97
|
-
lastFocusedInside = null;
|
|
98
|
-
document.addEventListener("keydown", onKeydown, true);
|
|
99
|
-
document.addEventListener("focusin", onFocusIn, true);
|
|
100
|
-
nextTick(() => {
|
|
101
|
-
if (!listening) return;
|
|
102
|
-
focusInitial();
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
function deactivate() {
|
|
106
|
-
if (!listening) return;
|
|
107
|
-
listening = false;
|
|
108
|
-
document.removeEventListener("keydown", onKeydown, true);
|
|
109
|
-
document.removeEventListener("focusin", onFocusIn, true);
|
|
110
|
-
const target = previouslyFocused;
|
|
111
|
-
previouslyFocused = null;
|
|
112
|
-
lastFocusedInside = null;
|
|
113
|
-
if (options.restoreFocus === false || !target) return;
|
|
114
|
-
if (!target.isConnected) return;
|
|
115
|
-
target.focus?.();
|
|
116
|
-
}
|
|
117
|
-
watch(() => Boolean(options.active?.() ?? true) && Boolean(container.value), (isActive) => {
|
|
118
|
-
if (isActive) activate();
|
|
119
|
-
else deactivate();
|
|
120
|
-
}, { immediate: true });
|
|
121
|
-
onScopeDispose(deactivate);
|
|
122
|
-
}
|
|
123
|
-
//#endregion
|
|
1
|
+
import { t as useFocusTrap } from "../chunks/useFocusTrap-D9bIPNF6.js";
|
|
124
2
|
export { useFocusTrap };
|
|
@@ -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-BAy4APOX.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-BAy4APOX.js";
|
|
2
2
|
export { GRANULARITY_PROVIDER_ID, createGranularityProvider, granularityProvider as default, granularityProvider, granularityComponentConfigs, granularityDefaultThemes, granularityThemeNames };
|
package/dist/index.js
CHANGED
|
@@ -22,8 +22,8 @@ import { useGrFormControl } from "./composables/useGrFormControl.js";
|
|
|
22
22
|
import { useComboboxNavigation } from "./composables/useComboboxNavigation.js";
|
|
23
23
|
import { useRovingFocus } from "./composables/useRovingFocus.js";
|
|
24
24
|
import { t as GrChip_default } from "./components/GrChip/chunks/GrChip-BTivtwff.js";
|
|
25
|
-
import { n as grAutocompleteSafelist, t as grAutocompleteConfig } from "./chunks/config-
|
|
26
|
-
import { t as GrAutocomplete_default } from "./components/GrAutocomplete/chunks/GrAutocomplete-
|
|
25
|
+
import { n as grAutocompleteSafelist, t as grAutocompleteConfig } from "./chunks/config-CYthTVK2.js";
|
|
26
|
+
import { t as GrAutocomplete_default } from "./components/GrAutocomplete/chunks/GrAutocomplete-BQsSE7sj.js";
|
|
27
27
|
import { t as GrSkeleton_default } from "./components/GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js";
|
|
28
28
|
import { n as GrAvatar_default, t as GrAvatarGroup_default } from "./components/GrAvatar/chunks/GrAvatar-CNmLmgcr.js";
|
|
29
29
|
import { c as initialsFrom, n as grAvatarSafelist, t as grAvatarConfig } from "./chunks/config-B3J0alyY.js";
|
|
@@ -62,26 +62,26 @@ import { n as grCollapseSafelist, t as grCollapseConfig } from "./chunks/config-
|
|
|
62
62
|
import { n as GrCollapse_default, t as GrCollapseItem_default } from "./components/GrCollapse/chunks/GrCollapse-BlW6ybdL.js";
|
|
63
63
|
import { n as grIconSafelist, t as grIconConfig } from "./chunks/config-3bQeQvqd.js";
|
|
64
64
|
import { t as GrInput_default } from "./components/GrInput/chunks/GrInput-BLywRZUN.js";
|
|
65
|
-
import { useFocusTrap } from "./
|
|
66
|
-
import { t as GrPopover_default } from "./components/GrPopover/chunks/GrPopover-
|
|
65
|
+
import { t as useFocusTrap } from "./chunks/useFocusTrap-D9bIPNF6.js";
|
|
66
|
+
import { t as GrPopover_default } from "./components/GrPopover/chunks/GrPopover-DEFxDffj.js";
|
|
67
67
|
import { useDragGesture } from "./composables/useDragGesture.js";
|
|
68
68
|
import { t as GrSlider_default } from "./components/GrSlider/chunks/GrSlider-DTTrZTHK.js";
|
|
69
|
-
import { t as GrColorPicker_default } from "./components/GrColorPicker/chunks/GrColorPicker-
|
|
69
|
+
import { t as GrColorPicker_default } from "./components/GrColorPicker/chunks/GrColorPicker-CIgdPXHn.js";
|
|
70
70
|
import { n as grColorPickerSafelist, t as grColorPickerConfig } from "./chunks/config-DIDz_E5m.js";
|
|
71
71
|
import { a as GR_KBD_TOKENS, o as findKbdToken, t as GrKbd_default } from "./components/GrKbd/chunks/GrKbd-D2ga1H9i.js";
|
|
72
|
-
import { t as GrModal_default } from "./components/GrModal/chunks/GrModal-
|
|
73
|
-
import { t as GrCommandPalette_default } from "./components/GrCommandPalette/chunks/GrCommandPalette-
|
|
72
|
+
import { t as GrModal_default } from "./components/GrModal/chunks/GrModal-_JrDhon-.js";
|
|
73
|
+
import { t as GrCommandPalette_default } from "./components/GrCommandPalette/chunks/GrCommandPalette-BZHUKlux.js";
|
|
74
74
|
import { n as grCommandPaletteSafelist, t as grCommandPaletteConfig } from "./chunks/config-D0NzGYaE.js";
|
|
75
75
|
import { t as GrConfigProvider_default } from "./components/GrConfigProvider/chunks/GrConfigProvider-BF7R3hgg.js";
|
|
76
76
|
import { t as grConfigProviderConfig } from "./chunks/config-B7W9VlZ7.js";
|
|
77
|
-
import { i as GrDialogFooter_default, n as GrDialogHeader_default, r as GrDialogCloseButton_default, t as GrDialog_default } from "./components/GrDialog/chunks/GrDialog-
|
|
77
|
+
import { i as GrDialogFooter_default, n as GrDialogHeader_default, r as GrDialogCloseButton_default, t as GrDialog_default } from "./components/GrDialog/chunks/GrDialog-C01Hhk6G.js";
|
|
78
78
|
import { a as extendDefaultParsers, n as coreResponseErrorParsers, r as createResponseErrorClassifier, s as normalizeError, t as GrResponseErrorBanner_default } from "./components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-DMeOWlzj.js";
|
|
79
|
-
import { t as GrConfirmDialog_default } from "./components/GrConfirmDialog/chunks/GrConfirmDialog-
|
|
79
|
+
import { t as GrConfirmDialog_default } from "./components/GrConfirmDialog/chunks/GrConfirmDialog-jRDs_E6C.js";
|
|
80
80
|
import { t as grConfirmDialogConfig } from "./chunks/config-A-bBiotF.js";
|
|
81
81
|
import "./components/GrConfirmDialog/index.js";
|
|
82
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-B33ZzwfB.js";
|
|
83
|
-
import { t as GrContextMenu_default } from "./components/GrContextMenu/chunks/GrContextMenu-
|
|
84
|
-
import { t as grContextMenuConfig } from "./chunks/config-
|
|
83
|
+
import { t as GrContextMenu_default } from "./components/GrContextMenu/chunks/GrContextMenu-DlFWm0eW.js";
|
|
84
|
+
import { t as grContextMenuConfig } from "./chunks/config-CsCUuukB.js";
|
|
85
85
|
import { t as GrTable_default } from "./components/GrTable/chunks/GrTable-jhUTczjv.js";
|
|
86
86
|
import { t as useDragSort } from "./chunks/useDragSort-0l47h4yb.js";
|
|
87
87
|
import { t as GrDataTable_default } from "./components/GrDataTable/chunks/GrDataTable-4JAgOQ-7.js";
|
|
@@ -99,24 +99,24 @@ import { n as useGrFormContext } from "./chunks/context-Bfrgsluh.js";
|
|
|
99
99
|
import { t as GrFormField_default } from "./components/GrFormField/chunks/GrFormField-DSylU7IU.js";
|
|
100
100
|
import { t as GrTextarea_default } from "./components/GrTextarea/chunks/GrTextarea-DinXG12-.js";
|
|
101
101
|
import { n as getByPath, o as runFieldRules, r as isEmpty, s as setByPath, t as createGrFormMessageResolver } from "./chunks/validation-5HhpanPP.js";
|
|
102
|
-
import { t as GrPromptDialog_default } from "./components/GrPromptDialog/chunks/GrPromptDialog-
|
|
103
|
-
import { a as useDialogService, i as teardownDialogService, n as dialogService, r as granularityDialogServicePlugin, t as GrDialogServiceHost_default } from "./components/GrDialogService/chunks/GrDialogService-
|
|
102
|
+
import { t as GrPromptDialog_default } from "./components/GrPromptDialog/chunks/GrPromptDialog-CailXSqW.js";
|
|
103
|
+
import { a as useDialogService, i as teardownDialogService, n as dialogService, r as granularityDialogServicePlugin, t as GrDialogServiceHost_default } from "./components/GrDialogService/chunks/GrDialogService-CmsJNUmM.js";
|
|
104
104
|
import { t as grDialogServiceConfig } from "./chunks/config-CjXjhphs.js";
|
|
105
105
|
import { n as grDividerSafelist, t as grDividerConfig } from "./chunks/config-D82r782v.js";
|
|
106
106
|
import { t as GrDivider_default } from "./components/GrDivider/chunks/GrDivider-BXavGcMX.js";
|
|
107
107
|
import { n as grDrawerSafelist, t as grDrawerConfig } from "./chunks/config-ChPg-BQv.js";
|
|
108
|
-
import { t as GrDrawer_default } from "./components/GrDrawer/chunks/GrDrawer-
|
|
109
|
-
import { t as GrDropdown_default } from "./components/GrDropdown/chunks/GrDropdown-
|
|
110
|
-
import { n as grDropdownSafelist, t as grDropdownConfig } from "./chunks/config-
|
|
108
|
+
import { t as GrDrawer_default } from "./components/GrDrawer/chunks/GrDrawer-xfoy-MCj.js";
|
|
109
|
+
import { t as GrDropdown_default } from "./components/GrDropdown/chunks/GrDropdown-7r772-Cq.js";
|
|
110
|
+
import { n as grDropdownSafelist, t as grDropdownConfig } from "./chunks/config-CT4lP6S4.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-
|
|
112
|
+
import { n as GrDropdownMenuColumn_default, r as GrDropdownMenu_default, t as GrDropdownMenuColumns_default } from "./components/GrDropdownMenu/chunks/GrDropdownMenu-DNurbsWc.js";
|
|
113
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-RqsWvgI9.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";
|
|
117
117
|
import { n as grFilePreviewSafelist, t as grFilePreviewConfig } from "./chunks/config-BaWANzzB.js";
|
|
118
118
|
import { t as GrProgressBar_default } from "./components/GrProgressBar/chunks/GrProgressBar-hszUOC8f.js";
|
|
119
|
-
import { n as GrUploadAbortError, r as GrUploadHttpError, t as GrFileUpload_default } from "./components/GrFileUpload/chunks/GrFileUpload-
|
|
119
|
+
import { n as GrUploadAbortError, r as GrUploadHttpError, t as GrFileUpload_default } from "./components/GrFileUpload/chunks/GrFileUpload-LL8RZvC0.js";
|
|
120
120
|
import { n as grFileUploadSafelist, t as grFileUploadConfig } from "./chunks/config-BlJa1Mj9.js";
|
|
121
121
|
import { t as GrForm_default } from "./components/GrForm/chunks/GrForm-CrnfCsgj.js";
|
|
122
122
|
import { t as grFormConfig } from "./chunks/config-Droqn55j.js";
|
|
@@ -126,7 +126,7 @@ import { t as GrFormFile_default } from "./components/GrFormFile/chunks/GrFormFi
|
|
|
126
126
|
import { n as grFormFileSafelist, t as grFormFileConfig } from "./chunks/config-BcXX7S7B.js";
|
|
127
127
|
import { n as grFormSectionSafelist, t as grFormSectionConfig } from "./chunks/config-BEO7brpO.js";
|
|
128
128
|
import { t as GrFormSection_default } from "./components/GrFormSection/chunks/GrFormSection-ejieOg9H.js";
|
|
129
|
-
import { t as GrImageViewer_default } from "./components/GrImageViewer/chunks/GrImageViewer
|
|
129
|
+
import { t as GrImageViewer_default } from "./components/GrImageViewer/chunks/GrImageViewer--BU8yrfx.js";
|
|
130
130
|
import { n as grImageViewerSafelist, t as grImageViewerConfig } from "./chunks/config-BDSaD-5p.js";
|
|
131
131
|
import { n as grInputSafelist, t as grInputConfig } from "./chunks/config-CIkdsWUk.js";
|
|
132
132
|
import "./components/GrInput/index.js";
|
|
@@ -149,10 +149,10 @@ import { t as GrNavbar_default } from "./components/GrNavbar/chunks/GrNavbar-_rt
|
|
|
149
149
|
import { n as grNavbarSafelist, t as grNavbarConfig } from "./chunks/config-2ZHRsdOc.js";
|
|
150
150
|
import { n as grNumberInputSafelist, t as grNumberInputConfig } from "./chunks/config-MmPym-Z72.js";
|
|
151
151
|
import { t as GrNumberInput_default } from "./components/GrNumberInput/chunks/GrNumberInput-DQ59YICu.js";
|
|
152
|
-
import { t as GrSelect_default } from "./components/GrSelect/chunks/GrSelect-
|
|
152
|
+
import { t as GrSelect_default } from "./components/GrSelect/chunks/GrSelect-CZqV1Eg4.js";
|
|
153
153
|
import { n as grPaginationSafelist, t as grPaginationConfig } from "./chunks/config-CjKpUcmy.js";
|
|
154
|
-
import { t as GrPagination_default } from "./components/GrPagination/chunks/GrPagination-
|
|
155
|
-
import { n as grPopoverSafelist, t as grPopoverConfig } from "./chunks/config-
|
|
154
|
+
import { t as GrPagination_default } from "./components/GrPagination/chunks/GrPagination-gBoWVHk6.js";
|
|
155
|
+
import { n as grPopoverSafelist, t as grPopoverConfig } from "./chunks/config-DVCNvhIG2.js";
|
|
156
156
|
import "./components/GrPopover/index.js";
|
|
157
157
|
import { n as grProgressBarSafelist, r as GR_TONES, t as grProgressBarConfig } from "./chunks/config-DWL81-aM.js";
|
|
158
158
|
import "./components/GrProgressBar/index.js";
|
|
@@ -170,7 +170,7 @@ import { t as GrRating_default } from "./components/GrRating/chunks/GrRating-IEi
|
|
|
170
170
|
import { n as GrFormErrorBanner_default, r as GrUploadErrorBanner_default, t as useResponseError } from "./components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-CBVRpgIG.js";
|
|
171
171
|
import { n as titleWhenTruncated, t as GrSegmented_default } from "./components/GrSegmented/chunks/GrSegmented-CB-VR-yL.js";
|
|
172
172
|
import { n as grSegmentedSafelist, t as grSegmentedConfig } from "./chunks/config-rLkc9Zn2.js";
|
|
173
|
-
import { n as grSelectSafelist, t as grSelectConfig } from "./chunks/config-
|
|
173
|
+
import { n as grSelectSafelist, t as grSelectConfig } from "./chunks/config-DOYz_SVK.js";
|
|
174
174
|
import "./components/GrSelect/index.js";
|
|
175
175
|
import { n as grSidebarSafelist, t as grSidebarConfig } from "./chunks/config-DNDgp9bB.js";
|
|
176
176
|
import { n as GrSidebarItem_default, r as GrSidebar_default, t as GrSidebarGroup_default } from "./components/GrSidebar/chunks/GrSidebar-alkwBUzL.js";
|
|
@@ -193,7 +193,7 @@ import "./components/GrTable/index.js";
|
|
|
193
193
|
import { n as GrTabPanels_default, t as GrTabPanel_default } from "./components/GrTabPanels/chunks/GrTabPanels-BZQS8-JM.js";
|
|
194
194
|
import { t as grTabPanelsConfig } from "./chunks/config-eXB87DOi.js";
|
|
195
195
|
import { n as grTabsSafelist, t as grTabsConfig } from "./chunks/config-_QF0O1vq.js";
|
|
196
|
-
import { t as GrTabs_default } from "./components/GrTabs/chunks/GrTabs-
|
|
196
|
+
import { t as GrTabs_default } from "./components/GrTabs/chunks/GrTabs-UsO4j8zv.js";
|
|
197
197
|
import { n as grTextareaSafelist, t as grTextareaConfig } from "./chunks/config-BhfNgyWL.js";
|
|
198
198
|
import "./components/GrTextarea/index.js";
|
|
199
199
|
import { n as GrTimeline_default, t as GrTimelineItem_default } from "./components/GrTimeline/chunks/GrTimeline-BiHpArsg.js";
|
|
@@ -204,8 +204,8 @@ import { t as GrToaster_default } from "./components/GrToaster/chunks/GrToaster-
|
|
|
204
204
|
import { n as grTooltipSafelist, t as grTooltipConfig } from "./chunks/config-BTmfQFwi.js";
|
|
205
205
|
import { t as GrTooltip_default } from "./components/GrTooltip/chunks/GrTooltip-uYETdbCD.js";
|
|
206
206
|
import { n as grTreeSafelist, t as grTreeConfig } from "./chunks/config-CDat1wXf.js";
|
|
207
|
-
import { n as grTreeSelectSafelist, t as grTreeSelectConfig } from "./chunks/config-
|
|
208
|
-
import { t as GrTreeSelect_default } from "./components/GrTreeSelect/chunks/GrTreeSelect-
|
|
207
|
+
import { n as grTreeSelectSafelist, t as grTreeSelectConfig } from "./chunks/config-DUNH02Fg.js";
|
|
208
|
+
import { t as GrTreeSelect_default } from "./components/GrTreeSelect/chunks/GrTreeSelect-DOXcpWq2.js";
|
|
209
209
|
import "./composables/useGrComponentConfig.js";
|
|
210
210
|
import "./composables/useGranularityTranslations.js";
|
|
211
211
|
import { GRANULARITY_THEME_STATE, granularityThemePlugin, initThemeEarly, useTheme } from "./composables/useTheme.js";
|
package/dist/theme.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as grThemeTokens, n as grDerivedTokens, t as grComponentTokens } from "./chunks/generated-
|
|
1
|
+
import { a as grThemeTokens, n as grDerivedTokens, t as grComponentTokens } from "./chunks/generated-Bk-f6NsN.js";
|
|
2
2
|
//#region src/theme/color.ts
|
|
3
3
|
function parseHex(value) {
|
|
4
4
|
const match = value.trim().match(/^#([\da-f]{3}|[\da-f]{6})$/i);
|
package/dist/tokens.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as grThemeTokens, i as grThemeNames, n as grDerivedTokens, r as grFoundationTokens, t as grComponentTokens } from "./chunks/generated-
|
|
1
|
+
import { a as grThemeTokens, i as grThemeNames, n as grDerivedTokens, r as grFoundationTokens, t as grComponentTokens } from "./chunks/generated-Bk-f6NsN.js";
|
|
2
2
|
export { grComponentTokens, grDerivedTokens, grFoundationTokens, grThemeNames, grThemeTokens };
|
|
@@ -60,4 +60,4 @@ export declare const autocompleteStateClass = "flex items-center justify-center
|
|
|
60
60
|
* (card + бордер + shadow-2 + скругление). Держим локальную копию строки,
|
|
61
61
|
* чтобы не тянуть зависимость от `GrSelect` (компоненты гранулярно независимы).
|
|
62
62
|
*/
|
|
63
|
-
export declare const autocompletePanelClasses = "rounded-[var(--gr-radius-xl)] border border-[var(--gr-brd)] bg-[var(--gr-
|
|
63
|
+
export declare const autocompletePanelClasses = "rounded-[var(--gr-radius-xl)] border border-[var(--gr-brd)] bg-[var(--gr-popover)] text-[var(--gr-popover-fg)] shadow-[var(--gr-shadow-2)] overflow-hidden";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { UseFloatingPlacement } from '../../composables/useFloating';
|
|
2
2
|
import { type GrDropdownWidth } from './grDropdownStyles';
|
|
3
3
|
export type GrDropdownTrigger = 'click' | 'hover';
|
|
4
4
|
export interface GrDropdownProps {
|
|
@@ -36,13 +36,13 @@ export interface GrDropdownEmits {
|
|
|
36
36
|
(e: 'update:open', value: boolean): void;
|
|
37
37
|
}
|
|
38
38
|
declare function open(): void;
|
|
39
|
-
declare function toggle(): void;
|
|
40
39
|
declare function close(): void;
|
|
40
|
+
declare function toggle(): void;
|
|
41
41
|
type __VLS_Slots = {
|
|
42
42
|
/**
|
|
43
43
|
* Триггер панели. `triggerProps` обязаны попасть на сам интерактивный
|
|
44
44
|
* элемент, а не на обёртку вокруг него: `aria-expanded` и `aria-controls`
|
|
45
|
-
* читаются с того узла, который получает
|
|
45
|
+
* читаются с того узла, который получает фокус, а клик приезжает вместе с ними.
|
|
46
46
|
*/
|
|
47
47
|
trigger?: (props: {
|
|
48
48
|
open: boolean;
|
|
@@ -94,11 +94,11 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
94
94
|
open: boolean;
|
|
95
95
|
disabled: boolean;
|
|
96
96
|
trigger: GrDropdownTrigger;
|
|
97
|
+
openDelay: number;
|
|
98
|
+
closeDelay: number;
|
|
97
99
|
closeOnContentClick: boolean;
|
|
98
100
|
teleportTo: string | HTMLElement;
|
|
99
101
|
contentClass: string;
|
|
100
|
-
openDelay: number;
|
|
101
|
-
closeDelay: number;
|
|
102
102
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
103
103
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
104
104
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { Placement } from '@floating-ui/dom';
|
|
2
2
|
/** Ширина панели: число — пиксели, строка — CSS-длина, `auto` — по контенту. */
|
|
3
3
|
export type GrDropdownWidth = number | string;
|
|
4
|
-
export declare const originClassByPlacement: Record<Placement, string>;
|
|
5
4
|
export declare function grDropdownOriginClass(placement: Placement): string;
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Поле вокруг пунктов меню.
|
|
7
|
+
*
|
|
8
|
+
* Поверхности здесь больше нет: панель рисует `GrPopover`, на котором меню и
|
|
9
|
+
* стоит. Осталось только поле — пункты не должны прилегать к рамке вплотную, —
|
|
10
|
+
* и классы потребителя.
|
|
11
|
+
*/
|
|
12
|
+
export declare const dropdownContentBaseClass = "p-1";
|
|
7
13
|
export declare function grDropdownContentClass(contentClass?: string): string;
|
|
@@ -116,13 +116,13 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
116
116
|
disabled: boolean;
|
|
117
117
|
items: GrDropdownMenuEntry[];
|
|
118
118
|
trigger: GrDropdownTrigger;
|
|
119
|
+
openDelay: number;
|
|
120
|
+
closeDelay: number;
|
|
119
121
|
closeOnContentClick: boolean;
|
|
120
122
|
teleportTo: string | HTMLElement;
|
|
121
123
|
contentClass: string;
|
|
122
124
|
dividers: boolean;
|
|
123
125
|
listClass: string;
|
|
124
|
-
openDelay: number;
|
|
125
|
-
closeDelay: number;
|
|
126
126
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
127
127
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
128
128
|
declare const _default: typeof __VLS_export;
|
|
@@ -27,10 +27,24 @@ export interface GrPopoverProps {
|
|
|
27
27
|
/** `id` видимого заголовка внутри панели — альтернатива `ariaLabel`. */
|
|
28
28
|
labelledBy?: string;
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
30
|
+
* Чем открывается панель.
|
|
31
|
+
*
|
|
32
|
+
* `manual` — только программно (через `v-model:open`): нужно контекстному меню
|
|
33
|
+
* и подтверждениям, где момент открытия решает потребитель. `hover` — по
|
|
34
|
+
* наведению, с задержками из `openDelay` и `closeDelay`; клик и клавиатура в
|
|
35
|
+
* этом режиме продолжают работать.
|
|
36
|
+
*/
|
|
37
|
+
trigger?: 'click' | 'manual' | 'hover';
|
|
38
|
+
/**
|
|
39
|
+
* Задержка открытия по наведению, мс.
|
|
40
|
+
*
|
|
41
|
+
* Обе задержки нужны, и каждая по своей причине: без `openDelay` панель
|
|
42
|
+
* выпрыгивает на любое пересечение курсором, без `closeDelay` её не удержать
|
|
43
|
+
* при переходе с триггера на панель — между ними зазор `offsetPx`.
|
|
32
44
|
*/
|
|
33
|
-
|
|
45
|
+
openDelay?: number;
|
|
46
|
+
/** Задержка закрытия после ухода курсора, мс. */
|
|
47
|
+
closeDelay?: number;
|
|
34
48
|
closeOnEsc?: boolean;
|
|
35
49
|
closeOnClickOutside?: boolean;
|
|
36
50
|
/** Закрывать по клику внутри панели — удобно для меню, вредно для формы. */
|
|
@@ -61,6 +75,30 @@ export interface GrPopoverProps {
|
|
|
61
75
|
anchor?: GrFloatingAnchorRect | null;
|
|
62
76
|
/** Поле панели. `none` — содержимое рисует своё (меню, список опций). */
|
|
63
77
|
padding?: GrPopoverPadding;
|
|
78
|
+
/**
|
|
79
|
+
* Брать ширину у триггера: `true` — точно его ширина, `'min'` — не уже его,
|
|
80
|
+
* дальше по содержимому. Панель у поля или у широкой кнопки, оказавшаяся уже
|
|
81
|
+
* своего триггера, читается как ошибка вёрстки.
|
|
82
|
+
*
|
|
83
|
+
* С потолком `--gr-popover-max-width` сочетается, а не спорит: ширину задаёт
|
|
84
|
+
* триггер, потолок её ограничивает — «шириной с триггер, но не шире
|
|
85
|
+
* читаемого». Поэтому это отдельный проп, а не значение одного перечисления
|
|
86
|
+
* вместе с потолком: оси независимы, и сочетание осмысленно.
|
|
87
|
+
*/
|
|
88
|
+
matchWidth?: boolean | 'min';
|
|
89
|
+
/**
|
|
90
|
+
* Обёртка триггера занимает всю ширину родителя вместо того, чтобы обжимать
|
|
91
|
+
* содержимое.
|
|
92
|
+
*
|
|
93
|
+
* Нужно форм-контролам: обёртка `inline-block` схлопывается по содержимому, и
|
|
94
|
+
* `w-full` у самого триггера начинает резолвиться относительно неё, а не
|
|
95
|
+
* относительно поля. Контрол, объявивший себя во всю ширину, рисуется по
|
|
96
|
+
* содержимому — рядом с полем ввода это читается как сбитая вёрстка.
|
|
97
|
+
*
|
|
98
|
+
* Имя то же, что у `GrButton` и `GrSegmented`: в ядре это устоявшееся слово
|
|
99
|
+
* для «во всю ширину».
|
|
100
|
+
*/
|
|
101
|
+
block?: boolean;
|
|
64
102
|
}
|
|
65
103
|
export interface GrPopoverEmits {
|
|
66
104
|
(e: 'update:open', value: boolean): void;
|
|
@@ -95,6 +133,8 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
95
133
|
ariaLabel: undefined;
|
|
96
134
|
labelledBy: undefined;
|
|
97
135
|
trigger: string;
|
|
136
|
+
openDelay: number;
|
|
137
|
+
closeDelay: number;
|
|
98
138
|
closeOnEsc: boolean;
|
|
99
139
|
closeOnClickOutside: boolean;
|
|
100
140
|
closeOnContentClick: boolean;
|
|
@@ -104,6 +144,8 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
104
144
|
disabled: boolean;
|
|
105
145
|
anchor: undefined;
|
|
106
146
|
padding: string;
|
|
147
|
+
matchWidth: boolean;
|
|
148
|
+
block: boolean;
|
|
107
149
|
}>>, {
|
|
108
150
|
open: typeof open;
|
|
109
151
|
close: typeof close;
|
|
@@ -120,6 +162,8 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
120
162
|
ariaLabel: undefined;
|
|
121
163
|
labelledBy: undefined;
|
|
122
164
|
trigger: string;
|
|
165
|
+
openDelay: number;
|
|
166
|
+
closeDelay: number;
|
|
123
167
|
closeOnEsc: boolean;
|
|
124
168
|
closeOnClickOutside: boolean;
|
|
125
169
|
closeOnContentClick: boolean;
|
|
@@ -129,6 +173,8 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
129
173
|
disabled: boolean;
|
|
130
174
|
anchor: undefined;
|
|
131
175
|
padding: string;
|
|
176
|
+
matchWidth: boolean;
|
|
177
|
+
block: boolean;
|
|
132
178
|
}>>> & Readonly<{
|
|
133
179
|
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
134
180
|
}>, {
|
|
@@ -138,12 +184,16 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
|
|
|
138
184
|
role: GrPopoverRole;
|
|
139
185
|
modal: boolean;
|
|
140
186
|
placement: UseFloatingPlacement;
|
|
187
|
+
block: boolean;
|
|
141
188
|
open: boolean;
|
|
142
189
|
disabled: boolean;
|
|
143
190
|
ariaLabel: string;
|
|
191
|
+
matchWidth: boolean | "min";
|
|
144
192
|
labelledBy: string;
|
|
145
193
|
offsetPx: number;
|
|
146
|
-
trigger: "click" | "manual";
|
|
194
|
+
trigger: "click" | "manual" | "hover";
|
|
195
|
+
openDelay: number;
|
|
196
|
+
closeDelay: number;
|
|
147
197
|
closeOnEsc: boolean;
|
|
148
198
|
closeOnClickOutside: boolean;
|
|
149
199
|
closeOnContentClick: boolean;
|
|
@@ -14,17 +14,25 @@ export type GrPopoverRole = 'dialog' | 'menu' | 'listbox' | 'grid' | 'group' | '
|
|
|
14
14
|
export type GrPopoverPadding = 'default' | 'none';
|
|
15
15
|
export declare const panelSizes: Record<GrPopoverSize, string>;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
* `useFloating`, здесь остаётся направление «роста» относительно триггера.
|
|
17
|
+
* Поверхность панели.
|
|
19
18
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*
|
|
27
|
-
*
|
|
19
|
+
* Ширина — `min()` из двух пределов, и они разной природы. Первый, `22rem`, —
|
|
20
|
+
* потолок содержимого: читаемая ширина колонки текста. Он **дефолт**, а не
|
|
21
|
+
* закон, и снимается хуком `--gr-popover-max-width` — примитив объявил, что
|
|
22
|
+
* содержимое панели дело потребителя, и навязывать ему форму не вправе.
|
|
23
|
+
* Тулбар, палитра и сетка шире прозы законно.
|
|
24
|
+
*
|
|
25
|
+
* Второй, `calc(100vw-1rem)`, — инвариант слоя: `useFloating` смещает панель в
|
|
26
|
+
* пределах вьюпорта, но не сужает её. Он не настраивается ничем и снаружи не
|
|
27
|
+
* отключается, потому что стоит вторым операндом `min()`: даже
|
|
28
|
+
* `--gr-popover-max-width: 100vw` его не снимает, а лишь уступает ему место.
|
|
29
|
+
*
|
|
30
|
+
* Хуком, а не пропом, — по трём причинам. Спор специфичности не возникает
|
|
31
|
+
* вовсе: кастомное свойство разрешается каскадом на самом элементе, а не
|
|
32
|
+
* порядком правил в сгенерированном CSS (та же ловушка, что описана у
|
|
33
|
+
* `panelSizesFlush`). Потолок можно менять по брейкпоинту и по теме — пропом
|
|
34
|
+
* этого не сделать. И словарь компонента не растёт: значение остаётся
|
|
35
|
+
* значением. Так же устроена высота списка у `GrCommandPalette`.
|
|
28
36
|
*/
|
|
29
37
|
/**
|
|
30
38
|
* Кегль без поля.
|
|
@@ -34,5 +42,24 @@ export declare function grPopoverOriginClass(placement: Placement): string;
|
|
|
34
42
|
* сгенерированном CSS. Меню внутри поповера с `p-3` — визуально не меню.
|
|
35
43
|
*/
|
|
36
44
|
export declare const panelSizesFlush: Record<GrPopoverSize, string>;
|
|
37
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Высота — тоже `min()` из двух пределов, но устроена иначе, чем ширина.
|
|
47
|
+
*
|
|
48
|
+
* Потолок ширины статичен: `calc(100vw-1rem)` не зависит от того, где стоит
|
|
49
|
+
* триггер. Потолок высоты статичным быть не может — доступное место есть
|
|
50
|
+
* расстояние до края вьюпорта на той стороне, куда панель встала, и меняется
|
|
51
|
+
* оно на каждом скролле. Поэтому второй операнд здесь — не константа, а замер
|
|
52
|
+
* слоя (`--gr-floating-available-height`, см. `useFloating`), и он пересчитан
|
|
53
|
+
* уже **после** `flip`: сторона окончательная.
|
|
54
|
+
*
|
|
55
|
+
* `overflow-y: auto` идёт с потолком одной строкой намеренно. Потолок без
|
|
56
|
+
* скролла не ограничивает, а обрезает: содержимое молча уходит под нижний край
|
|
57
|
+
* панели, и добраться до него нельзя ничем. Пока потолок не упёрся, полоса не
|
|
58
|
+
* рисуется, так что для коротких панелей не меняется ничего.
|
|
59
|
+
*
|
|
60
|
+
* Хук `--gr-popover-max-height` по умолчанию `100vh` — то есть «мнения нет»,
|
|
61
|
+
* и высоту диктует замер. Он же служит фолбэком, пока позиция не посчитана
|
|
62
|
+
* (первый кадр, SSR): панель не схлопывается в ноль, а просто не ограничена.
|
|
63
|
+
*/
|
|
64
|
+
export declare const popoverPanelBaseClass = "rounded-[var(--gr-radius-xl)] border border-[var(--gr-brd)] bg-[var(--gr-popover)] text-[var(--gr-popover-fg)] shadow-[var(--gr-shadow-2)] max-w-[min(var(--gr-popover-max-width,22rem),calc(100vw-1rem))] max-h-[min(var(--gr-popover-max-height,100vh),var(--gr-floating-available-height,100vh))] overflow-y-auto focus:outline-none";
|
|
38
65
|
export declare function grPopoverPanelClass(size: GrPopoverSize, placement: Placement, extra?: string, padding?: GrPopoverPadding): string;
|