@feugene/granularity 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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-BTwYMQaz2.js → config-DBXCIb6r2.js} +4 -3
- package/dist/chunks/config-DBXCIb6r2.js.map +1 -0
- package/dist/chunks/{config-uzUuosv7.js → config-DGGaKf4R.js} +6 -5
- package/dist/chunks/config-DGGaKf4R.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/{generated-CSyPsWtM.js → generated-Buw6W7Te.js} +7 -0
- package/dist/chunks/{generated-CSyPsWtM.js.map → generated-Buw6W7Te.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-DKwigt7b.js +91 -0
- package/dist/chunks/grPopoverStyles-DKwigt7b.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-3LUawDPh.js} +6 -6
- package/dist/chunks/{granular-provider-CrQua8PT.js.map → granular-provider-3LUawDPh.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-D1Iis7jf.js} +2 -1
- package/dist/components/GrColorPicker/chunks/GrColorPicker-D1Iis7jf.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-CWmgrzpi.js} +17 -3
- package/dist/components/GrContextMenu/chunks/GrContextMenu-CWmgrzpi.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-CDkPkvIJ.js +180 -0
- package/dist/components/GrDropdown/chunks/GrDropdown-CDkPkvIJ.js.map +1 -0
- package/dist/components/GrDropdown/index.js +2 -2
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-GOzuAXsi.js → GrDropdownMenu-DQrZ_yPV.js} +1 -1
- package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-GOzuAXsi.js.map → GrDropdownMenu-DQrZ_yPV.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-CzeXMcvh.js} +87 -13
- package/dist/components/GrPopover/chunks/GrPopover-CzeXMcvh.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/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 +19 -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/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":"GrConfirmDialog-CUP43q__.js","names":[],"sources":["../../../../src/components/GrConfirmDialog/GrConfirmDialog.vue","../../../../src/components/GrConfirmDialog/GrConfirmDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrConfirmDialog — GR-примитив диалога подтверждения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog`/`GrPromptDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Клик по «Confirm»/«Cancel» эмитит одноимённое событие и закрывает диалог\n * через `update:modelValue`.\n */\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrResponseErrorBanner from '../GrResponseErrorBanner/GrResponseErrorBanner.vue'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\nimport type { ResponseErrorInfo } from '../GrResponseErrorBanner'\n\n/** Какое действие получает фокус при открытии окна. */\nexport type GrConfirmDialogFocusAction = 'confirm' | 'cancel' | 'none'\n\nexport interface GrConfirmDialogProps {\n modelValue: boolean\n title?: string\n description?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n /**\n * Структура ошибки ответа сервера для показа в теле диалога\n * (через `GrResponseErrorBanner`). Используется императивным\n * `useDialogService` для async-`onConfirm`. `null` — блок скрыт.\n */\n error?: ResponseErrorInfo | null\n /** Состояние загрузки кнопки Confirm (async-`onConfirm` in-flight). */\n confirmLoading?: boolean\n /** Принудительно дизейблит кнопку Confirm. */\n confirmDisabled?: boolean\n /**\n * Закрывать ли диалог автоматически по клику Confirm. По умолчанию `true`\n * (историческое поведение). `false` — отдаёт управление закрытием наружу\n * (нужно `useDialogService`, который ждёт результат async-`onConfirm`).\n */\n closeOnConfirm?: boolean\n /**\n * Какое действие получает фокус при открытии. По умолчанию «Отмена»:\n * подтверждение бывает деструктивным, и `Enter` сразу после открытия не\n * должен его запускать. `none` оставляет фокус на панели окна.\n *\n * Имя не `initialFocus` намеренно: у `GrModal`/`GrDrawer` так называется\n * проп с элементом, а здесь выбирается действие.\n */\n focusAction?: GrConfirmDialogFocusAction\n /**\n * Запрет закрытия «мягкими» способами (Esc, клик по бэкдропу), пока идёт\n * подтверждение (`confirmLoading`). Кнопка закрытия и «Отмена» остаются:\n * окно без единого выхода — ловушка.\n */\n persistent?: boolean\n}\n\nexport interface GrConfirmDialogEmits {\n (e: 'update:modelValue', value: boolean): void\n (e: 'confirm'): void\n (e: 'cancel'): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(defineProps<GrConfirmDialogProps>(), {\n title: undefined,\n description: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: undefined,\n buttonSize: undefined,\n confirmText: undefined,\n cancelText: undefined,\n confirmVariant: 'primary',\n confirmTone: 'primary',\n error: null,\n confirmLoading: false,\n confirmDisabled: false,\n closeOnConfirm: true,\n focusAction: 'cancel',\n persistent: false,\n})\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentProp('GrConfirmDialog', 'size', () => props.size, 'md')\n\nconst emit = defineEmits<GrConfirmDialogEmits>()\n\n// Дефолты берём из общего i18n-блока пакета (fallback — англ.), а не хардкодим.\nconst { t } = useGranularityTranslations()\nconst resolvedTitle = computed(() => props.title ?? t('gr.dialog.confirm.title', 'Confirm'))\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.common.close', 'Close'))\nconst resolvedConfirmText = computed(() => props.confirmText ?? t('gr.common.confirm', 'Confirm'))\nconst resolvedCancelText = computed(() => props.cancelText ?? t('gr.common.cancel', 'Cancel'))\n\nconst open = computed({\n get: () => props.modelValue,\n set: (value: boolean) => emit('update:modelValue', value),\n})\n\nconst confirmButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\nconst cancelButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\n\n// Пока подтверждение в полёте, случайное движение не должно оборвать операцию.\nconst softCloseBlocked = computed(() => props.persistent && props.confirmLoading)\nconst resolvedCloseOnBackdrop = computed(() => (softCloseBlocked.value ? false : props.closeOnBackdrop))\nconst resolvedCloseOnEsc = computed(() => (softCloseBlocked.value ? false : props.closeOnEsc))\n\n/**\n * Фокус ставит содержимое после отрисовки, а не проп `initialFocus` у\n * `GrModal`: кнопка рождается внутри поддерева диалога, и возврат её же пропом\n * наверх замыкает рендер в цикл (проверено на `GrPromptDialog`).\n *\n * Молчит, когда фокусировать нечего: со своим слотом `#footer` кнопок с\n * рефами в DOM нет, и фокус остаётся на панели — это корректный исход, а не\n * повод падать.\n */\nfunction focusAction(): void {\n if (props.focusAction === 'confirm')\n confirmButtonRef.value?.focus()\n else if (props.focusAction === 'cancel')\n cancelButtonRef.value?.focus()\n}\n\n// Источник — не только `modelValue`, но и сами кнопки: содержимое панели\n// появляется на такт позже открытия, и фокус по фиксированному `nextTick`\n// приходился на момент, когда фокусировать ещё нечего.\nwatch(\n [() => props.modelValue, cancelButtonRef, confirmButtonRef],\n () => {\n if (!props.modelValue || props.focusAction === 'none')\n return\n focusAction()\n },\n // `immediate`: окно могут смонтировать уже открытым — смены пропа тогда нет.\n { immediate: true, flush: 'post' },\n)\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n emit('confirm')\n if (props.closeOnConfirm)\n emit('update:modelValue', false)\n}\n\ndefineSlots<{\n /** Содержимое диалога вместо пропа `message`. */\n default?: () => any\n /** Разбор ошибки вместо встроенного баннера. */\n error?: (props: { error: ResponseErrorInfo | null }) => any\n /** Кнопки диалога вместо пары «отмена и подтверждение». */\n footer?: () => any\n}>()\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"resolvedTitle\"\n :size=\"resolvedSize\"\n :close-on-backdrop=\"resolvedCloseOnBackdrop\"\n :close-on-esc=\"resolvedCloseOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"resolvedCloseLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)] text-[var(--gr-muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <slot name=\"error\" :error=\"error\">\n <GrResponseErrorBanner v-if=\"error\" :error=\"error\" :can-dismiss=\"false\" />\n </slot>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton ref=\"cancelButtonRef\" data-testid=\"gr-confirm-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ resolvedCancelText }}\n </GrButton>\n <GrButton\n ref=\"confirmButtonRef\"\n data-testid=\"gr-confirm-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :loading=\"confirmLoading\"\n :disabled=\"confirmDisabled\"\n @click=\"onConfirm\"\n >\n {{ resolvedConfirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrConfirmDialog — GR-примитив диалога подтверждения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog`/`GrPromptDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Клик по «Confirm»/«Cancel» эмитит одноимённое событие и закрывает диалог\n * через `update:modelValue`.\n */\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrResponseErrorBanner from '../GrResponseErrorBanner/GrResponseErrorBanner.vue'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\nimport type { ResponseErrorInfo } from '../GrResponseErrorBanner'\n\n/** Какое действие получает фокус при открытии окна. */\nexport type GrConfirmDialogFocusAction = 'confirm' | 'cancel' | 'none'\n\nexport interface GrConfirmDialogProps {\n modelValue: boolean\n title?: string\n description?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n /**\n * Структура ошибки ответа сервера для показа в теле диалога\n * (через `GrResponseErrorBanner`). Используется императивным\n * `useDialogService` для async-`onConfirm`. `null` — блок скрыт.\n */\n error?: ResponseErrorInfo | null\n /** Состояние загрузки кнопки Confirm (async-`onConfirm` in-flight). */\n confirmLoading?: boolean\n /** Принудительно дизейблит кнопку Confirm. */\n confirmDisabled?: boolean\n /**\n * Закрывать ли диалог автоматически по клику Confirm. По умолчанию `true`\n * (историческое поведение). `false` — отдаёт управление закрытием наружу\n * (нужно `useDialogService`, который ждёт результат async-`onConfirm`).\n */\n closeOnConfirm?: boolean\n /**\n * Какое действие получает фокус при открытии. По умолчанию «Отмена»:\n * подтверждение бывает деструктивным, и `Enter` сразу после открытия не\n * должен его запускать. `none` оставляет фокус на панели окна.\n *\n * Имя не `initialFocus` намеренно: у `GrModal`/`GrDrawer` так называется\n * проп с элементом, а здесь выбирается действие.\n */\n focusAction?: GrConfirmDialogFocusAction\n /**\n * Запрет закрытия «мягкими» способами (Esc, клик по бэкдропу), пока идёт\n * подтверждение (`confirmLoading`). Кнопка закрытия и «Отмена» остаются:\n * окно без единого выхода — ловушка.\n */\n persistent?: boolean\n}\n\nexport interface GrConfirmDialogEmits {\n (e: 'update:modelValue', value: boolean): void\n (e: 'confirm'): void\n (e: 'cancel'): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(defineProps<GrConfirmDialogProps>(), {\n title: undefined,\n description: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: undefined,\n buttonSize: undefined,\n confirmText: undefined,\n cancelText: undefined,\n confirmVariant: 'primary',\n confirmTone: 'primary',\n error: null,\n confirmLoading: false,\n confirmDisabled: false,\n closeOnConfirm: true,\n focusAction: 'cancel',\n persistent: false,\n})\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentProp('GrConfirmDialog', 'size', () => props.size, 'md')\n\nconst emit = defineEmits<GrConfirmDialogEmits>()\n\n// Дефолты берём из общего i18n-блока пакета (fallback — англ.), а не хардкодим.\nconst { t } = useGranularityTranslations()\nconst resolvedTitle = computed(() => props.title ?? t('gr.dialog.confirm.title', 'Confirm'))\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.common.close', 'Close'))\nconst resolvedConfirmText = computed(() => props.confirmText ?? t('gr.common.confirm', 'Confirm'))\nconst resolvedCancelText = computed(() => props.cancelText ?? t('gr.common.cancel', 'Cancel'))\n\nconst open = computed({\n get: () => props.modelValue,\n set: (value: boolean) => emit('update:modelValue', value),\n})\n\nconst confirmButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\nconst cancelButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\n\n// Пока подтверждение в полёте, случайное движение не должно оборвать операцию.\nconst softCloseBlocked = computed(() => props.persistent && props.confirmLoading)\nconst resolvedCloseOnBackdrop = computed(() => (softCloseBlocked.value ? false : props.closeOnBackdrop))\nconst resolvedCloseOnEsc = computed(() => (softCloseBlocked.value ? false : props.closeOnEsc))\n\n/**\n * Фокус ставит содержимое после отрисовки, а не проп `initialFocus` у\n * `GrModal`: кнопка рождается внутри поддерева диалога, и возврат её же пропом\n * наверх замыкает рендер в цикл (проверено на `GrPromptDialog`).\n *\n * Молчит, когда фокусировать нечего: со своим слотом `#footer` кнопок с\n * рефами в DOM нет, и фокус остаётся на панели — это корректный исход, а не\n * повод падать.\n */\nfunction focusAction(): void {\n if (props.focusAction === 'confirm')\n confirmButtonRef.value?.focus()\n else if (props.focusAction === 'cancel')\n cancelButtonRef.value?.focus()\n}\n\n// Источник — не только `modelValue`, но и сами кнопки: содержимое панели\n// появляется на такт позже открытия, и фокус по фиксированному `nextTick`\n// приходился на момент, когда фокусировать ещё нечего.\nwatch(\n [() => props.modelValue, cancelButtonRef, confirmButtonRef],\n () => {\n if (!props.modelValue || props.focusAction === 'none')\n return\n focusAction()\n },\n // `immediate`: окно могут смонтировать уже открытым — смены пропа тогда нет.\n { immediate: true, flush: 'post' },\n)\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n emit('confirm')\n if (props.closeOnConfirm)\n emit('update:modelValue', false)\n}\n\ndefineSlots<{\n /** Содержимое диалога вместо пропа `message`. */\n default?: () => any\n /** Разбор ошибки вместо встроенного баннера. */\n error?: (props: { error: ResponseErrorInfo | null }) => any\n /** Кнопки диалога вместо пары «отмена и подтверждение». */\n footer?: () => any\n}>()\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"resolvedTitle\"\n :size=\"resolvedSize\"\n :close-on-backdrop=\"resolvedCloseOnBackdrop\"\n :close-on-esc=\"resolvedCloseOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"resolvedCloseLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)] text-[var(--gr-muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <slot name=\"error\" :error=\"error\">\n <GrResponseErrorBanner v-if=\"error\" :error=\"error\" :can-dismiss=\"false\" />\n </slot>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton ref=\"cancelButtonRef\" data-testid=\"gr-confirm-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ resolvedCancelText }}\n </GrButton>\n <GrButton\n ref=\"confirmButtonRef\"\n data-testid=\"gr-confirm-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :loading=\"confirmLoading\"\n :disabled=\"confirmDisabled\"\n @click=\"onConfirm\"\n >\n {{ resolvedConfirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqFA,MAAM,QAAQ;EA4Bd,MAAM,eAAe,mBAAmB,mBAAmB,cAAc,MAAM,MAAM,IAAI;EAEzF,MAAM,OAAO;EAGb,MAAM,EAAE,MAAM,2BAA2B;EACzC,MAAM,gBAAgB,eAAe,MAAM,SAAS,EAAE,2BAA2B,SAAS,CAAC;EAC3F,MAAM,qBAAqB,eAAe,MAAM,cAAc,EAAE,mBAAmB,OAAO,CAAC;EAC3F,MAAM,sBAAsB,eAAe,MAAM,eAAe,EAAE,qBAAqB,SAAS,CAAC;EACjG,MAAM,qBAAqB,eAAe,MAAM,cAAc,EAAE,oBAAoB,QAAQ,CAAC;EAE7F,MAAM,OAAO,SAAS;GACpB,WAAW,MAAM;GACjB,MAAM,UAAmB,KAAK,qBAAqB,KAAK;EAC1D,CAAC;EAED,MAAM,mBAAmB,IAA0C,IAAI;EACvE,MAAM,kBAAkB,IAA0C,IAAI;EAGtE,MAAM,mBAAmB,eAAe,MAAM,cAAc,MAAM,cAAc;EAChF,MAAM,0BAA0B,eAAgB,iBAAiB,QAAQ,QAAQ,MAAM,eAAgB;EACvG,MAAM,qBAAqB,eAAgB,iBAAiB,QAAQ,QAAQ,MAAM,UAAW;;;;;;;;;;EAW7F,SAAS,cAAoB;GAC3B,IAAI,MAAM,gBAAgB,WACxB,iBAAiB,OAAO,MAAM;QAC3B,IAAI,MAAM,gBAAgB,UAC7B,gBAAgB,OAAO,MAAM;EACjC;EAKA,MACE;SAAO,MAAM;GAAY;GAAiB;EAAgB,SACpD;GACJ,IAAI,CAAC,MAAM,cAAc,MAAM,gBAAgB,QAC7C;GACF,YAAY;EACd,GAEA;GAAE,WAAW;GAAM,OAAO;EAAO,CACnC;EAEA,SAAS,WAAiB;GACxB,KAAK,QAAQ;GACb,KAAK,qBAAqB,KAAK;EACjC;EAEA,SAAS,YAAkB;GACzB,KAAK,SAAS;GACd,IAAI,MAAM,gBACR,KAAK,qBAAqB,KAAK;EACnC;;uBAaE,YA8CW,kBAAA;gBA7CA,KAAA;sEAAI,QAAA;IACZ,OAAO,cAAA;IACP,MAAM,MAAA,YAAA;IACN,qBAAmB,wBAAA;IACnB,gBAAc,mBAAA;IACd,eAAa,QAAA;IACb,qBAAmB,QAAA;IACnB,iBAAe,QAAA;IACf,iBAAe,QAAA;IACf,eAAa,QAAA;IACb,eAAa,mBAAA;;IAcH,QAAM,cAmBR,CAlBP,WAkBO,KAAA,QAAA,UAAA,CAAA,SAAA,CAjBL,mBAgBM,OAhBN,YAgBM,CAfJ,YAEW,kBAAA;cAFG;KAAJ,KAAI;KAAkB,eAAY;KAAoB,SAAQ;KAAW,MAAM,QAAA;KAAa,SAAO;;4BACnF,CAAA,gBAAA,gBAArB,mBAAA,KAAkB,GAAA,CAAA,CAAA,CAAA;;qBAEvB,YAWW,kBAAA;cAVL;KAAJ,KAAI;KACJ,eAAY;KACX,SAAS,QAAA;KACT,MAAM,QAAA;KACN,MAAM,QAAA;KACN,SAAS,QAAA;KACT,UAAU,QAAA;KACV,SAAO;;4BAEiB,CAAA,gBAAA,gBAAtB,oBAAA,KAAmB,GAAA,CAAA,CAAA,CAAA;;;;;;;;;2BAlBxB,CAVN,mBAUM,OAVN,YAUM,CATJ,WAIO,KAAA,QAAA,WAAA,CAAA,SAAA,CAHM,QAAA,eAAA,UAAA,GAAX,mBAEM,OAFN,YAEM,gBADD,QAAA,WAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,GAIlB,WAEO,KAAA,QAAA,SAAA,EAFa,OAAO,QAAA,MAAK,SAEzB,CADwB,QAAA,SAAA,UAAA,GAA7B,YAA0E,+BAAA;;KAArC,OAAO,QAAA;KAAQ,eAAa"}
|
|
1
|
+
{"version":3,"file":"GrConfirmDialog-jRDs_E6C.js","names":[],"sources":["../../../../src/components/GrConfirmDialog/GrConfirmDialog.vue","../../../../src/components/GrConfirmDialog/GrConfirmDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrConfirmDialog — GR-примитив диалога подтверждения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog`/`GrPromptDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Клик по «Confirm»/«Cancel» эмитит одноимённое событие и закрывает диалог\n * через `update:modelValue`.\n */\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrResponseErrorBanner from '../GrResponseErrorBanner/GrResponseErrorBanner.vue'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\nimport type { ResponseErrorInfo } from '../GrResponseErrorBanner'\n\n/** Какое действие получает фокус при открытии окна. */\nexport type GrConfirmDialogFocusAction = 'confirm' | 'cancel' | 'none'\n\nexport interface GrConfirmDialogProps {\n modelValue: boolean\n title?: string\n description?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n /**\n * Структура ошибки ответа сервера для показа в теле диалога\n * (через `GrResponseErrorBanner`). Используется императивным\n * `useDialogService` для async-`onConfirm`. `null` — блок скрыт.\n */\n error?: ResponseErrorInfo | null\n /** Состояние загрузки кнопки Confirm (async-`onConfirm` in-flight). */\n confirmLoading?: boolean\n /** Принудительно дизейблит кнопку Confirm. */\n confirmDisabled?: boolean\n /**\n * Закрывать ли диалог автоматически по клику Confirm. По умолчанию `true`\n * (историческое поведение). `false` — отдаёт управление закрытием наружу\n * (нужно `useDialogService`, который ждёт результат async-`onConfirm`).\n */\n closeOnConfirm?: boolean\n /**\n * Какое действие получает фокус при открытии. По умолчанию «Отмена»:\n * подтверждение бывает деструктивным, и `Enter` сразу после открытия не\n * должен его запускать. `none` оставляет фокус на панели окна.\n *\n * Имя не `initialFocus` намеренно: у `GrModal`/`GrDrawer` так называется\n * проп с элементом, а здесь выбирается действие.\n */\n focusAction?: GrConfirmDialogFocusAction\n /**\n * Запрет закрытия «мягкими» способами (Esc, клик по бэкдропу), пока идёт\n * подтверждение (`confirmLoading`). Кнопка закрытия и «Отмена» остаются:\n * окно без единого выхода — ловушка.\n */\n persistent?: boolean\n}\n\nexport interface GrConfirmDialogEmits {\n (e: 'update:modelValue', value: boolean): void\n (e: 'confirm'): void\n (e: 'cancel'): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(defineProps<GrConfirmDialogProps>(), {\n title: undefined,\n description: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: undefined,\n buttonSize: undefined,\n confirmText: undefined,\n cancelText: undefined,\n confirmVariant: 'primary',\n confirmTone: 'primary',\n error: null,\n confirmLoading: false,\n confirmDisabled: false,\n closeOnConfirm: true,\n focusAction: 'cancel',\n persistent: false,\n})\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentProp('GrConfirmDialog', 'size', () => props.size, 'md')\n\nconst emit = defineEmits<GrConfirmDialogEmits>()\n\n// Дефолты берём из общего i18n-блока пакета (fallback — англ.), а не хардкодим.\nconst { t } = useGranularityTranslations()\nconst resolvedTitle = computed(() => props.title ?? t('gr.dialog.confirm.title', 'Confirm'))\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.common.close', 'Close'))\nconst resolvedConfirmText = computed(() => props.confirmText ?? t('gr.common.confirm', 'Confirm'))\nconst resolvedCancelText = computed(() => props.cancelText ?? t('gr.common.cancel', 'Cancel'))\n\nconst open = computed({\n get: () => props.modelValue,\n set: (value: boolean) => emit('update:modelValue', value),\n})\n\nconst confirmButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\nconst cancelButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\n\n// Пока подтверждение в полёте, случайное движение не должно оборвать операцию.\nconst softCloseBlocked = computed(() => props.persistent && props.confirmLoading)\nconst resolvedCloseOnBackdrop = computed(() => (softCloseBlocked.value ? false : props.closeOnBackdrop))\nconst resolvedCloseOnEsc = computed(() => (softCloseBlocked.value ? false : props.closeOnEsc))\n\n/**\n * Фокус ставит содержимое после отрисовки, а не проп `initialFocus` у\n * `GrModal`: кнопка рождается внутри поддерева диалога, и возврат её же пропом\n * наверх замыкает рендер в цикл (проверено на `GrPromptDialog`).\n *\n * Молчит, когда фокусировать нечего: со своим слотом `#footer` кнопок с\n * рефами в DOM нет, и фокус остаётся на панели — это корректный исход, а не\n * повод падать.\n */\nfunction focusAction(): void {\n if (props.focusAction === 'confirm')\n confirmButtonRef.value?.focus()\n else if (props.focusAction === 'cancel')\n cancelButtonRef.value?.focus()\n}\n\n// Источник — не только `modelValue`, но и сами кнопки: содержимое панели\n// появляется на такт позже открытия, и фокус по фиксированному `nextTick`\n// приходился на момент, когда фокусировать ещё нечего.\nwatch(\n [() => props.modelValue, cancelButtonRef, confirmButtonRef],\n () => {\n if (!props.modelValue || props.focusAction === 'none')\n return\n focusAction()\n },\n // `immediate`: окно могут смонтировать уже открытым — смены пропа тогда нет.\n { immediate: true, flush: 'post' },\n)\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n emit('confirm')\n if (props.closeOnConfirm)\n emit('update:modelValue', false)\n}\n\ndefineSlots<{\n /** Содержимое диалога вместо пропа `message`. */\n default?: () => any\n /** Разбор ошибки вместо встроенного баннера. */\n error?: (props: { error: ResponseErrorInfo | null }) => any\n /** Кнопки диалога вместо пары «отмена и подтверждение». */\n footer?: () => any\n}>()\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"resolvedTitle\"\n :size=\"resolvedSize\"\n :close-on-backdrop=\"resolvedCloseOnBackdrop\"\n :close-on-esc=\"resolvedCloseOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"resolvedCloseLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)] text-[var(--gr-muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <slot name=\"error\" :error=\"error\">\n <GrResponseErrorBanner v-if=\"error\" :error=\"error\" :can-dismiss=\"false\" />\n </slot>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton ref=\"cancelButtonRef\" data-testid=\"gr-confirm-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ resolvedCancelText }}\n </GrButton>\n <GrButton\n ref=\"confirmButtonRef\"\n data-testid=\"gr-confirm-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :loading=\"confirmLoading\"\n :disabled=\"confirmDisabled\"\n @click=\"onConfirm\"\n >\n {{ resolvedConfirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrConfirmDialog — GR-примитив диалога подтверждения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog`/`GrPromptDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Клик по «Confirm»/«Cancel» эмитит одноимённое событие и закрывает диалог\n * через `update:modelValue`.\n */\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrResponseErrorBanner from '../GrResponseErrorBanner/GrResponseErrorBanner.vue'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\nimport type { ResponseErrorInfo } from '../GrResponseErrorBanner'\n\n/** Какое действие получает фокус при открытии окна. */\nexport type GrConfirmDialogFocusAction = 'confirm' | 'cancel' | 'none'\n\nexport interface GrConfirmDialogProps {\n modelValue: boolean\n title?: string\n description?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n /**\n * Структура ошибки ответа сервера для показа в теле диалога\n * (через `GrResponseErrorBanner`). Используется императивным\n * `useDialogService` для async-`onConfirm`. `null` — блок скрыт.\n */\n error?: ResponseErrorInfo | null\n /** Состояние загрузки кнопки Confirm (async-`onConfirm` in-flight). */\n confirmLoading?: boolean\n /** Принудительно дизейблит кнопку Confirm. */\n confirmDisabled?: boolean\n /**\n * Закрывать ли диалог автоматически по клику Confirm. По умолчанию `true`\n * (историческое поведение). `false` — отдаёт управление закрытием наружу\n * (нужно `useDialogService`, который ждёт результат async-`onConfirm`).\n */\n closeOnConfirm?: boolean\n /**\n * Какое действие получает фокус при открытии. По умолчанию «Отмена»:\n * подтверждение бывает деструктивным, и `Enter` сразу после открытия не\n * должен его запускать. `none` оставляет фокус на панели окна.\n *\n * Имя не `initialFocus` намеренно: у `GrModal`/`GrDrawer` так называется\n * проп с элементом, а здесь выбирается действие.\n */\n focusAction?: GrConfirmDialogFocusAction\n /**\n * Запрет закрытия «мягкими» способами (Esc, клик по бэкдропу), пока идёт\n * подтверждение (`confirmLoading`). Кнопка закрытия и «Отмена» остаются:\n * окно без единого выхода — ловушка.\n */\n persistent?: boolean\n}\n\nexport interface GrConfirmDialogEmits {\n (e: 'update:modelValue', value: boolean): void\n (e: 'confirm'): void\n (e: 'cancel'): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(defineProps<GrConfirmDialogProps>(), {\n title: undefined,\n description: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: undefined,\n buttonSize: undefined,\n confirmText: undefined,\n cancelText: undefined,\n confirmVariant: 'primary',\n confirmTone: 'primary',\n error: null,\n confirmLoading: false,\n confirmDisabled: false,\n closeOnConfirm: true,\n focusAction: 'cancel',\n persistent: false,\n})\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentProp('GrConfirmDialog', 'size', () => props.size, 'md')\n\nconst emit = defineEmits<GrConfirmDialogEmits>()\n\n// Дефолты берём из общего i18n-блока пакета (fallback — англ.), а не хардкодим.\nconst { t } = useGranularityTranslations()\nconst resolvedTitle = computed(() => props.title ?? t('gr.dialog.confirm.title', 'Confirm'))\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.common.close', 'Close'))\nconst resolvedConfirmText = computed(() => props.confirmText ?? t('gr.common.confirm', 'Confirm'))\nconst resolvedCancelText = computed(() => props.cancelText ?? t('gr.common.cancel', 'Cancel'))\n\nconst open = computed({\n get: () => props.modelValue,\n set: (value: boolean) => emit('update:modelValue', value),\n})\n\nconst confirmButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\nconst cancelButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\n\n// Пока подтверждение в полёте, случайное движение не должно оборвать операцию.\nconst softCloseBlocked = computed(() => props.persistent && props.confirmLoading)\nconst resolvedCloseOnBackdrop = computed(() => (softCloseBlocked.value ? false : props.closeOnBackdrop))\nconst resolvedCloseOnEsc = computed(() => (softCloseBlocked.value ? false : props.closeOnEsc))\n\n/**\n * Фокус ставит содержимое после отрисовки, а не проп `initialFocus` у\n * `GrModal`: кнопка рождается внутри поддерева диалога, и возврат её же пропом\n * наверх замыкает рендер в цикл (проверено на `GrPromptDialog`).\n *\n * Молчит, когда фокусировать нечего: со своим слотом `#footer` кнопок с\n * рефами в DOM нет, и фокус остаётся на панели — это корректный исход, а не\n * повод падать.\n */\nfunction focusAction(): void {\n if (props.focusAction === 'confirm')\n confirmButtonRef.value?.focus()\n else if (props.focusAction === 'cancel')\n cancelButtonRef.value?.focus()\n}\n\n// Источник — не только `modelValue`, но и сами кнопки: содержимое панели\n// появляется на такт позже открытия, и фокус по фиксированному `nextTick`\n// приходился на момент, когда фокусировать ещё нечего.\nwatch(\n [() => props.modelValue, cancelButtonRef, confirmButtonRef],\n () => {\n if (!props.modelValue || props.focusAction === 'none')\n return\n focusAction()\n },\n // `immediate`: окно могут смонтировать уже открытым — смены пропа тогда нет.\n { immediate: true, flush: 'post' },\n)\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n emit('confirm')\n if (props.closeOnConfirm)\n emit('update:modelValue', false)\n}\n\ndefineSlots<{\n /** Содержимое диалога вместо пропа `message`. */\n default?: () => any\n /** Разбор ошибки вместо встроенного баннера. */\n error?: (props: { error: ResponseErrorInfo | null }) => any\n /** Кнопки диалога вместо пары «отмена и подтверждение». */\n footer?: () => any\n}>()\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"resolvedTitle\"\n :size=\"resolvedSize\"\n :close-on-backdrop=\"resolvedCloseOnBackdrop\"\n :close-on-esc=\"resolvedCloseOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"resolvedCloseLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)] text-[var(--gr-muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <slot name=\"error\" :error=\"error\">\n <GrResponseErrorBanner v-if=\"error\" :error=\"error\" :can-dismiss=\"false\" />\n </slot>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton ref=\"cancelButtonRef\" data-testid=\"gr-confirm-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ resolvedCancelText }}\n </GrButton>\n <GrButton\n ref=\"confirmButtonRef\"\n data-testid=\"gr-confirm-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :loading=\"confirmLoading\"\n :disabled=\"confirmDisabled\"\n @click=\"onConfirm\"\n >\n {{ resolvedConfirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqFA,MAAM,QAAQ;EA4Bd,MAAM,eAAe,mBAAmB,mBAAmB,cAAc,MAAM,MAAM,IAAI;EAEzF,MAAM,OAAO;EAGb,MAAM,EAAE,MAAM,2BAA2B;EACzC,MAAM,gBAAgB,eAAe,MAAM,SAAS,EAAE,2BAA2B,SAAS,CAAC;EAC3F,MAAM,qBAAqB,eAAe,MAAM,cAAc,EAAE,mBAAmB,OAAO,CAAC;EAC3F,MAAM,sBAAsB,eAAe,MAAM,eAAe,EAAE,qBAAqB,SAAS,CAAC;EACjG,MAAM,qBAAqB,eAAe,MAAM,cAAc,EAAE,oBAAoB,QAAQ,CAAC;EAE7F,MAAM,OAAO,SAAS;GACpB,WAAW,MAAM;GACjB,MAAM,UAAmB,KAAK,qBAAqB,KAAK;EAC1D,CAAC;EAED,MAAM,mBAAmB,IAA0C,IAAI;EACvE,MAAM,kBAAkB,IAA0C,IAAI;EAGtE,MAAM,mBAAmB,eAAe,MAAM,cAAc,MAAM,cAAc;EAChF,MAAM,0BAA0B,eAAgB,iBAAiB,QAAQ,QAAQ,MAAM,eAAgB;EACvG,MAAM,qBAAqB,eAAgB,iBAAiB,QAAQ,QAAQ,MAAM,UAAW;;;;;;;;;;EAW7F,SAAS,cAAoB;GAC3B,IAAI,MAAM,gBAAgB,WACxB,iBAAiB,OAAO,MAAM;QAC3B,IAAI,MAAM,gBAAgB,UAC7B,gBAAgB,OAAO,MAAM;EACjC;EAKA,MACE;SAAO,MAAM;GAAY;GAAiB;EAAgB,SACpD;GACJ,IAAI,CAAC,MAAM,cAAc,MAAM,gBAAgB,QAC7C;GACF,YAAY;EACd,GAEA;GAAE,WAAW;GAAM,OAAO;EAAO,CACnC;EAEA,SAAS,WAAiB;GACxB,KAAK,QAAQ;GACb,KAAK,qBAAqB,KAAK;EACjC;EAEA,SAAS,YAAkB;GACzB,KAAK,SAAS;GACd,IAAI,MAAM,gBACR,KAAK,qBAAqB,KAAK;EACnC;;uBAaE,YA8CW,kBAAA;gBA7CA,KAAA;sEAAI,QAAA;IACZ,OAAO,cAAA;IACP,MAAM,MAAA,YAAA;IACN,qBAAmB,wBAAA;IACnB,gBAAc,mBAAA;IACd,eAAa,QAAA;IACb,qBAAmB,QAAA;IACnB,iBAAe,QAAA;IACf,iBAAe,QAAA;IACf,eAAa,QAAA;IACb,eAAa,mBAAA;;IAcH,QAAM,cAmBR,CAlBP,WAkBO,KAAA,QAAA,UAAA,CAAA,SAAA,CAjBL,mBAgBM,OAhBN,YAgBM,CAfJ,YAEW,kBAAA;cAFG;KAAJ,KAAI;KAAkB,eAAY;KAAoB,SAAQ;KAAW,MAAM,QAAA;KAAa,SAAO;;4BACnF,CAAA,gBAAA,gBAArB,mBAAA,KAAkB,GAAA,CAAA,CAAA,CAAA;;qBAEvB,YAWW,kBAAA;cAVL;KAAJ,KAAI;KACJ,eAAY;KACX,SAAS,QAAA;KACT,MAAM,QAAA;KACN,MAAM,QAAA;KACN,SAAS,QAAA;KACT,UAAU,QAAA;KACV,SAAO;;4BAEiB,CAAA,gBAAA,gBAAtB,oBAAA,KAAmB,GAAA,CAAA,CAAA,CAAA;;;;;;;;;2BAlBxB,CAVN,mBAUM,OAVN,YAUM,CATJ,WAIO,KAAA,QAAA,WAAA,CAAA,SAAA,CAHM,QAAA,eAAA,UAAA,GAAX,mBAEM,OAFN,YAEM,gBADD,QAAA,WAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,GAIlB,WAEO,KAAA,QAAA,SAAA,EAFa,OAAO,QAAA,MAAK,SAEzB,CADwB,QAAA,SAAA,UAAA,GAA7B,YAA0E,+BAAA;;KAArC,OAAO,QAAA;KAAQ,eAAa"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as GrConfirmDialog_default } from "./chunks/GrConfirmDialog-
|
|
1
|
+
import { t as GrConfirmDialog_default } from "./chunks/GrConfirmDialog-jRDs_E6C.js";
|
|
2
2
|
import { t as grConfirmDialogConfig } from "../../chunks/config-A-bBiotF.js";
|
|
3
3
|
export { GrConfirmDialog_default as GrConfirmDialog, GrConfirmDialog_default as default, grConfirmDialogConfig };
|
package/dist/components/GrContextMenu/chunks/{GrContextMenu-ClkVjdcP.js → GrContextMenu-CWmgrzpi.js}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
|
|
2
2
|
import { i as isEditableTarget } from "../../../chunks/keyboard-DE2yhz_b.js";
|
|
3
3
|
import { t as useControlledOpen } from "../../../chunks/useControlledOpen-DV3SqLTP.js";
|
|
4
|
-
import { t as GrPopover_default } from "../../GrPopover/chunks/GrPopover-
|
|
5
|
-
import { t as useMenuItemsFocus } from "../../../chunks/useMenuItemsFocus-
|
|
4
|
+
import { t as GrPopover_default } from "../../GrPopover/chunks/GrPopover-CzeXMcvh.js";
|
|
5
|
+
import { t as useMenuItemsFocus } from "../../../chunks/useMenuItemsFocus-B7Bl_aFA.js";
|
|
6
6
|
import { i as isMenuSection, n as GrDropdownMenuEntries_default, r as isMenuAction, t as GrDropdownMenuList_default } from "../../GrDropdownMenu/chunks/GrDropdownMenuList-B33ZzwfB.js";
|
|
7
7
|
import { computed, createCommentVNode, createElementBlock, createVNode, defineComponent, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, ref, renderSlot, unref, useSlots, watch, withCtx } from "vue";
|
|
8
8
|
//#region src/components/GrContextMenu/contextMenuAnchor.ts
|
|
@@ -121,6 +121,20 @@ var GrContextMenu_default = /* @__PURE__ */ defineComponent({
|
|
|
121
121
|
const resolvedAriaLabel = computed(() => props.ariaLabel ?? t("gr.contextMenu.label", "Context menu"));
|
|
122
122
|
const listStyle = computed(() => ({ minWidth: typeof props.minWidth === "number" ? `${props.minWidth}px` : props.minWidth }));
|
|
123
123
|
/**
|
|
124
|
+
* Потолок ширины панели снят: ширину меню определяет его собственный `minWidth`.
|
|
125
|
+
*
|
|
126
|
+
* По умолчанию `GrPopover` держит `22rem` — читаемую ширину колонки текста. Но
|
|
127
|
+
* `minWidth` этого меню лежит на списке **внутри** панели, а список не сжимается:
|
|
128
|
+
* `minWidth` крупнее потолка вылезал бы за скруглённый край панели наружу, потому
|
|
129
|
+
* что у неё `overflow: visible`. Замер: `min-width: 500px` при потолке 352px даёт
|
|
130
|
+
* вылет в 161px.
|
|
131
|
+
*
|
|
132
|
+
* Два предела на одну ширину — один снаружи, другой изнутри — противоречат друг
|
|
133
|
+
* другу по построению, поэтому внешний снимается. «Не шире вьюпорта» остаётся: он
|
|
134
|
+
* второй операнд `min()` и хуком не снимается.
|
|
135
|
+
*/
|
|
136
|
+
const panelClass = computed(() => ["[--gr-popover-max-width:100vw]", props.contentClass].filter(Boolean).join(" "));
|
|
137
|
+
/**
|
|
124
138
|
* Меню без единого действия не открывается: фокусировать в нём нечего, и оно
|
|
125
139
|
* становится ловушкой, из которой есть только Esc.
|
|
126
140
|
*/
|
|
@@ -284,7 +298,7 @@ var GrContextMenu_default = /* @__PURE__ */ defineComponent({
|
|
|
284
298
|
placement: __props.placement,
|
|
285
299
|
"offset-px": __props.offsetPx,
|
|
286
300
|
"teleport-to": __props.teleportTo,
|
|
287
|
-
"content-class":
|
|
301
|
+
"content-class": panelClass.value,
|
|
288
302
|
"aria-label": __props.labelledBy ? void 0 : resolvedAriaLabel.value,
|
|
289
303
|
"labelled-by": __props.labelledBy,
|
|
290
304
|
role: "menu",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GrContextMenu-CWmgrzpi.js","names":[],"sources":["../../../../src/components/GrContextMenu/contextMenuAnchor.ts","../../../../src/components/GrContextMenu/GrContextMenu.vue","../../../../src/components/GrContextMenu/GrContextMenu.vue"],"sourcesContent":["import type { GrFloatingAnchorRect } from '../../composables/useFloating'\n\n/** Точка курсора — якорь нулевого размера. */\nexport function anchorFromPointer(event: MouseEvent): GrFloatingAnchorRect {\n return { x: event.clientX, y: event.clientY }\n}\n\n/**\n * Прямоугольник элемента — якорь клавиатурного вызова.\n *\n * Не угол и не точка: меню, вызванное с клавиатуры, принадлежит **строке**, и\n * при нехватке места снизу обязано перевернуться относительно неё целиком.\n */\nexport function anchorFromElement(element: Element): GrFloatingAnchorRect {\n const rect = element.getBoundingClientRect()\n\n return { x: rect.left, y: rect.top, width: rect.width, height: rect.height }\n}\n\n/**\n * `contextmenu` пришёл с клавиатуры, а не от мыши.\n *\n * Браузеры порождают это событие и для `Shift+F10`, но координаты в нём\n * бесполезны: то угол элемента, то нули. Признаков два сразу, потому что по\n * отдельности каждый ошибается — правый клик всегда `button === 2`, а\n * клавиатурный вызов всегда без «числа кликов».\n */\nexport function isKeyboardContextMenu(event: MouseEvent): boolean {\n return event.button !== 2 && event.detail === 0\n}\n\n/**\n * Пользователь просит нативное меню браузера.\n *\n * `Shift`+правый клик — де-факто escape-hatch, в Firefox задокументированный.\n * `ctrlKey` сюда не входит намеренно: на macOS Ctrl+клик **и есть** правый\n * клик, и меню перестало бы открываться у части пользователей.\n */\nexport function wantsNativeMenu(event: MouseEvent): boolean {\n return event.shiftKey\n}\n\n/** Клавиатурный запрос контекстного меню: `Shift+F10` или клавиша `ContextMenu`. */\nexport function isContextMenuKey(event: KeyboardEvent): boolean {\n return event.key === 'ContextMenu' || (event.key === 'F10' && event.shiftKey)\n}\n","<script setup lang=\"ts\">\n/**\n * GrContextMenu — меню по правому клику.\n *\n * Отличие от `GrDropdownMenu` не в содержимом, а в том, откуда меню растёт: у\n * дропдауна есть триггер-элемент, здесь — точка курсора, которой в DOM нет.\n * Поэтому слой берётся у `GrPopover` в якорном режиме, а не собирается заново.\n *\n * A11y: панель — `role=\"menu\"` с доступным именем, пункты приезжают из\n * `GrDropdownMenu` вместе со своими ролями. Меню, открываемое только правым\n * кликом, недоступно с клавиатуры, поэтому обёртка ловит `Shift+F10` и клавишу\n * `ContextMenu` — это условие приёмки, а не удобство.\n */\nimport { computed, nextTick, onBeforeUnmount, ref, useSlots, watch } from 'vue'\n\nimport { useControlledOpen } from '../../composables/internal/useControlledOpen'\nimport { useMenuItemsFocus } from '../../composables/internal/useMenuItemsFocus'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { isEditableTarget } from '../../internal/keyboard'\nimport GrDropdownMenuEntries from '../GrDropdownMenu/GrDropdownMenuEntries.vue'\nimport GrDropdownMenuList from '../GrDropdownMenu/GrDropdownMenuList.vue'\nimport type { GrDropdownMenuAction, GrDropdownMenuEntry } from '../GrDropdownMenu/menuModel'\nimport { isMenuAction, isMenuSection } from '../GrDropdownMenu/menuModel'\nimport GrPopover from '../GrPopover/GrPopover.vue'\nimport type { GrFloatingAnchorRect, UseFloatingPlacement } from '../../composables/useFloating'\n\nimport {\n anchorFromElement,\n anchorFromPointer,\n isContextMenuKey,\n isKeyboardContextMenu,\n wantsNativeMenu,\n} from './contextMenuAnchor'\n\n/** Чем открывается меню. `manual` — только императивно, из кода потребителя. */\nexport type GrContextMenuTrigger = 'contextmenu' | 'manual'\n\n/** Откуда пришло открытие: указатель, клавиатура или вызов из кода. */\nexport type GrContextMenuSource = 'pointer' | 'keyboard' | 'api'\n\nexport interface GrContextMenuOpenContext {\n source: GrContextMenuSource\n /** По чему кликнули или что было в фокусе — отсюда потребитель берёт строку. */\n target: HTMLElement | null\n anchor: GrFloatingAnchorRect\n event: MouseEvent | KeyboardEvent | null\n}\n\nexport interface GrContextMenuProps {\n /** Декларативное меню. Слот `#content` сильнее. */\n items?: GrDropdownMenuEntry[]\n /** Открыто ли меню. Без пропа компонент ведёт состояние сам. */\n open?: boolean\n trigger?: GrContextMenuTrigger\n disabled?: boolean\n placement?: UseFloatingPlacement\n /** Зазор от якоря. Ноль по умолчанию: меню липнет к курсору. */\n offsetPx?: number\n /** Меню из коротких слов не должно быть шириной в слово. */\n minWidth?: number | string\n ariaLabel?: string\n labelledBy?: string\n teleportTo?: string | HTMLElement\n contentClass?: string\n listClass?: string\n dividers?: boolean\n /**\n * Закрывать при прокрутке страницы. Якорь — точка вьюпорта, и панель осталась\n * бы висеть на экране, пока контент под ней уезжает. Так же ведут себя\n * нативные меню.\n */\n closeOnScroll?: boolean\n /** Пропускать `Shift`+правый клик к браузеру. */\n allowNativeMenu?: boolean\n}\n\nexport interface GrContextMenuEmits {\n (e: 'update:open', value: boolean): void\n /**\n * Меню собирается открыться у этой цели. Приходит **до** открытия, чтобы\n * потребитель успел пересобрать `items` под неё: пункты для папки и для файла\n * разные, а узнать цель иначе неоткуда. Пустая модель после этого просто не\n * откроется — отдельный способ отменить открытие не нужен.\n */\n (e: 'beforeOpen', context: GrContextMenuOpenContext): void\n (e: 'select', item: GrDropdownMenuAction): void\n}\n\nconst props = withDefaults(defineProps<GrContextMenuProps>(), {\n items: undefined,\n open: undefined,\n trigger: 'contextmenu',\n disabled: false,\n placement: 'bottom-start',\n offsetPx: 0,\n minWidth: '11rem',\n ariaLabel: undefined,\n labelledBy: undefined,\n teleportTo: undefined,\n contentClass: undefined,\n listClass: undefined,\n dividers: false,\n closeOnScroll: true,\n allowNativeMenu: true,\n})\n\nconst emit = defineEmits<GrContextMenuEmits>()\n\nconst slots = useSlots()\nconst { t } = useGranularityTranslations()\n\nconst { open: isOpen, setOpen } = useControlledOpen(\n () => props.open,\n next => emit('update:open', next),\n)\n\nconst areaEl = ref<HTMLElement | null>(null)\nconst listRef = ref<{ $el?: HTMLElement } | null>(null)\nconst anchor = ref<GrFloatingAnchorRect | null>(null)\n\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.contextMenu.label', 'Context menu'))\n\nconst listStyle = computed(() => ({\n minWidth: typeof props.minWidth === 'number' ? `${props.minWidth}px` : props.minWidth,\n}))\n\n/**\n * Потолок ширины панели снят: ширину меню определяет его собственный `minWidth`.\n *\n * По умолчанию `GrPopover` держит `22rem` — читаемую ширину колонки текста. Но\n * `minWidth` этого меню лежит на списке **внутри** панели, а список не сжимается:\n * `minWidth` крупнее потолка вылезал бы за скруглённый край панели наружу, потому\n * что у неё `overflow: visible`. Замер: `min-width: 500px` при потолке 352px даёт\n * вылет в 161px.\n *\n * Два предела на одну ширину — один снаружи, другой изнутри — противоречат друг\n * другу по построению, поэтому внешний снимается. «Не шире вьюпорта» остаётся: он\n * второй операнд `min()` и хуком не снимается.\n */\nconst panelClass = computed(() => ['[--gr-popover-max-width:100vw]', props.contentClass].filter(Boolean).join(' '))\n\n/**\n * Меню без единого действия не открывается: фокусировать в нём нечего, и оно\n * становится ловушкой, из которой есть только Esc.\n */\nconst isEmpty = computed(() => {\n if (slots.content)\n return false\n\n return (props.items ?? []).every(entry => !isMenuAction(entry)\n && (!isMenuSection(entry) || entry.items.length === 0))\n})\n\nconst menu = useMenuItemsFocus({\n container: () => listRef.value?.$el ?? null,\n close: () => close(),\n})\n\nfunction panelOf(): HTMLElement | null {\n return listRef.value?.$el?.closest('[data-gr-popover-panel]') ?? null\n}\n\nfunction isInsidePanel(target: EventTarget | null): boolean {\n return target instanceof Node && (panelOf()?.contains(target) ?? false)\n}\n\nasync function openWith(context: GrContextMenuOpenContext): Promise<void> {\n if (props.disabled)\n return\n\n anchor.value = context.anchor\n emit('beforeOpen', context)\n\n // Тик между уведомлением и открытием — не перестраховка: `items` доезжают сюда\n // пропом, то есть следующим рендером родителя. Без ожидания меню под узел\n // дерева открылось бы с пунктами от предыдущей цели.\n await nextTick()\n\n if (isEmpty.value)\n return\n\n setOpen(true)\n\n await nextTick()\n menu.focusAt(0)\n}\n\n/** Открыть у точки курсора или у произвольного прямоугольника вьюпорта. */\nfunction openAt(at: MouseEvent | GrFloatingAnchorRect): void {\n const fromPointer = at instanceof MouseEvent\n\n void openWith({\n source: fromPointer ? 'pointer' : 'api',\n target: fromPointer ? (at.target as HTMLElement | null) : null,\n anchor: fromPointer ? anchorFromPointer(at) : at,\n event: fromPointer ? at : null,\n })\n}\n\n/** Открыть у прямоугольника элемента — клавиатурный путь для внешних композитов. */\nfunction openAtElement(element: Element): void {\n void openWith({\n source: 'api',\n target: element instanceof HTMLElement ? element : null,\n anchor: anchorFromElement(element),\n event: null,\n })\n}\n\nfunction open(): void {\n if (anchor.value)\n void openWith({ source: 'api', target: null, anchor: anchor.value, event: null })\n else if (areaEl.value)\n openAtElement(areaEl.value)\n}\n\nfunction close(): void {\n setOpen(false)\n menu.reset()\n}\n\nfunction toggle(): void {\n isOpen.value ? close() : open()\n}\n\nfunction onSelect(item: GrDropdownMenuAction): void {\n emit('select', item)\n}\n\nfunction onAreaContextMenu(event: MouseEvent): void {\n if (props.trigger !== 'contextmenu' || props.disabled)\n return\n\n if (props.allowNativeMenu && wantsNativeMenu(event))\n return\n\n event.preventDefault()\n // Вложенные области: побеждает ближайшая к цели, как в нативных приложениях.\n event.stopPropagation()\n\n if (isKeyboardContextMenu(event)) {\n const target = (document.activeElement as HTMLElement | null) ?? areaEl.value\n if (target)\n openAtElement(target)\n return\n }\n\n openAt(event)\n}\n\n/**\n * `trigger` здесь намеренно не проверяется: `manual` отключает открытие\n * указателем, а клавиатурный путь оставить обязан — иначе меню недоступно с\n * клавиатуры в принципе, и потребителю пришлось бы писать этот обработчик\n * заново на каждой странице.\n */\nfunction onAreaKeydown(event: KeyboardEvent): void {\n if (props.disabled)\n return\n\n if (!isContextMenuKey(event))\n return\n\n // В поле ввода нативное меню (орфография, буфер) полезнее нашего.\n if (isEditableTarget(event.target))\n return\n\n // Отмена keydown гасит `contextmenu`, который браузер породил бы следом:\n // без неё меню открылось бы дважды и второй раз — по координатам, а не по\n // прямоугольнику строки.\n event.preventDefault()\n\n const target = (document.activeElement as HTMLElement | null) ?? areaEl.value\n if (!target)\n return\n\n void openWith({\n source: 'keyboard',\n target,\n anchor: anchorFromElement(target),\n event,\n })\n}\n\n/**\n * Правый клик мимо меню его не закрывает: `v-click-outside` отбрасывает всё,\n * что не левая кнопка, а `contextmenu` вообще не порождает `click`. Ослаблять\n * директиву нельзя — гард бережёт дропдауны, — поэтому слушаем сами.\n */\nfunction onDocumentContextMenu(event: MouseEvent): void {\n if (isInsidePanel(event.target)) {\n event.preventDefault()\n return\n }\n\n // Внутри своей области меню не закрываем: обработчик области перенесёт его к\n // новой точке, а закрытие с последующим открытием мигало бы панелью.\n if (event.target instanceof Node && areaEl.value?.contains(event.target))\n return\n\n close()\n}\n\nfunction onDocumentScroll(event: Event): void {\n if (isInsidePanel(event.target))\n return\n\n close()\n}\n\nlet scrollFrame: number | undefined\n\nfunction stopListening(): void {\n if (scrollFrame !== undefined) {\n cancelAnimationFrame(scrollFrame)\n scrollFrame = undefined\n }\n\n window.removeEventListener('contextmenu', onDocumentContextMenu, true)\n window.removeEventListener('scroll', onDocumentScroll, true)\n}\n\nwatch(isOpen, (next) => {\n if (typeof window === 'undefined')\n return\n\n if (!next) {\n stopListening()\n return\n }\n\n window.addEventListener('contextmenu', onDocumentContextMenu, true)\n\n // Слушатель прокрутки — со следующего кадра: само открытие прокручивает\n // страницу (браузер подтягивает в вид то, по чему кликнули и что получило\n // фокус), и меню закрывало бы само себя ровно в момент появления.\n if (props.closeOnScroll) {\n scrollFrame = requestAnimationFrame(() => {\n scrollFrame = undefined\n window.addEventListener('scroll', onDocumentScroll, { capture: true, passive: true })\n })\n }\n})\n\nonBeforeUnmount(() => {\n if (typeof window === 'undefined')\n return\n\n stopListening()\n})\n\ndefineExpose({ openAt, openAtElement, open, close, toggle })\n\ndefineSlots<{\n /** Область, по которой вызывается меню. */\n default?: (props: { open: boolean }) => any\n /** Содержимое меню. */\n content?: (props: { close: () => void }) => any\n}>()\n</script>\n\n<template>\n <div data-gr-context-menu>\n <div\n v-if=\"slots.default\"\n ref=\"areaEl\"\n data-gr-context-menu-area\n @contextmenu=\"onAreaContextMenu\"\n @keydown=\"onAreaKeydown\"\n >\n <slot :open=\"isOpen\" />\n </div>\n\n <GrPopover\n :open=\"isOpen\"\n :anchor=\"anchor\"\n :placement=\"placement\"\n :offset-px=\"offsetPx\"\n :teleport-to=\"teleportTo\"\n :content-class=\"panelClass\"\n :aria-label=\"labelledBy ? undefined : resolvedAriaLabel\"\n :labelled-by=\"labelledBy\"\n role=\"menu\"\n trigger=\"manual\"\n padding=\"none\"\n close-on-content-click\n :auto-focus=\"false\"\n @update:open=\"setOpen($event)\"\n >\n <template #content=\"{ close: closePanel }\">\n <GrDropdownMenuList\n ref=\"listRef\"\n class=\"p-1\"\n :style=\"listStyle\"\n :dividers=\"dividers\"\n :class=\"listClass\"\n @keydown=\"menu.onKeydown\"\n >\n <slot name=\"content\" :close=\"closePanel\">\n <GrDropdownMenuEntries :items=\"items\" @select=\"onSelect\" />\n </slot>\n </GrDropdownMenuList>\n </template>\n </GrPopover>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrContextMenu — меню по правому клику.\n *\n * Отличие от `GrDropdownMenu` не в содержимом, а в том, откуда меню растёт: у\n * дропдауна есть триггер-элемент, здесь — точка курсора, которой в DOM нет.\n * Поэтому слой берётся у `GrPopover` в якорном режиме, а не собирается заново.\n *\n * A11y: панель — `role=\"menu\"` с доступным именем, пункты приезжают из\n * `GrDropdownMenu` вместе со своими ролями. Меню, открываемое только правым\n * кликом, недоступно с клавиатуры, поэтому обёртка ловит `Shift+F10` и клавишу\n * `ContextMenu` — это условие приёмки, а не удобство.\n */\nimport { computed, nextTick, onBeforeUnmount, ref, useSlots, watch } from 'vue'\n\nimport { useControlledOpen } from '../../composables/internal/useControlledOpen'\nimport { useMenuItemsFocus } from '../../composables/internal/useMenuItemsFocus'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { isEditableTarget } from '../../internal/keyboard'\nimport GrDropdownMenuEntries from '../GrDropdownMenu/GrDropdownMenuEntries.vue'\nimport GrDropdownMenuList from '../GrDropdownMenu/GrDropdownMenuList.vue'\nimport type { GrDropdownMenuAction, GrDropdownMenuEntry } from '../GrDropdownMenu/menuModel'\nimport { isMenuAction, isMenuSection } from '../GrDropdownMenu/menuModel'\nimport GrPopover from '../GrPopover/GrPopover.vue'\nimport type { GrFloatingAnchorRect, UseFloatingPlacement } from '../../composables/useFloating'\n\nimport {\n anchorFromElement,\n anchorFromPointer,\n isContextMenuKey,\n isKeyboardContextMenu,\n wantsNativeMenu,\n} from './contextMenuAnchor'\n\n/** Чем открывается меню. `manual` — только императивно, из кода потребителя. */\nexport type GrContextMenuTrigger = 'contextmenu' | 'manual'\n\n/** Откуда пришло открытие: указатель, клавиатура или вызов из кода. */\nexport type GrContextMenuSource = 'pointer' | 'keyboard' | 'api'\n\nexport interface GrContextMenuOpenContext {\n source: GrContextMenuSource\n /** По чему кликнули или что было в фокусе — отсюда потребитель берёт строку. */\n target: HTMLElement | null\n anchor: GrFloatingAnchorRect\n event: MouseEvent | KeyboardEvent | null\n}\n\nexport interface GrContextMenuProps {\n /** Декларативное меню. Слот `#content` сильнее. */\n items?: GrDropdownMenuEntry[]\n /** Открыто ли меню. Без пропа компонент ведёт состояние сам. */\n open?: boolean\n trigger?: GrContextMenuTrigger\n disabled?: boolean\n placement?: UseFloatingPlacement\n /** Зазор от якоря. Ноль по умолчанию: меню липнет к курсору. */\n offsetPx?: number\n /** Меню из коротких слов не должно быть шириной в слово. */\n minWidth?: number | string\n ariaLabel?: string\n labelledBy?: string\n teleportTo?: string | HTMLElement\n contentClass?: string\n listClass?: string\n dividers?: boolean\n /**\n * Закрывать при прокрутке страницы. Якорь — точка вьюпорта, и панель осталась\n * бы висеть на экране, пока контент под ней уезжает. Так же ведут себя\n * нативные меню.\n */\n closeOnScroll?: boolean\n /** Пропускать `Shift`+правый клик к браузеру. */\n allowNativeMenu?: boolean\n}\n\nexport interface GrContextMenuEmits {\n (e: 'update:open', value: boolean): void\n /**\n * Меню собирается открыться у этой цели. Приходит **до** открытия, чтобы\n * потребитель успел пересобрать `items` под неё: пункты для папки и для файла\n * разные, а узнать цель иначе неоткуда. Пустая модель после этого просто не\n * откроется — отдельный способ отменить открытие не нужен.\n */\n (e: 'beforeOpen', context: GrContextMenuOpenContext): void\n (e: 'select', item: GrDropdownMenuAction): void\n}\n\nconst props = withDefaults(defineProps<GrContextMenuProps>(), {\n items: undefined,\n open: undefined,\n trigger: 'contextmenu',\n disabled: false,\n placement: 'bottom-start',\n offsetPx: 0,\n minWidth: '11rem',\n ariaLabel: undefined,\n labelledBy: undefined,\n teleportTo: undefined,\n contentClass: undefined,\n listClass: undefined,\n dividers: false,\n closeOnScroll: true,\n allowNativeMenu: true,\n})\n\nconst emit = defineEmits<GrContextMenuEmits>()\n\nconst slots = useSlots()\nconst { t } = useGranularityTranslations()\n\nconst { open: isOpen, setOpen } = useControlledOpen(\n () => props.open,\n next => emit('update:open', next),\n)\n\nconst areaEl = ref<HTMLElement | null>(null)\nconst listRef = ref<{ $el?: HTMLElement } | null>(null)\nconst anchor = ref<GrFloatingAnchorRect | null>(null)\n\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.contextMenu.label', 'Context menu'))\n\nconst listStyle = computed(() => ({\n minWidth: typeof props.minWidth === 'number' ? `${props.minWidth}px` : props.minWidth,\n}))\n\n/**\n * Потолок ширины панели снят: ширину меню определяет его собственный `minWidth`.\n *\n * По умолчанию `GrPopover` держит `22rem` — читаемую ширину колонки текста. Но\n * `minWidth` этого меню лежит на списке **внутри** панели, а список не сжимается:\n * `minWidth` крупнее потолка вылезал бы за скруглённый край панели наружу, потому\n * что у неё `overflow: visible`. Замер: `min-width: 500px` при потолке 352px даёт\n * вылет в 161px.\n *\n * Два предела на одну ширину — один снаружи, другой изнутри — противоречат друг\n * другу по построению, поэтому внешний снимается. «Не шире вьюпорта» остаётся: он\n * второй операнд `min()` и хуком не снимается.\n */\nconst panelClass = computed(() => ['[--gr-popover-max-width:100vw]', props.contentClass].filter(Boolean).join(' '))\n\n/**\n * Меню без единого действия не открывается: фокусировать в нём нечего, и оно\n * становится ловушкой, из которой есть только Esc.\n */\nconst isEmpty = computed(() => {\n if (slots.content)\n return false\n\n return (props.items ?? []).every(entry => !isMenuAction(entry)\n && (!isMenuSection(entry) || entry.items.length === 0))\n})\n\nconst menu = useMenuItemsFocus({\n container: () => listRef.value?.$el ?? null,\n close: () => close(),\n})\n\nfunction panelOf(): HTMLElement | null {\n return listRef.value?.$el?.closest('[data-gr-popover-panel]') ?? null\n}\n\nfunction isInsidePanel(target: EventTarget | null): boolean {\n return target instanceof Node && (panelOf()?.contains(target) ?? false)\n}\n\nasync function openWith(context: GrContextMenuOpenContext): Promise<void> {\n if (props.disabled)\n return\n\n anchor.value = context.anchor\n emit('beforeOpen', context)\n\n // Тик между уведомлением и открытием — не перестраховка: `items` доезжают сюда\n // пропом, то есть следующим рендером родителя. Без ожидания меню под узел\n // дерева открылось бы с пунктами от предыдущей цели.\n await nextTick()\n\n if (isEmpty.value)\n return\n\n setOpen(true)\n\n await nextTick()\n menu.focusAt(0)\n}\n\n/** Открыть у точки курсора или у произвольного прямоугольника вьюпорта. */\nfunction openAt(at: MouseEvent | GrFloatingAnchorRect): void {\n const fromPointer = at instanceof MouseEvent\n\n void openWith({\n source: fromPointer ? 'pointer' : 'api',\n target: fromPointer ? (at.target as HTMLElement | null) : null,\n anchor: fromPointer ? anchorFromPointer(at) : at,\n event: fromPointer ? at : null,\n })\n}\n\n/** Открыть у прямоугольника элемента — клавиатурный путь для внешних композитов. */\nfunction openAtElement(element: Element): void {\n void openWith({\n source: 'api',\n target: element instanceof HTMLElement ? element : null,\n anchor: anchorFromElement(element),\n event: null,\n })\n}\n\nfunction open(): void {\n if (anchor.value)\n void openWith({ source: 'api', target: null, anchor: anchor.value, event: null })\n else if (areaEl.value)\n openAtElement(areaEl.value)\n}\n\nfunction close(): void {\n setOpen(false)\n menu.reset()\n}\n\nfunction toggle(): void {\n isOpen.value ? close() : open()\n}\n\nfunction onSelect(item: GrDropdownMenuAction): void {\n emit('select', item)\n}\n\nfunction onAreaContextMenu(event: MouseEvent): void {\n if (props.trigger !== 'contextmenu' || props.disabled)\n return\n\n if (props.allowNativeMenu && wantsNativeMenu(event))\n return\n\n event.preventDefault()\n // Вложенные области: побеждает ближайшая к цели, как в нативных приложениях.\n event.stopPropagation()\n\n if (isKeyboardContextMenu(event)) {\n const target = (document.activeElement as HTMLElement | null) ?? areaEl.value\n if (target)\n openAtElement(target)\n return\n }\n\n openAt(event)\n}\n\n/**\n * `trigger` здесь намеренно не проверяется: `manual` отключает открытие\n * указателем, а клавиатурный путь оставить обязан — иначе меню недоступно с\n * клавиатуры в принципе, и потребителю пришлось бы писать этот обработчик\n * заново на каждой странице.\n */\nfunction onAreaKeydown(event: KeyboardEvent): void {\n if (props.disabled)\n return\n\n if (!isContextMenuKey(event))\n return\n\n // В поле ввода нативное меню (орфография, буфер) полезнее нашего.\n if (isEditableTarget(event.target))\n return\n\n // Отмена keydown гасит `contextmenu`, который браузер породил бы следом:\n // без неё меню открылось бы дважды и второй раз — по координатам, а не по\n // прямоугольнику строки.\n event.preventDefault()\n\n const target = (document.activeElement as HTMLElement | null) ?? areaEl.value\n if (!target)\n return\n\n void openWith({\n source: 'keyboard',\n target,\n anchor: anchorFromElement(target),\n event,\n })\n}\n\n/**\n * Правый клик мимо меню его не закрывает: `v-click-outside` отбрасывает всё,\n * что не левая кнопка, а `contextmenu` вообще не порождает `click`. Ослаблять\n * директиву нельзя — гард бережёт дропдауны, — поэтому слушаем сами.\n */\nfunction onDocumentContextMenu(event: MouseEvent): void {\n if (isInsidePanel(event.target)) {\n event.preventDefault()\n return\n }\n\n // Внутри своей области меню не закрываем: обработчик области перенесёт его к\n // новой точке, а закрытие с последующим открытием мигало бы панелью.\n if (event.target instanceof Node && areaEl.value?.contains(event.target))\n return\n\n close()\n}\n\nfunction onDocumentScroll(event: Event): void {\n if (isInsidePanel(event.target))\n return\n\n close()\n}\n\nlet scrollFrame: number | undefined\n\nfunction stopListening(): void {\n if (scrollFrame !== undefined) {\n cancelAnimationFrame(scrollFrame)\n scrollFrame = undefined\n }\n\n window.removeEventListener('contextmenu', onDocumentContextMenu, true)\n window.removeEventListener('scroll', onDocumentScroll, true)\n}\n\nwatch(isOpen, (next) => {\n if (typeof window === 'undefined')\n return\n\n if (!next) {\n stopListening()\n return\n }\n\n window.addEventListener('contextmenu', onDocumentContextMenu, true)\n\n // Слушатель прокрутки — со следующего кадра: само открытие прокручивает\n // страницу (браузер подтягивает в вид то, по чему кликнули и что получило\n // фокус), и меню закрывало бы само себя ровно в момент появления.\n if (props.closeOnScroll) {\n scrollFrame = requestAnimationFrame(() => {\n scrollFrame = undefined\n window.addEventListener('scroll', onDocumentScroll, { capture: true, passive: true })\n })\n }\n})\n\nonBeforeUnmount(() => {\n if (typeof window === 'undefined')\n return\n\n stopListening()\n})\n\ndefineExpose({ openAt, openAtElement, open, close, toggle })\n\ndefineSlots<{\n /** Область, по которой вызывается меню. */\n default?: (props: { open: boolean }) => any\n /** Содержимое меню. */\n content?: (props: { close: () => void }) => any\n}>()\n</script>\n\n<template>\n <div data-gr-context-menu>\n <div\n v-if=\"slots.default\"\n ref=\"areaEl\"\n data-gr-context-menu-area\n @contextmenu=\"onAreaContextMenu\"\n @keydown=\"onAreaKeydown\"\n >\n <slot :open=\"isOpen\" />\n </div>\n\n <GrPopover\n :open=\"isOpen\"\n :anchor=\"anchor\"\n :placement=\"placement\"\n :offset-px=\"offsetPx\"\n :teleport-to=\"teleportTo\"\n :content-class=\"panelClass\"\n :aria-label=\"labelledBy ? undefined : resolvedAriaLabel\"\n :labelled-by=\"labelledBy\"\n role=\"menu\"\n trigger=\"manual\"\n padding=\"none\"\n close-on-content-click\n :auto-focus=\"false\"\n @update:open=\"setOpen($event)\"\n >\n <template #content=\"{ close: closePanel }\">\n <GrDropdownMenuList\n ref=\"listRef\"\n class=\"p-1\"\n :style=\"listStyle\"\n :dividers=\"dividers\"\n :class=\"listClass\"\n @keydown=\"menu.onKeydown\"\n >\n <slot name=\"content\" :close=\"closePanel\">\n <GrDropdownMenuEntries :items=\"items\" @select=\"onSelect\" />\n </slot>\n </GrDropdownMenuList>\n </template>\n </GrPopover>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as GrContextMenu_default } from "./chunks/GrContextMenu-
|
|
2
|
-
import { t as grContextMenuConfig } from "../../chunks/config-
|
|
1
|
+
import { t as GrContextMenu_default } from "./chunks/GrContextMenu-CWmgrzpi.js";
|
|
2
|
+
import { t as grContextMenuConfig } from "../../chunks/config-CsCUuukB.js";
|
|
3
3
|
export { GrContextMenu_default as GrContextMenu, GrContextMenu_default as default, grContextMenuConfig };
|
|
@@ -2,7 +2,7 @@ import { t as x_default } from "../../../chunks/x-2KXnqxiD.js";
|
|
|
2
2
|
import { i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
|
|
3
3
|
import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
|
|
4
4
|
import { t as GrButton_default } from "../../GrButton/chunks/GrButton-7GP0zObj.js";
|
|
5
|
-
import { n as useGrModalTitle, t as GrModal_default } from "../../GrModal/chunks/GrModal-
|
|
5
|
+
import { n as useGrModalTitle, t as GrModal_default } from "../../GrModal/chunks/GrModal-_JrDhon-.js";
|
|
6
6
|
import { a as resolveGrDialogTitle, i as resolveGrDialogSectionConfig, n as DEFAULT_GR_DIALOG_FOOTER_CONFIG, r as DEFAULT_GR_DIALOG_HEADER_CONFIG, t as DEFAULT_GR_DIALOG_BODY_CONFIG } from "../../../chunks/dialogShared-CxW62PQE.js";
|
|
7
7
|
import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createVNode, defineComponent, guardReactiveProps, mergeProps, normalizeClass, normalizeProps, openBlock, renderSlot, toDisplayString, unref, useAttrs, useSlots, withCtx } from "vue";
|
|
8
8
|
//#endregion
|
package/dist/components/GrDialog/chunks/{GrDialog-BiMJ9_T4.js.map → GrDialog-C01Hhk6G.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrDialog-BiMJ9_T4.js","names":["$emit","$emit"],"sources":["../../../../src/components/GrDialog/GrDialogFooter.vue","../../../../src/components/GrDialog/GrDialogFooter.vue","../../../../src/components/GrDialog/GrDialogCloseButton.vue","../../../../src/components/GrDialog/GrDialogCloseButton.vue","../../../../src/components/GrDialog/GrDialogHeader.vue","../../../../src/components/GrDialog/GrDialogHeader.vue","../../../../src/components/GrDialog/GrDialog.vue","../../../../src/components/GrDialog/GrDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport {\n DEFAULT_GR_DIALOG_FOOTER_CONFIG,\n resolveGrDialogSectionConfig,\n type GrDialogSectionConfig,\n} from './dialogShared'\n\nexport interface GrDialogFooterProps {\n config?: GrDialogSectionConfig\n}\n\nconst props = withDefaults(defineProps<GrDialogFooterProps>(), {\n config: undefined,\n})\n\nconst resolvedConfig = computed(() => resolveGrDialogSectionConfig(props.config, DEFAULT_GR_DIALOG_FOOTER_CONFIG))\n\nconst rootClass = computed(() => [\n resolvedConfig.value.paddingX,\n resolvedConfig.value.paddingY,\n resolvedConfig.value.bordered ? 'border-t border-[var(--gr-brd)]' : '',\n])\n\ndefineSlots<{\n /** Действия диалога. */\n default?: () => any\n}>()\n</script>\n\n<template>\n <div data-gr-dialog-footer :class=\"rootClass\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport {\n DEFAULT_GR_DIALOG_FOOTER_CONFIG,\n resolveGrDialogSectionConfig,\n type GrDialogSectionConfig,\n} from './dialogShared'\n\nexport interface GrDialogFooterProps {\n config?: GrDialogSectionConfig\n}\n\nconst props = withDefaults(defineProps<GrDialogFooterProps>(), {\n config: undefined,\n})\n\nconst resolvedConfig = computed(() => resolveGrDialogSectionConfig(props.config, DEFAULT_GR_DIALOG_FOOTER_CONFIG))\n\nconst rootClass = computed(() => [\n resolvedConfig.value.paddingX,\n resolvedConfig.value.paddingY,\n resolvedConfig.value.bordered ? 'border-t border-[var(--gr-brd)]' : '',\n])\n\ndefineSlots<{\n /** Действия диалога. */\n default?: () => any\n}>()\n</script>\n\n<template>\n <div data-gr-dialog-footer :class=\"rootClass\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport IconClose from '~icons/lucide/x'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nexport interface GrDialogCloseButtonEmits {\n (e: 'click'): void\n}\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst { t } = useGranularityTranslations()\n\n// A11y-лейбл: берём из атрибутов (родитель прокидывает `:aria-label=\"closeLabel\"`)\n// или используем i18n-дефолт. Не хардкодим английское \"Close\" — GR должен быть i18n-friendly.\nconst attrs = useAttrs()\nconst ariaLabel = computed(() => (attrs['aria-label'] as string | undefined) ?? t('gr.common.close', 'Close'))\n\ndefineEmits<GrDialogCloseButtonEmits>()\n</script>\n\n<template>\n <GrButton\n v-bind=\"attrs\"\n data-gr-dialog-close\n variant=\"ghost\"\n size=\"sm\"\n square\n :aria-label=\"ariaLabel\"\n @click=\"$emit('click')\"\n >\n <IconClose class=\"h-4 w-4\" aria-hidden=\"true\" />\n </GrButton>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport IconClose from '~icons/lucide/x'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nexport interface GrDialogCloseButtonEmits {\n (e: 'click'): void\n}\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst { t } = useGranularityTranslations()\n\n// A11y-лейбл: берём из атрибутов (родитель прокидывает `:aria-label=\"closeLabel\"`)\n// или используем i18n-дефолт. Не хардкодим английское \"Close\" — GR должен быть i18n-friendly.\nconst attrs = useAttrs()\nconst ariaLabel = computed(() => (attrs['aria-label'] as string | undefined) ?? t('gr.common.close', 'Close'))\n\ndefineEmits<GrDialogCloseButtonEmits>()\n</script>\n\n<template>\n <GrButton\n v-bind=\"attrs\"\n data-gr-dialog-close\n variant=\"ghost\"\n size=\"sm\"\n square\n :aria-label=\"ariaLabel\"\n @click=\"$emit('click')\"\n >\n <IconClose class=\"h-4 w-4\" aria-hidden=\"true\" />\n </GrButton>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport GrDialogCloseButton from './GrDialogCloseButton.vue'\nimport { useGrModalTitle } from '../GrModal/context'\nimport {\n DEFAULT_GR_DIALOG_HEADER_CONFIG,\n type GrDialogSectionConfig,\n resolveGrDialogSectionConfig,\n resolveGrDialogTitle,\n} from './dialogShared'\n\nexport interface GrDialogHeaderProps {\n title?: string\n showCloseButton?: boolean\n config?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n}\n\nexport interface GrDialogHeaderEmits {\n (e: 'close'): void\n}\n\nconst props = withDefaults(defineProps<GrDialogHeaderProps>(), {\n title: undefined,\n showCloseButton: true,\n config: undefined,\n closeLabel: undefined,\n})\n\nconst slots = defineSlots<{\n default?: (props: { title?: string }) => any\n}>()\n\ndefineEmits<GrDialogHeaderEmits>()\n\nconst resolvedTitle = computed(() => resolveGrDialogTitle(props.title))\n\nconst resolvedConfig = computed(() =>\n resolveGrDialogSectionConfig(props.config, DEFAULT_GR_DIALOG_HEADER_CONFIG),\n)\n\nconst rootClass = computed(() => [\n resolvedConfig.value.paddingX,\n resolvedConfig.value.paddingY,\n resolvedConfig.value.bordered ? 'border-b border-[var(--gr-brd)]' : '',\n 'flex items-center justify-between gap-4',\n])\n\n// Видимый заголовок рендерим только когда нет пользовательского слота:\n// если слот `#header` задан, a11y-title отдаётся через `GrModal #title`\n// на уровне `GrDialog` (см. JSDoc у `GrDialog.vue`).\nconst showVisibleTitle = computed(() => !slots.default && !!resolvedTitle.value)\n\n// Имя окна: заголовок объявляет себя окну, и `GrModal` ставит на него\n// `aria-labelledby`. Вне `GrModal` регистрация — no-op, шапку можно\n// использовать и отдельно.\nconst { titleId } = useGrModalTitle(() => showVisibleTitle.value)\n</script>\n\n<template>\n <div data-gr-dialog-header :class=\"rootClass\">\n <template v-if=\"slots.default\">\n <div class=\"flex-1 min-w-0 flex items-center\">\n <slot :title=\"resolvedTitle\" />\n </div>\n </template>\n <div\n v-else-if=\"showVisibleTitle\"\n :id=\"titleId\"\n data-gr-dialog-title\n class=\"flex-1 min-w-0 text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)] font-700\"\n >\n {{ resolvedTitle }}\n </div>\n <div v-else class=\"flex-1 min-w-0\" />\n <GrDialogCloseButton\n v-if=\"showCloseButton\"\n :aria-label=\"closeLabel\"\n @click=\"$emit('close')\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport GrDialogCloseButton from './GrDialogCloseButton.vue'\nimport { useGrModalTitle } from '../GrModal/context'\nimport {\n DEFAULT_GR_DIALOG_HEADER_CONFIG,\n type GrDialogSectionConfig,\n resolveGrDialogSectionConfig,\n resolveGrDialogTitle,\n} from './dialogShared'\n\nexport interface GrDialogHeaderProps {\n title?: string\n showCloseButton?: boolean\n config?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n}\n\nexport interface GrDialogHeaderEmits {\n (e: 'close'): void\n}\n\nconst props = withDefaults(defineProps<GrDialogHeaderProps>(), {\n title: undefined,\n showCloseButton: true,\n config: undefined,\n closeLabel: undefined,\n})\n\nconst slots = defineSlots<{\n default?: (props: { title?: string }) => any\n}>()\n\ndefineEmits<GrDialogHeaderEmits>()\n\nconst resolvedTitle = computed(() => resolveGrDialogTitle(props.title))\n\nconst resolvedConfig = computed(() =>\n resolveGrDialogSectionConfig(props.config, DEFAULT_GR_DIALOG_HEADER_CONFIG),\n)\n\nconst rootClass = computed(() => [\n resolvedConfig.value.paddingX,\n resolvedConfig.value.paddingY,\n resolvedConfig.value.bordered ? 'border-b border-[var(--gr-brd)]' : '',\n 'flex items-center justify-between gap-4',\n])\n\n// Видимый заголовок рендерим только когда нет пользовательского слота:\n// если слот `#header` задан, a11y-title отдаётся через `GrModal #title`\n// на уровне `GrDialog` (см. JSDoc у `GrDialog.vue`).\nconst showVisibleTitle = computed(() => !slots.default && !!resolvedTitle.value)\n\n// Имя окна: заголовок объявляет себя окну, и `GrModal` ставит на него\n// `aria-labelledby`. Вне `GrModal` регистрация — no-op, шапку можно\n// использовать и отдельно.\nconst { titleId } = useGrModalTitle(() => showVisibleTitle.value)\n</script>\n\n<template>\n <div data-gr-dialog-header :class=\"rootClass\">\n <template v-if=\"slots.default\">\n <div class=\"flex-1 min-w-0 flex items-center\">\n <slot :title=\"resolvedTitle\" />\n </div>\n </template>\n <div\n v-else-if=\"showVisibleTitle\"\n :id=\"titleId\"\n data-gr-dialog-title\n class=\"flex-1 min-w-0 text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)] font-700\"\n >\n {{ resolvedTitle }}\n </div>\n <div v-else class=\"flex-1 min-w-0\" />\n <GrDialogCloseButton\n v-if=\"showCloseButton\"\n :aria-label=\"closeLabel\"\n @click=\"$emit('close')\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrDialog — GR-примитив диалога поверх `GrModal`.\n *\n * Архитектурно:\n * - ширина/радиус/скролл-лок/Esc/бэкдроп — ответственность `GrModal`;\n * - заголовок/подвал/кнопка закрытия/паддинги секций — ответственность `GrDialog`.\n *\n * A11y: ровно один `DialogTitle` на открытое окно.\n * - Если хедер отображается без слота `#header` — видимый `DialogTitle` рендерит\n * `GrDialogHeader`.\n * - В остальных случаях (`!showHeader`, либо `showHeader` со слотом `#header`)\n * `GrDialog` отдаёт sr-only title в слот `#title` у `GrModal`, чтобы\n * `GrModal` корректно проставил `aria-labelledby` на корень окна.\n * - `aria-label` вниз уходит всегда: `GrModal` иначе не отличил бы «заголовок\n * рисует `GrDialogHeader`» от «имени нет вовсе» и подставил бы обобщённое.\n */\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed } from 'vue'\n\nimport GrModal from '../GrModal/GrModal.vue'\nimport type { GrModalScrollBehavior } from '../GrModal/grModalStyles'\nimport GrDialogFooter from './GrDialogFooter.vue'\nimport GrDialogHeader from './GrDialogHeader.vue'\nimport {\n DEFAULT_GR_DIALOG_BODY_CONFIG,\n type GrDialogSectionConfig,\n type GrDialogSize,\n resolveGrDialogSectionConfig,\n resolveGrDialogTitle,\n} from './dialogShared'\n\nexport interface GrDialogProps {\n modelValue: boolean\n title?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n /**\n * Доступное имя окна, когда заголовка нет вовсе: `showHeader: false` без\n * `title` и без слота `#header` оставил бы окно безымянным.\n */\n ariaLabel?: string\n /**\n * Кто скроллится при длинном содержимом. При `inside` шапка и подвал\n * закреплены, а едет только тело.\n */\n scrollBehavior?: GrModalScrollBehavior\n /**\n * Элемент, получающий фокус при открытии. По умолчанию — панель окна.\n * Элемент **из самого диалога** сюда передавать нельзя: проп, возвращающий\n * наверх то, что рождено внутри поддерева, замыкает рендер в цикл. Фокус на\n * своём содержимом ставится из содержимого — так это сделано в\n * `GrPromptDialog`.\n */\n initialFocus?: HTMLElement | null\n}\n\nexport interface GrDialogEmits {\n (e: 'update:modelValue', value: boolean): void\n /** Окно открылось и анимация закончилась. */\n (e: 'opened'): void\n /** Окно закрылось и анимация закончилась — содержимое можно размонтировать. */\n (e: 'closed'): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(defineProps<GrDialogProps>(), {\n title: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: undefined,\n ariaLabel: undefined,\n scrollBehavior: 'outside',\n initialFocus: null,\n})\n\nconst emit = defineEmits<GrDialogEmits>()\n\nconst slots = defineSlots<{\n default?: () => any\n header?: (props: { title?: string }) => any\n footer?: () => any\n}>()\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\n// Резолвим здесь, а не полагаемся на `GrModal`: иначе дефолт диалога затенил бы\n// конфиг раньше, чем примитив успел бы в него заглянуть.\nconst resolvedSize = useGrComponentProp('GrDialog', 'size', () => props.size, 'md')\n\nconst resolvedTitle = computed(() => resolveGrDialogTitle(props.title))\n\nconst bodyClass = computed(() => {\n const cfg = resolveGrDialogSectionConfig(props.bodyConfig, DEFAULT_GR_DIALOG_BODY_CONFIG)\n return [cfg.paddingX, cfg.paddingY]\n})\n\n// Нужен ли sr-only title через `GrModal #title`:\n// - `!showHeader` — вообще нет заголовка в разметке;\n// - `showHeader && $slots.header` — кастомный хедер не обязан содержать DialogTitle.\n// В обоих случаях даём окну a11y-title, не дублируя его визуально.\nconst useModalSrOnlyTitle = computed(\n () => !!resolvedTitle.value && (!props.showHeader || !!slots.header),\n)\n\nfunction open(): void {\n emit('update:modelValue', true)\n}\n\nfunction close(): void {\n emit('update:modelValue', false)\n}\n\nfunction toggle(): void {\n emit('update:modelValue', !props.modelValue)\n}\n\ndefineExpose({ open, close, toggle })\n</script>\n\n<template>\n <GrModal\n :model-value=\"modelValue\"\n :size=\"resolvedSize\"\n :scroll-behavior=\"scrollBehavior\"\n :initial-focus=\"initialFocus\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :aria-label=\"ariaLabel ?? resolvedTitle\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n @opened=\"emit('opened')\"\n @closed=\"emit('closed')\"\n >\n <template v-if=\"useModalSrOnlyTitle\" #title>\n <span class=\"sr-only\">{{ resolvedTitle }}</span>\n </template>\n\n <!-- Шапка и подвал уходят в layout-слоты `GrModal`: при `inside` они\n остаются вне скроллящегося тела. -->\n <template v-if=\"showHeader\" #header>\n <GrDialogHeader\n :title=\"resolvedTitle\"\n :show-close-button=\"showCloseButton\"\n :config=\"headerConfig\"\n :close-label=\"closeLabel\"\n @close=\"close\"\n >\n <template v-if=\"slots.header\" #default=\"slotProps\">\n <slot name=\"header\" v-bind=\"slotProps\" />\n </template>\n </GrDialogHeader>\n </template>\n\n <div :class=\"bodyClass\">\n <slot />\n </div>\n\n <template v-if=\"slots.footer\" #footer>\n <GrDialogFooter :config=\"footerConfig\">\n <slot name=\"footer\" />\n </GrDialogFooter>\n </template>\n </GrModal>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrDialog — GR-примитив диалога поверх `GrModal`.\n *\n * Архитектурно:\n * - ширина/радиус/скролл-лок/Esc/бэкдроп — ответственность `GrModal`;\n * - заголовок/подвал/кнопка закрытия/паддинги секций — ответственность `GrDialog`.\n *\n * A11y: ровно один `DialogTitle` на открытое окно.\n * - Если хедер отображается без слота `#header` — видимый `DialogTitle` рендерит\n * `GrDialogHeader`.\n * - В остальных случаях (`!showHeader`, либо `showHeader` со слотом `#header`)\n * `GrDialog` отдаёт sr-only title в слот `#title` у `GrModal`, чтобы\n * `GrModal` корректно проставил `aria-labelledby` на корень окна.\n * - `aria-label` вниз уходит всегда: `GrModal` иначе не отличил бы «заголовок\n * рисует `GrDialogHeader`» от «имени нет вовсе» и подставил бы обобщённое.\n */\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed } from 'vue'\n\nimport GrModal from '../GrModal/GrModal.vue'\nimport type { GrModalScrollBehavior } from '../GrModal/grModalStyles'\nimport GrDialogFooter from './GrDialogFooter.vue'\nimport GrDialogHeader from './GrDialogHeader.vue'\nimport {\n DEFAULT_GR_DIALOG_BODY_CONFIG,\n type GrDialogSectionConfig,\n type GrDialogSize,\n resolveGrDialogSectionConfig,\n resolveGrDialogTitle,\n} from './dialogShared'\n\nexport interface GrDialogProps {\n modelValue: boolean\n title?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n /**\n * Доступное имя окна, когда заголовка нет вовсе: `showHeader: false` без\n * `title` и без слота `#header` оставил бы окно безымянным.\n */\n ariaLabel?: string\n /**\n * Кто скроллится при длинном содержимом. При `inside` шапка и подвал\n * закреплены, а едет только тело.\n */\n scrollBehavior?: GrModalScrollBehavior\n /**\n * Элемент, получающий фокус при открытии. По умолчанию — панель окна.\n * Элемент **из самого диалога** сюда передавать нельзя: проп, возвращающий\n * наверх то, что рождено внутри поддерева, замыкает рендер в цикл. Фокус на\n * своём содержимом ставится из содержимого — так это сделано в\n * `GrPromptDialog`.\n */\n initialFocus?: HTMLElement | null\n}\n\nexport interface GrDialogEmits {\n (e: 'update:modelValue', value: boolean): void\n /** Окно открылось и анимация закончилась. */\n (e: 'opened'): void\n /** Окно закрылось и анимация закончилась — содержимое можно размонтировать. */\n (e: 'closed'): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(defineProps<GrDialogProps>(), {\n title: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: undefined,\n ariaLabel: undefined,\n scrollBehavior: 'outside',\n initialFocus: null,\n})\n\nconst emit = defineEmits<GrDialogEmits>()\n\nconst slots = defineSlots<{\n default?: () => any\n header?: (props: { title?: string }) => any\n footer?: () => any\n}>()\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\n// Резолвим здесь, а не полагаемся на `GrModal`: иначе дефолт диалога затенил бы\n// конфиг раньше, чем примитив успел бы в него заглянуть.\nconst resolvedSize = useGrComponentProp('GrDialog', 'size', () => props.size, 'md')\n\nconst resolvedTitle = computed(() => resolveGrDialogTitle(props.title))\n\nconst bodyClass = computed(() => {\n const cfg = resolveGrDialogSectionConfig(props.bodyConfig, DEFAULT_GR_DIALOG_BODY_CONFIG)\n return [cfg.paddingX, cfg.paddingY]\n})\n\n// Нужен ли sr-only title через `GrModal #title`:\n// - `!showHeader` — вообще нет заголовка в разметке;\n// - `showHeader && $slots.header` — кастомный хедер не обязан содержать DialogTitle.\n// В обоих случаях даём окну a11y-title, не дублируя его визуально.\nconst useModalSrOnlyTitle = computed(\n () => !!resolvedTitle.value && (!props.showHeader || !!slots.header),\n)\n\nfunction open(): void {\n emit('update:modelValue', true)\n}\n\nfunction close(): void {\n emit('update:modelValue', false)\n}\n\nfunction toggle(): void {\n emit('update:modelValue', !props.modelValue)\n}\n\ndefineExpose({ open, close, toggle })\n</script>\n\n<template>\n <GrModal\n :model-value=\"modelValue\"\n :size=\"resolvedSize\"\n :scroll-behavior=\"scrollBehavior\"\n :initial-focus=\"initialFocus\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :aria-label=\"ariaLabel ?? resolvedTitle\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n @opened=\"emit('opened')\"\n @closed=\"emit('closed')\"\n >\n <template v-if=\"useModalSrOnlyTitle\" #title>\n <span class=\"sr-only\">{{ resolvedTitle }}</span>\n </template>\n\n <!-- Шапка и подвал уходят в layout-слоты `GrModal`: при `inside` они\n остаются вне скроллящегося тела. -->\n <template v-if=\"showHeader\" #header>\n <GrDialogHeader\n :title=\"resolvedTitle\"\n :show-close-button=\"showCloseButton\"\n :config=\"headerConfig\"\n :close-label=\"closeLabel\"\n @close=\"close\"\n >\n <template v-if=\"slots.header\" #default=\"slotProps\">\n <slot name=\"header\" v-bind=\"slotProps\" />\n </template>\n </GrDialogHeader>\n </template>\n\n <div :class=\"bodyClass\">\n <slot />\n </div>\n\n <template v-if=\"slots.footer\" #footer>\n <GrDialogFooter :config=\"footerConfig\">\n <slot name=\"footer\" />\n </GrDialogFooter>\n </template>\n </GrModal>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GrDialog-C01Hhk6G.js","names":["$emit","$emit"],"sources":["../../../../src/components/GrDialog/GrDialogFooter.vue","../../../../src/components/GrDialog/GrDialogFooter.vue","../../../../src/components/GrDialog/GrDialogCloseButton.vue","../../../../src/components/GrDialog/GrDialogCloseButton.vue","../../../../src/components/GrDialog/GrDialogHeader.vue","../../../../src/components/GrDialog/GrDialogHeader.vue","../../../../src/components/GrDialog/GrDialog.vue","../../../../src/components/GrDialog/GrDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport {\n DEFAULT_GR_DIALOG_FOOTER_CONFIG,\n resolveGrDialogSectionConfig,\n type GrDialogSectionConfig,\n} from './dialogShared'\n\nexport interface GrDialogFooterProps {\n config?: GrDialogSectionConfig\n}\n\nconst props = withDefaults(defineProps<GrDialogFooterProps>(), {\n config: undefined,\n})\n\nconst resolvedConfig = computed(() => resolveGrDialogSectionConfig(props.config, DEFAULT_GR_DIALOG_FOOTER_CONFIG))\n\nconst rootClass = computed(() => [\n resolvedConfig.value.paddingX,\n resolvedConfig.value.paddingY,\n resolvedConfig.value.bordered ? 'border-t border-[var(--gr-brd)]' : '',\n])\n\ndefineSlots<{\n /** Действия диалога. */\n default?: () => any\n}>()\n</script>\n\n<template>\n <div data-gr-dialog-footer :class=\"rootClass\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport {\n DEFAULT_GR_DIALOG_FOOTER_CONFIG,\n resolveGrDialogSectionConfig,\n type GrDialogSectionConfig,\n} from './dialogShared'\n\nexport interface GrDialogFooterProps {\n config?: GrDialogSectionConfig\n}\n\nconst props = withDefaults(defineProps<GrDialogFooterProps>(), {\n config: undefined,\n})\n\nconst resolvedConfig = computed(() => resolveGrDialogSectionConfig(props.config, DEFAULT_GR_DIALOG_FOOTER_CONFIG))\n\nconst rootClass = computed(() => [\n resolvedConfig.value.paddingX,\n resolvedConfig.value.paddingY,\n resolvedConfig.value.bordered ? 'border-t border-[var(--gr-brd)]' : '',\n])\n\ndefineSlots<{\n /** Действия диалога. */\n default?: () => any\n}>()\n</script>\n\n<template>\n <div data-gr-dialog-footer :class=\"rootClass\">\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport IconClose from '~icons/lucide/x'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nexport interface GrDialogCloseButtonEmits {\n (e: 'click'): void\n}\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst { t } = useGranularityTranslations()\n\n// A11y-лейбл: берём из атрибутов (родитель прокидывает `:aria-label=\"closeLabel\"`)\n// или используем i18n-дефолт. Не хардкодим английское \"Close\" — GR должен быть i18n-friendly.\nconst attrs = useAttrs()\nconst ariaLabel = computed(() => (attrs['aria-label'] as string | undefined) ?? t('gr.common.close', 'Close'))\n\ndefineEmits<GrDialogCloseButtonEmits>()\n</script>\n\n<template>\n <GrButton\n v-bind=\"attrs\"\n data-gr-dialog-close\n variant=\"ghost\"\n size=\"sm\"\n square\n :aria-label=\"ariaLabel\"\n @click=\"$emit('click')\"\n >\n <IconClose class=\"h-4 w-4\" aria-hidden=\"true\" />\n </GrButton>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport IconClose from '~icons/lucide/x'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nexport interface GrDialogCloseButtonEmits {\n (e: 'click'): void\n}\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst { t } = useGranularityTranslations()\n\n// A11y-лейбл: берём из атрибутов (родитель прокидывает `:aria-label=\"closeLabel\"`)\n// или используем i18n-дефолт. Не хардкодим английское \"Close\" — GR должен быть i18n-friendly.\nconst attrs = useAttrs()\nconst ariaLabel = computed(() => (attrs['aria-label'] as string | undefined) ?? t('gr.common.close', 'Close'))\n\ndefineEmits<GrDialogCloseButtonEmits>()\n</script>\n\n<template>\n <GrButton\n v-bind=\"attrs\"\n data-gr-dialog-close\n variant=\"ghost\"\n size=\"sm\"\n square\n :aria-label=\"ariaLabel\"\n @click=\"$emit('click')\"\n >\n <IconClose class=\"h-4 w-4\" aria-hidden=\"true\" />\n </GrButton>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport GrDialogCloseButton from './GrDialogCloseButton.vue'\nimport { useGrModalTitle } from '../GrModal/context'\nimport {\n DEFAULT_GR_DIALOG_HEADER_CONFIG,\n type GrDialogSectionConfig,\n resolveGrDialogSectionConfig,\n resolveGrDialogTitle,\n} from './dialogShared'\n\nexport interface GrDialogHeaderProps {\n title?: string\n showCloseButton?: boolean\n config?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n}\n\nexport interface GrDialogHeaderEmits {\n (e: 'close'): void\n}\n\nconst props = withDefaults(defineProps<GrDialogHeaderProps>(), {\n title: undefined,\n showCloseButton: true,\n config: undefined,\n closeLabel: undefined,\n})\n\nconst slots = defineSlots<{\n default?: (props: { title?: string }) => any\n}>()\n\ndefineEmits<GrDialogHeaderEmits>()\n\nconst resolvedTitle = computed(() => resolveGrDialogTitle(props.title))\n\nconst resolvedConfig = computed(() =>\n resolveGrDialogSectionConfig(props.config, DEFAULT_GR_DIALOG_HEADER_CONFIG),\n)\n\nconst rootClass = computed(() => [\n resolvedConfig.value.paddingX,\n resolvedConfig.value.paddingY,\n resolvedConfig.value.bordered ? 'border-b border-[var(--gr-brd)]' : '',\n 'flex items-center justify-between gap-4',\n])\n\n// Видимый заголовок рендерим только когда нет пользовательского слота:\n// если слот `#header` задан, a11y-title отдаётся через `GrModal #title`\n// на уровне `GrDialog` (см. JSDoc у `GrDialog.vue`).\nconst showVisibleTitle = computed(() => !slots.default && !!resolvedTitle.value)\n\n// Имя окна: заголовок объявляет себя окну, и `GrModal` ставит на него\n// `aria-labelledby`. Вне `GrModal` регистрация — no-op, шапку можно\n// использовать и отдельно.\nconst { titleId } = useGrModalTitle(() => showVisibleTitle.value)\n</script>\n\n<template>\n <div data-gr-dialog-header :class=\"rootClass\">\n <template v-if=\"slots.default\">\n <div class=\"flex-1 min-w-0 flex items-center\">\n <slot :title=\"resolvedTitle\" />\n </div>\n </template>\n <div\n v-else-if=\"showVisibleTitle\"\n :id=\"titleId\"\n data-gr-dialog-title\n class=\"flex-1 min-w-0 text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)] font-700\"\n >\n {{ resolvedTitle }}\n </div>\n <div v-else class=\"flex-1 min-w-0\" />\n <GrDialogCloseButton\n v-if=\"showCloseButton\"\n :aria-label=\"closeLabel\"\n @click=\"$emit('close')\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport GrDialogCloseButton from './GrDialogCloseButton.vue'\nimport { useGrModalTitle } from '../GrModal/context'\nimport {\n DEFAULT_GR_DIALOG_HEADER_CONFIG,\n type GrDialogSectionConfig,\n resolveGrDialogSectionConfig,\n resolveGrDialogTitle,\n} from './dialogShared'\n\nexport interface GrDialogHeaderProps {\n title?: string\n showCloseButton?: boolean\n config?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n}\n\nexport interface GrDialogHeaderEmits {\n (e: 'close'): void\n}\n\nconst props = withDefaults(defineProps<GrDialogHeaderProps>(), {\n title: undefined,\n showCloseButton: true,\n config: undefined,\n closeLabel: undefined,\n})\n\nconst slots = defineSlots<{\n default?: (props: { title?: string }) => any\n}>()\n\ndefineEmits<GrDialogHeaderEmits>()\n\nconst resolvedTitle = computed(() => resolveGrDialogTitle(props.title))\n\nconst resolvedConfig = computed(() =>\n resolveGrDialogSectionConfig(props.config, DEFAULT_GR_DIALOG_HEADER_CONFIG),\n)\n\nconst rootClass = computed(() => [\n resolvedConfig.value.paddingX,\n resolvedConfig.value.paddingY,\n resolvedConfig.value.bordered ? 'border-b border-[var(--gr-brd)]' : '',\n 'flex items-center justify-between gap-4',\n])\n\n// Видимый заголовок рендерим только когда нет пользовательского слота:\n// если слот `#header` задан, a11y-title отдаётся через `GrModal #title`\n// на уровне `GrDialog` (см. JSDoc у `GrDialog.vue`).\nconst showVisibleTitle = computed(() => !slots.default && !!resolvedTitle.value)\n\n// Имя окна: заголовок объявляет себя окну, и `GrModal` ставит на него\n// `aria-labelledby`. Вне `GrModal` регистрация — no-op, шапку можно\n// использовать и отдельно.\nconst { titleId } = useGrModalTitle(() => showVisibleTitle.value)\n</script>\n\n<template>\n <div data-gr-dialog-header :class=\"rootClass\">\n <template v-if=\"slots.default\">\n <div class=\"flex-1 min-w-0 flex items-center\">\n <slot :title=\"resolvedTitle\" />\n </div>\n </template>\n <div\n v-else-if=\"showVisibleTitle\"\n :id=\"titleId\"\n data-gr-dialog-title\n class=\"flex-1 min-w-0 text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)] font-700\"\n >\n {{ resolvedTitle }}\n </div>\n <div v-else class=\"flex-1 min-w-0\" />\n <GrDialogCloseButton\n v-if=\"showCloseButton\"\n :aria-label=\"closeLabel\"\n @click=\"$emit('close')\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrDialog — GR-примитив диалога поверх `GrModal`.\n *\n * Архитектурно:\n * - ширина/радиус/скролл-лок/Esc/бэкдроп — ответственность `GrModal`;\n * - заголовок/подвал/кнопка закрытия/паддинги секций — ответственность `GrDialog`.\n *\n * A11y: ровно один `DialogTitle` на открытое окно.\n * - Если хедер отображается без слота `#header` — видимый `DialogTitle` рендерит\n * `GrDialogHeader`.\n * - В остальных случаях (`!showHeader`, либо `showHeader` со слотом `#header`)\n * `GrDialog` отдаёт sr-only title в слот `#title` у `GrModal`, чтобы\n * `GrModal` корректно проставил `aria-labelledby` на корень окна.\n * - `aria-label` вниз уходит всегда: `GrModal` иначе не отличил бы «заголовок\n * рисует `GrDialogHeader`» от «имени нет вовсе» и подставил бы обобщённое.\n */\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed } from 'vue'\n\nimport GrModal from '../GrModal/GrModal.vue'\nimport type { GrModalScrollBehavior } from '../GrModal/grModalStyles'\nimport GrDialogFooter from './GrDialogFooter.vue'\nimport GrDialogHeader from './GrDialogHeader.vue'\nimport {\n DEFAULT_GR_DIALOG_BODY_CONFIG,\n type GrDialogSectionConfig,\n type GrDialogSize,\n resolveGrDialogSectionConfig,\n resolveGrDialogTitle,\n} from './dialogShared'\n\nexport interface GrDialogProps {\n modelValue: boolean\n title?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n /**\n * Доступное имя окна, когда заголовка нет вовсе: `showHeader: false` без\n * `title` и без слота `#header` оставил бы окно безымянным.\n */\n ariaLabel?: string\n /**\n * Кто скроллится при длинном содержимом. При `inside` шапка и подвал\n * закреплены, а едет только тело.\n */\n scrollBehavior?: GrModalScrollBehavior\n /**\n * Элемент, получающий фокус при открытии. По умолчанию — панель окна.\n * Элемент **из самого диалога** сюда передавать нельзя: проп, возвращающий\n * наверх то, что рождено внутри поддерева, замыкает рендер в цикл. Фокус на\n * своём содержимом ставится из содержимого — так это сделано в\n * `GrPromptDialog`.\n */\n initialFocus?: HTMLElement | null\n}\n\nexport interface GrDialogEmits {\n (e: 'update:modelValue', value: boolean): void\n /** Окно открылось и анимация закончилась. */\n (e: 'opened'): void\n /** Окно закрылось и анимация закончилась — содержимое можно размонтировать. */\n (e: 'closed'): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(defineProps<GrDialogProps>(), {\n title: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: undefined,\n ariaLabel: undefined,\n scrollBehavior: 'outside',\n initialFocus: null,\n})\n\nconst emit = defineEmits<GrDialogEmits>()\n\nconst slots = defineSlots<{\n default?: () => any\n header?: (props: { title?: string }) => any\n footer?: () => any\n}>()\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\n// Резолвим здесь, а не полагаемся на `GrModal`: иначе дефолт диалога затенил бы\n// конфиг раньше, чем примитив успел бы в него заглянуть.\nconst resolvedSize = useGrComponentProp('GrDialog', 'size', () => props.size, 'md')\n\nconst resolvedTitle = computed(() => resolveGrDialogTitle(props.title))\n\nconst bodyClass = computed(() => {\n const cfg = resolveGrDialogSectionConfig(props.bodyConfig, DEFAULT_GR_DIALOG_BODY_CONFIG)\n return [cfg.paddingX, cfg.paddingY]\n})\n\n// Нужен ли sr-only title через `GrModal #title`:\n// - `!showHeader` — вообще нет заголовка в разметке;\n// - `showHeader && $slots.header` — кастомный хедер не обязан содержать DialogTitle.\n// В обоих случаях даём окну a11y-title, не дублируя его визуально.\nconst useModalSrOnlyTitle = computed(\n () => !!resolvedTitle.value && (!props.showHeader || !!slots.header),\n)\n\nfunction open(): void {\n emit('update:modelValue', true)\n}\n\nfunction close(): void {\n emit('update:modelValue', false)\n}\n\nfunction toggle(): void {\n emit('update:modelValue', !props.modelValue)\n}\n\ndefineExpose({ open, close, toggle })\n</script>\n\n<template>\n <GrModal\n :model-value=\"modelValue\"\n :size=\"resolvedSize\"\n :scroll-behavior=\"scrollBehavior\"\n :initial-focus=\"initialFocus\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :aria-label=\"ariaLabel ?? resolvedTitle\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n @opened=\"emit('opened')\"\n @closed=\"emit('closed')\"\n >\n <template v-if=\"useModalSrOnlyTitle\" #title>\n <span class=\"sr-only\">{{ resolvedTitle }}</span>\n </template>\n\n <!-- Шапка и подвал уходят в layout-слоты `GrModal`: при `inside` они\n остаются вне скроллящегося тела. -->\n <template v-if=\"showHeader\" #header>\n <GrDialogHeader\n :title=\"resolvedTitle\"\n :show-close-button=\"showCloseButton\"\n :config=\"headerConfig\"\n :close-label=\"closeLabel\"\n @close=\"close\"\n >\n <template v-if=\"slots.header\" #default=\"slotProps\">\n <slot name=\"header\" v-bind=\"slotProps\" />\n </template>\n </GrDialogHeader>\n </template>\n\n <div :class=\"bodyClass\">\n <slot />\n </div>\n\n <template v-if=\"slots.footer\" #footer>\n <GrDialogFooter :config=\"footerConfig\">\n <slot name=\"footer\" />\n </GrDialogFooter>\n </template>\n </GrModal>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrDialog — GR-примитив диалога поверх `GrModal`.\n *\n * Архитектурно:\n * - ширина/радиус/скролл-лок/Esc/бэкдроп — ответственность `GrModal`;\n * - заголовок/подвал/кнопка закрытия/паддинги секций — ответственность `GrDialog`.\n *\n * A11y: ровно один `DialogTitle` на открытое окно.\n * - Если хедер отображается без слота `#header` — видимый `DialogTitle` рендерит\n * `GrDialogHeader`.\n * - В остальных случаях (`!showHeader`, либо `showHeader` со слотом `#header`)\n * `GrDialog` отдаёт sr-only title в слот `#title` у `GrModal`, чтобы\n * `GrModal` корректно проставил `aria-labelledby` на корень окна.\n * - `aria-label` вниз уходит всегда: `GrModal` иначе не отличил бы «заголовок\n * рисует `GrDialogHeader`» от «имени нет вовсе» и подставил бы обобщённое.\n */\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed } from 'vue'\n\nimport GrModal from '../GrModal/GrModal.vue'\nimport type { GrModalScrollBehavior } from '../GrModal/grModalStyles'\nimport GrDialogFooter from './GrDialogFooter.vue'\nimport GrDialogHeader from './GrDialogHeader.vue'\nimport {\n DEFAULT_GR_DIALOG_BODY_CONFIG,\n type GrDialogSectionConfig,\n type GrDialogSize,\n resolveGrDialogSectionConfig,\n resolveGrDialogTitle,\n} from './dialogShared'\n\nexport interface GrDialogProps {\n modelValue: boolean\n title?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n /**\n * Доступное имя окна, когда заголовка нет вовсе: `showHeader: false` без\n * `title` и без слота `#header` оставил бы окно безымянным.\n */\n ariaLabel?: string\n /**\n * Кто скроллится при длинном содержимом. При `inside` шапка и подвал\n * закреплены, а едет только тело.\n */\n scrollBehavior?: GrModalScrollBehavior\n /**\n * Элемент, получающий фокус при открытии. По умолчанию — панель окна.\n * Элемент **из самого диалога** сюда передавать нельзя: проп, возвращающий\n * наверх то, что рождено внутри поддерева, замыкает рендер в цикл. Фокус на\n * своём содержимом ставится из содержимого — так это сделано в\n * `GrPromptDialog`.\n */\n initialFocus?: HTMLElement | null\n}\n\nexport interface GrDialogEmits {\n (e: 'update:modelValue', value: boolean): void\n /** Окно открылось и анимация закончилась. */\n (e: 'opened'): void\n /** Окно закрылось и анимация закончилась — содержимое можно размонтировать. */\n (e: 'closed'): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(defineProps<GrDialogProps>(), {\n title: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: undefined,\n ariaLabel: undefined,\n scrollBehavior: 'outside',\n initialFocus: null,\n})\n\nconst emit = defineEmits<GrDialogEmits>()\n\nconst slots = defineSlots<{\n default?: () => any\n header?: (props: { title?: string }) => any\n footer?: () => any\n}>()\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\n// Резолвим здесь, а не полагаемся на `GrModal`: иначе дефолт диалога затенил бы\n// конфиг раньше, чем примитив успел бы в него заглянуть.\nconst resolvedSize = useGrComponentProp('GrDialog', 'size', () => props.size, 'md')\n\nconst resolvedTitle = computed(() => resolveGrDialogTitle(props.title))\n\nconst bodyClass = computed(() => {\n const cfg = resolveGrDialogSectionConfig(props.bodyConfig, DEFAULT_GR_DIALOG_BODY_CONFIG)\n return [cfg.paddingX, cfg.paddingY]\n})\n\n// Нужен ли sr-only title через `GrModal #title`:\n// - `!showHeader` — вообще нет заголовка в разметке;\n// - `showHeader && $slots.header` — кастомный хедер не обязан содержать DialogTitle.\n// В обоих случаях даём окну a11y-title, не дублируя его визуально.\nconst useModalSrOnlyTitle = computed(\n () => !!resolvedTitle.value && (!props.showHeader || !!slots.header),\n)\n\nfunction open(): void {\n emit('update:modelValue', true)\n}\n\nfunction close(): void {\n emit('update:modelValue', false)\n}\n\nfunction toggle(): void {\n emit('update:modelValue', !props.modelValue)\n}\n\ndefineExpose({ open, close, toggle })\n</script>\n\n<template>\n <GrModal\n :model-value=\"modelValue\"\n :size=\"resolvedSize\"\n :scroll-behavior=\"scrollBehavior\"\n :initial-focus=\"initialFocus\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :aria-label=\"ariaLabel ?? resolvedTitle\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n @opened=\"emit('opened')\"\n @closed=\"emit('closed')\"\n >\n <template v-if=\"useModalSrOnlyTitle\" #title>\n <span class=\"sr-only\">{{ resolvedTitle }}</span>\n </template>\n\n <!-- Шапка и подвал уходят в layout-слоты `GrModal`: при `inside` они\n остаются вне скроллящегося тела. -->\n <template v-if=\"showHeader\" #header>\n <GrDialogHeader\n :title=\"resolvedTitle\"\n :show-close-button=\"showCloseButton\"\n :config=\"headerConfig\"\n :close-label=\"closeLabel\"\n @close=\"close\"\n >\n <template v-if=\"slots.header\" #default=\"slotProps\">\n <slot name=\"header\" v-bind=\"slotProps\" />\n </template>\n </GrDialogHeader>\n </template>\n\n <div :class=\"bodyClass\">\n <slot />\n </div>\n\n <template v-if=\"slots.footer\" #footer>\n <GrDialogFooter :config=\"footerConfig\">\n <slot name=\"footer\" />\n </GrDialogFooter>\n </template>\n </GrModal>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { i as GrDialogFooter_default, n as GrDialogHeader_default, r as GrDialogCloseButton_default, t as GrDialog_default } from "./chunks/GrDialog-
|
|
1
|
+
import { i as GrDialogFooter_default, n as GrDialogHeader_default, r as GrDialogCloseButton_default, t as GrDialog_default } from "./chunks/GrDialog-C01Hhk6G.js";
|
|
2
2
|
import { t as grDialogSafelist } from "../../chunks/safelist-Y3zrlhOa.js";
|
|
3
3
|
export { GrDialog_default as GrDialog, GrDialog_default as default, GrDialogCloseButton_default as GrDialogCloseButton, GrDialogFooter_default as GrDialogFooter, GrDialogHeader_default as GrDialogHeader, grDialogSafelist };
|
|
@@ -4,8 +4,8 @@ import { n as useGranularityTranslations, t as resolveGranularityI18n } from "..
|
|
|
4
4
|
import { t as ensurePortalRoot } from "../../../chunks/portalRoot-CVhCgdG6.js";
|
|
5
5
|
import { t as GrButton_default } from "../../GrButton/chunks/GrButton-7GP0zObj.js";
|
|
6
6
|
import { n as coreResponseErrorParsers, o as responseErrorParserPresets, r as createResponseErrorClassifier } from "../../GrResponseErrorBanner/chunks/GrResponseErrorBanner-DMeOWlzj.js";
|
|
7
|
-
import { t as GrConfirmDialog_default } from "../../GrConfirmDialog/chunks/GrConfirmDialog-
|
|
8
|
-
import { t as GrPromptDialog_default } from "../../GrPromptDialog/chunks/GrPromptDialog-
|
|
7
|
+
import { t as GrConfirmDialog_default } from "../../GrConfirmDialog/chunks/GrConfirmDialog-jRDs_E6C.js";
|
|
8
|
+
import { t as GrPromptDialog_default } from "../../GrPromptDialog/chunks/GrPromptDialog-CailXSqW.js";
|
|
9
9
|
import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, getCurrentInstance, inject, markRaw, mergeProps, nextTick, onBeforeUnmount, onMounted, openBlock, provide, reactive, ref, render, renderList, shallowRef, toDisplayString, withCtx } from "vue";
|
|
10
10
|
//#region src/components/GrDialogService/store.ts
|
|
11
11
|
function createDialogServiceState() {
|
|
@@ -517,6 +517,11 @@ var GrDialogServiceItem_default = /* @__PURE__ */ defineComponent({
|
|
|
517
517
|
confirmTone: o.confirmTone
|
|
518
518
|
};
|
|
519
519
|
});
|
|
520
|
+
/**
|
|
521
|
+
* `alert` рисуется тем же `GrConfirmDialog`, что и `confirm`, но без кнопки
|
|
522
|
+
* отмены: у сообщения нет второго исхода, и лишняя кнопка предлагала бы выбор,
|
|
523
|
+
* которого нет.
|
|
524
|
+
*/
|
|
520
525
|
return (_ctx, _cache) => {
|
|
521
526
|
return __props.request.kind === "prompt" ? (openBlock(), createBlock(GrPromptDialog_default, mergeProps({ key: 0 }, sharedProps.value, {
|
|
522
527
|
value: promptValue.value,
|