@feugene/granularity 0.4.2 → 0.4.3

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.
@@ -12,6 +12,7 @@ var variantClassByVariant = {
12
12
  primary: "text-[var(--primary)] visited:text-[var(--primary)] hover:text-[var(--primary-hover)] active:text-[var(--primary-active)]",
13
13
  default: "text-[var(--fg)] hover:text-[var(--primary)] active:text-[var(--primary-active)]",
14
14
  muted: "text-[var(--muted-fg)] hover:text-[var(--fg)] active:text-[var(--fg)]",
15
+ "muted-primary": "text-[var(--muted-fg)] hover:text-[var(--primary-hover)] active:text-[var(--primary-hover)]",
15
16
  danger: "text-[var(--ds-danger)] hover:text-[var(--ds-danger-hover)] active:text-[var(--ds-danger-active)]"
16
17
  };
17
18
  var disabledStateClass = "cursor-not-allowed opacity-60 text-[var(--muted-fg)]";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-DUtUkSzc.js","names":[],"sources":["../../src/components/GrLink/grLinkStyles.ts","../../src/components/GrLink/safelist.ts","../../src/components/GrLink/config.ts"],"sourcesContent":["export type GrLinkVariant = 'primary' | 'default' | 'muted' | 'muted-primary' |'danger'\nexport type GrLinkUnderline = 'auto' | 'always' | 'none'\nexport type GrLinkSize = 'sm' | 'md' | 'lg'\n\n// Базовые классы корневого элемента (`<a>`/`<span>`). Вынесены сюда,\n// чтобы быть единственным источником истины как для шаблона, так и для safelist.\nexport const baseRootClass = 'inline-flex items-center gap-1 rounded-[6px] transition-colors duration-150'\nexport const focusRingClass = 'focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]'\n\nexport const sizeClassBySize: Record<GrLinkSize, string> = {\n sm: 'text-sm',\n md: 'text-[14px]',\n lg: 'text-base',\n}\n\nexport const variantClassByVariant: Record<GrLinkVariant, string> = {\n primary:\n 'text-[var(--primary)] visited:text-[var(--primary)] hover:text-[var(--primary-hover)] active:text-[var(--primary-active)]',\n default: 'text-[var(--fg)] hover:text-[var(--primary)] active:text-[var(--primary-active)]',\n muted: 'text-[var(--muted-fg)] hover:text-[var(--fg)] active:text-[var(--fg)]',\n 'muted-primary': 'text-[var(--muted-fg)] hover:text-[var(--primary-hover)] active:text-[var(--primary-hover)]',\n danger: 'text-[var(--ds-danger)] hover:text-[var(--ds-danger-hover)] active:text-[var(--ds-danger-active)]',\n}\n\nexport const disabledStateClass = 'cursor-not-allowed opacity-60 text-[var(--muted-fg)]'\n\nconst UNDERLINE_VALUES: readonly GrLinkUnderline[] = ['auto', 'always', 'none']\n\nfunction underlineClass(underline: GrLinkUnderline, disabled: boolean): string {\n if (disabled) return 'no-underline'\n if (underline === 'always') return 'underline underline-offset-4'\n if (underline === 'none') return 'no-underline'\n return 'no-underline hover:underline hover:underline-offset-4'\n}\n\n// Derived from `underlineClass` so that there is a single source of truth:\n// any change/extension of the underline logic is automatically reflected\n// in the safelist without manual updates.\nexport const underlineClasses: readonly string[] = [...new Set(\n UNDERLINE_VALUES.flatMap(u => [underlineClass(u, false), underlineClass(u, true)]),\n)]\n\nfunction disabledClass(disabled: boolean): string {\n return disabled ? disabledStateClass : ''\n}\n\nexport function grLinkClass(options: { size: GrLinkSize, underline: GrLinkUnderline, variant: GrLinkVariant, disabled: boolean }): string {\n return [\n sizeClassBySize[options.size],\n underlineClass(options.underline, options.disabled),\n variantClassByVariant[options.variant],\n disabledClass(options.disabled),\n ]\n .filter(Boolean)\n .join(' ')\n}\n","import { splitClassTokens } from '../shared/classTokens'\nimport {\n baseRootClass,\n disabledStateClass,\n focusRingClass,\n sizeClassBySize,\n underlineClasses,\n variantClassByVariant,\n} from './grLinkStyles'\n\nexport const grLinkSafelist = [...new Set([\n ...splitClassTokens(baseRootClass),\n ...splitClassTokens(focusRingClass),\n ...Object.values(sizeClassBySize).flatMap(splitClassTokens),\n ...underlineClasses.flatMap(splitClassTokens),\n ...Object.values(variantClassByVariant).flatMap(splitClassTokens),\n ...splitClassTokens(disabledStateClass),\n])]\n","import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nimport { grLinkSafelist } from './safelist'\n\nexport const grLinkConfig = defineGranularComponent(import.meta.url, {\n name: 'GrLink',\n safelist: grLinkSafelist,\n})"],"mappings":";;;AAMA,IAAa,gBAAgB;AAC7B,IAAa,iBAAiB;AAE9B,IAAa,kBAA8C;CACzD,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AAED,IAAa,wBAAuD;CAClE,SACE;CACF,SAAS;CACT,OAAO;CACP,iBAAiB;CACjB,QAAQ;CACT;AAED,IAAa,qBAAqB;AAElC,IAAM,mBAA+C;CAAC;CAAQ;CAAU;CAAO;AAE/E,SAAS,eAAe,WAA4B,UAA2B;AAC7E,KAAI,SAAU,QAAO;AACrB,KAAI,cAAc,SAAU,QAAO;AACnC,KAAI,cAAc,OAAQ,QAAO;AACjC,QAAO;;AAMT,IAAa,mBAAsC,CAAC,GAAG,IAAI,IACzD,iBAAiB,SAAQ,MAAK,CAAC,eAAe,GAAG,MAAM,EAAE,eAAe,GAAG,KAAK,CAAC,CAAC,CACnF,CAAC;AAEF,SAAS,cAAc,UAA2B;AAChD,QAAO,WAAW,qBAAqB;;AAGzC,SAAgB,YAAY,SAA8G;AACxI,QAAO;EACL,gBAAgB,QAAQ;EACxB,eAAe,QAAQ,WAAW,QAAQ,SAAS;EACnD,sBAAsB,QAAQ;EAC9B,cAAc,QAAQ,SAAS;EAChC,CACE,OAAO,QAAQ,CACf,KAAK,IAAI;;;;AC5Cd,IAAa,iBAAiB,CAAC,GAAG,IAAI,IAAI;CACxC,GAAG,iBAAiB,cAAc;CAClC,GAAG,iBAAiB,eAAe;CACnC,GAAG,OAAO,OAAO,gBAAgB,CAAC,QAAQ,iBAAiB;CAC3D,GAAG,iBAAiB,QAAQ,iBAAiB;CAC7C,GAAG,OAAO,OAAO,sBAAsB,CAAC,QAAQ,iBAAiB;CACjE,GAAG,iBAAiB,mBAAmB;CACxC,CAAC,CAAC;;;ACbH,IAAa,eAAe,wBAAwB,OAAO,KAAK,KAAK;CACnE,MAAM;CACN,UAAU;CACX,CAAA"}
@@ -23,7 +23,7 @@ import { t as grFormSectionConfig } from "./config-BCPyma1I.js";
23
23
  import { t as grImageViewerConfig } from "./config-BA0BWYzs.js";
24
24
  import { t as grInputConfig } from "./config-D19pyP4D.js";
25
25
  import { t as grInputTagConfig } from "./config-DgRJlF00.js";
26
- import { t as grLinkConfig } from "./config-Cf0J6wCX.js";
26
+ import { t as grLinkConfig } from "./config-DUtUkSzc.js";
27
27
  import { t as grListConfig } from "./config-fCcRwjIB.js";
28
28
  import { t as grLoadingConfig } from "./config-BN-B2K4r.js";
29
29
  import { t as grModalConfig } from "./config-XwI6t8cn.js";
@@ -1 +1 @@
1
- {"version":3,"file":"shared-Cu5QkNmt.js","names":[],"sources":["../../src/components/GrDialog/config.ts","../../src/granular-provider/shared.ts"],"sourcesContent":["import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nimport { grDialogSafelist } from './safelist'\n\nexport const grDialogConfig = defineGranularComponent(import.meta.url, {\n name: 'GrDialog',\n dependencies: ['GrButton', 'GrModal'],\n safelist: grDialogSafelist,\n})\n","// Общий код browser- и node-entry granular-provider'а.\n//\n// Оба entry (`./index.ts`, `./node.ts`) отличаются только списком\n// компонентов, у которых есть node-only вариант конфига (например,\n// `GrButton`, чей `config.node.ts` использует `tokenDefinitionsFromCssSync`\n// и тянет `node:fs`). Browser-вариант таких компонентов берёт облегчённый\n// `./config.ts`, node-вариант — `./config.node.ts`. Всё остальное — `id`,\n// `theme.*`, `packageBaseUrl` и полный список browser-safe компонентов —\n// живёт здесь.\n//\n// ВАЖНО: все `new URL('../styles/...', import.meta.url)` намеренно находятся\n// здесь — `shared.ts` лежит в той же директории, что и `index.ts` / `node.ts`,\n// поэтому относительные пути идентичны. Это ОК для браузера: бандлеры\n// транслируют такие конструкции в статические asset-URL и `node:*` в бандл\n// не утаскивают.\n//\n// Ключи записи `<Name>: ds<Name>Config` в `granularityComponentConfigs`\n// критичны для regex‑парсинга в `apps/showcase/scripts/generate-component-api.mjs`,\n// не ломайте формат.\nimport {\n defineGranularProvider,\n type GranularComponentDescriptor,\n type GranularProvider,\n} from '@feugene/unocss-preset-granular/contract'\nimport { grAlertConfig } from '../components/GrAlert/config'\nimport { grAvatarConfig } from '../components/GrAvatar/config'\nimport { grBadgeConfig } from '../components/GrBadge/config'\nimport { grBadgeWrapConfig } from '../components/GrBadgeWrap/config'\nimport { grBottomNavConfig } from '../components/GrBottomNav/config'\nimport { grButtonConfig } from '../components/GrButton/config'\nimport { grButtonGroupConfig } from '../components/GrButtonGroup/config'\nimport { grCardConfig } from '../components/GrCard/config'\nimport { grCheckboxConfig } from '../components/GrCheckbox/config'\nimport { grCollapseConfig } from '../components/GrCollapse/config'\nimport { grConfirmDialogConfig } from '../components/GrConfirmDialog/config'\nimport { grDataTableConfig } from '../components/GrDataTable/config'\nimport { grDialogConfig } from '../components/GrDialog/config'\nimport { grDrawerConfig } from '../components/GrDrawer/config'\nimport { grDropdownConfig } from '../components/GrDropdown/config'\nimport { grDropdownMenuConfig } from '../components/GrDropdownMenu/config'\nimport { grEmptyStateConfig } from '../components/GrEmptyState/config'\nimport { grFileUploadConfig } from '../components/GrFileUpload/config'\nimport { grFormFieldConfig } from '../components/GrFormField/config'\nimport { grFormFileConfig } from '../components/GrFormFile/config'\nimport { grFormSectionConfig } from '../components/GrFormSection/config'\nimport { grIconConfig } from '../components/GrIcon/config'\nimport { grImageViewerConfig } from '../components/GrImageViewer/config'\nimport { grInputConfig } from '../components/GrInput/config'\nimport { grInputTagConfig } from '../components/GrInputTag/config'\nimport { grLinkConfig } from '../components/GrLink/config'\nimport { grListConfig } from '../components/GrList/config'\nimport { grLoadingConfig } from '../components/GrLoading/config'\nimport { grModalConfig } from '../components/GrModal/config'\nimport { grNavbarConfig } from '../components/GrNavbar/config'\nimport { grNumberInputConfig } from '../components/GrNumberInput/config'\nimport { grPaginationConfig } from '../components/GrPagination/config'\nimport { grProgressBarConfig } from '../components/GrProgressBar/config'\nimport { grPromptDialogConfig } from '../components/GrPromptDialog/config'\nimport { grRadioConfig } from '../components/GrRadio/config'\nimport { grRadioGroupConfig } from '../components/GrRadioGroup/config'\nimport { grSegmentedConfig } from '../components/GrSegmented/config'\nimport { grSelectConfig } from '../components/GrSelect/config'\nimport { grSidebarConfig } from '../components/GrSidebar/config'\nimport { grSkeletonConfig } from '../components/GrSkeleton/config'\nimport { grSwitchConfig } from '../components/GrSwitch/config'\nimport { grTableConfig } from '../components/GrTable/config'\nimport { grTabsConfig } from '../components/GrTabs/config'\nimport { grTextareaConfig } from '../components/GrTextarea/config'\nimport { grToasterConfig } from '../components/GrToaster/config'\nimport { grTooltipConfig } from '../components/GrTooltip/config'\nimport { grTreeConfig } from '../components/GrTree/config'\nimport { grTreeSelectConfig } from '../components/GrTreeSelect/config'\n\n/** Идентификатор провайдера — совпадает с именем пакета. */\nexport const GRANULARITY_PROVIDER_ID = '@feugene/granularity'\n\n// runtime-concat: литерал `new URL('..', import.meta.url)` rolldown заменяет\n// на `data:`-URL, поэтому собираем корень пакета из `import.meta.url` вручную\n// (отрезая два последних сегмента: имя файла и каталог `granular-provider/`).\nconst packageBaseUrl = `${import.meta.url.slice(\n 0,\n import.meta.url.lastIndexOf('/', import.meta.url.lastIndexOf('/') - 1) + 1,\n)}`\n\n/** Встроенные темы пакета. Единственный источник правды о списке тем. */\nexport const granularityThemeNames = ['light', 'dark'] as const\nexport type GranularityThemeName = (typeof granularityThemeNames)[number]\n\n/** Темы, активные по умолчанию, если окружение не переопределяет выбор. */\nexport const granularityDefaultThemes: readonly GranularityThemeName[] = ['light']\n\nconst theme = {\n baseCssUrl: new URL('../styles/base.css', import.meta.url).href,\n tokensCssUrl: new URL('../styles/tokens.css', import.meta.url).href,\n themes: {\n light: new URL('../styles/themes/light.css', import.meta.url).href,\n dark: new URL('../styles/themes/dark.css', import.meta.url).href,\n },\n defaultThemes: granularityDefaultThemes,\n} as const\n\n/**\n * Полный реестр публичных компонентов пакета `@feugene/granularity`.\n *\n * Ключи — имена компонентов (совпадают с публичным subpath‑экспортом\n * `@feugene/granularity/components/<Name>`). Значения — browser‑safe\n * `ds<Name>Config` из `./config.ts` рядом с SFC.\n *\n * Для компонентов, у которых есть node-only вариант конфига\n * (например, `GrButton` с `tokenDefinitionsFromCssSync`), browser‑конфиг\n * остаётся здесь, а node‑вариант подставляется снаружи через\n * `createGranularityProvider(overrides)` — см. `./index.ts` (browser)\n * и `./node.ts` (node).\n *\n * Формат записи `<Name>: ds<Name>Config` критичен для regex‑парсинга\n * в `apps/showcase/scripts/generate-component-api.mjs`, не ломайте его.\n */\nexport const granularityComponentConfigs = {\n GrAlert: grAlertConfig,\n GrAvatar: grAvatarConfig,\n GrBadge: grBadgeConfig,\n GrBadgeWrap: grBadgeWrapConfig,\n GrBottomNav: grBottomNavConfig,\n GrButton: grButtonConfig,\n GrButtonGroup: grButtonGroupConfig,\n GrCard: grCardConfig,\n GrCheckbox: grCheckboxConfig,\n GrCollapse: grCollapseConfig,\n GrConfirmDialog: grConfirmDialogConfig,\n GrDataTable: grDataTableConfig,\n GrDialog: grDialogConfig,\n GrDrawer: grDrawerConfig,\n GrDropdown: grDropdownConfig,\n GrDropdownMenu: grDropdownMenuConfig,\n GrEmptyState: grEmptyStateConfig,\n GrFileUpload: grFileUploadConfig,\n GrFormField: grFormFieldConfig,\n GrFormFile: grFormFileConfig,\n GrFormSection: grFormSectionConfig,\n GrIcon: grIconConfig,\n GrImageViewer: grImageViewerConfig,\n GrInput: grInputConfig,\n GrInputTag: grInputTagConfig,\n GrLink: grLinkConfig,\n GrList: grListConfig,\n GrLoading: grLoadingConfig,\n GrModal: grModalConfig,\n GrNavbar: grNavbarConfig,\n GrNumberInput: grNumberInputConfig,\n GrPagination: grPaginationConfig,\n GrProgressBar: grProgressBarConfig,\n GrPromptDialog: grPromptDialogConfig,\n GrRadio: grRadioConfig,\n GrRadioGroup: grRadioGroupConfig,\n GrSegmented: grSegmentedConfig,\n GrSelect: grSelectConfig,\n GrSidebar: grSidebarConfig,\n GrSkeleton: grSkeletonConfig,\n GrSwitch: grSwitchConfig,\n GrTable: grTableConfig,\n GrTabs: grTabsConfig,\n GrTextarea: grTextareaConfig,\n GrToaster: grToasterConfig,\n GrTooltip: grTooltipConfig,\n GrTree: grTreeConfig,\n GrTreeSelect: grTreeSelectConfig,\n}\n\nexport type GranularityComponentName = keyof typeof granularityComponentConfigs\n\n/** Базовый (browser-safe) набор компонентов в порядке реестра. */\nconst baseComponents: readonly GranularComponentDescriptor[] = Object.values(\n granularityComponentConfigs,\n)\n\n/**\n * Собирает granular-provider пакета `@feugene/granularity`.\n *\n * Принимает массив `GranularComponentDescriptor`'ов — это компоненты,\n * у которых есть node-only вариант конфига (например, `GrButton` с\n * `tokenDefinitionsFromCssSync`). Дескрипторы с именем, которое уже\n * присутствует в базовом наборе, переопределяют его (побеждает\n * переданный снаружи), остальные — добавляются в конец списка.\n */\nexport function createGranularityProvider(\n overrides: readonly GranularComponentDescriptor[] = [],\n): GranularProvider {\n const overrideByName = new Map(\n overrides.map(component => [component.name, component]),\n )\n const components: GranularComponentDescriptor[] = [\n ...baseComponents.map(component => overrideByName.get(component.name) ?? component),\n ...overrides.filter(component => !baseComponents.some(base => base.name === component.name)),\n ]\n\n return defineGranularProvider({\n id: GRANULARITY_PROVIDER_ID,\n contractVersion: 1,\n packageBaseUrl,\n components,\n theme,\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,IAAa,iBAAiB,wBAAwB,OAAO,KAAK,KAAK;CACrE,MAAM;CACN,cAAc,CAAC,YAAY,UAAU;CACrC,UAAU;CACX,CAAC;;;;ACkEF,IAAa,0BAA0B;AAKvC,IAAM,iBAAiB,GAAG,OAAO,KAAK,IAAI,MACxC,GACA,OAAO,KAAK,IAAI,YAAY,KAAK,OAAO,KAAK,IAAI,YAAY,IAAI,GAAG,EAAE,GAAG,EAC1E;;AAGD,IAAa,wBAAwB,CAAC,SAAS,OAAO;;AAItD,IAAa,2BAA4D,CAAC,QAAQ;AAElF,IAAM,QAAQ;CACZ,YAAY,IAAA,IAAA,i2BAAA,KAAA,OAAA,KAAA,IAA8C,CAAC;CAC3D,cAAc,IAAA,IAAA,iuKAAA,KAAA,OAAA,KAAA,IAAgD,CAAC;CAC/D,QAAQ;EACN,OAAO,IAAA,IAAA,qrGAAA,KAAA,OAAA,KAAA,IAAsD,CAAC;EAC9D,MAAM,IAAA,IAAA,qxGAAA,KAAA,OAAA,KAAA,IAAqD,CAAC;EAC7D;CACD,eAAe;CAChB;;;;;;;;;;;;;;;;;AAkBD,IAAa,8BAA8B;CACzC,SAAS;CACT,UAAU;CACV,SAAS;CACT,aAAa;CACb,aAAa;CACb,UAAU;CACV,eAAe;CACf,QAAQ;CACR,YAAY;CACZ,YAAY;CACZ,iBAAiB;CACjB,aAAa;CACb,UAAU;CACV,UAAU;CACV,YAAY;CACZ,gBAAgB;CAChB,cAAc;CACd,cAAc;CACd,aAAa;CACb,YAAY;CACZ,eAAe;CACf,QAAQ;CACR,eAAe;CACf,SAAS;CACT,YAAY;CACZ,QAAQ;CACR,QAAQ;CACR,WAAW;CACX,SAAS;CACT,UAAU;CACV,eAAe;CACf,cAAc;CACd,eAAe;CACf,gBAAgB;CAChB,SAAS;CACT,cAAc;CACd,aAAa;CACb,UAAU;CACV,WAAW;CACX,YAAY;CACZ,UAAU;CACV,SAAS;CACT,QAAQ;CACR,YAAY;CACZ,WAAW;CACX,WAAW;CACX,QAAQ;CACR,cAAc;CACf;;AAKD,IAAM,iBAAyD,OAAO,OACpE,4BACD;;;;;;;;;;AAWD,SAAgB,0BACd,YAAoD,EAAE,EACpC;CAClB,MAAM,iBAAiB,IAAI,IACzB,UAAU,KAAI,cAAa,CAAC,UAAU,MAAM,UAAU,CAAC,CACxD;AAMD,QAAO,uBAAuB;EAC5B,IAAI;EACJ,iBAAiB;EACjB;EACA,YATgD,CAChD,GAAG,eAAe,KAAI,cAAa,eAAe,IAAI,UAAU,KAAK,IAAI,UAAU,EACnF,GAAG,UAAU,QAAO,cAAa,CAAC,eAAe,MAAK,SAAQ,KAAK,SAAS,UAAU,KAAK,CAAC,CAC7F;EAOC;EACD,CAAC"}
1
+ {"version":3,"file":"shared-buYOkZSv.js","names":[],"sources":["../../src/components/GrDialog/config.ts","../../src/granular-provider/shared.ts"],"sourcesContent":["import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nimport { grDialogSafelist } from './safelist'\n\nexport const grDialogConfig = defineGranularComponent(import.meta.url, {\n name: 'GrDialog',\n dependencies: ['GrButton', 'GrModal'],\n safelist: grDialogSafelist,\n})\n","// Общий код browser- и node-entry granular-provider'а.\n//\n// Оба entry (`./index.ts`, `./node.ts`) отличаются только списком\n// компонентов, у которых есть node-only вариант конфига (например,\n// `GrButton`, чей `config.node.ts` использует `tokenDefinitionsFromCssSync`\n// и тянет `node:fs`). Browser-вариант таких компонентов берёт облегчённый\n// `./config.ts`, node-вариант — `./config.node.ts`. Всё остальное — `id`,\n// `theme.*`, `packageBaseUrl` и полный список browser-safe компонентов —\n// живёт здесь.\n//\n// ВАЖНО: все `new URL('../styles/...', import.meta.url)` намеренно находятся\n// здесь — `shared.ts` лежит в той же директории, что и `index.ts` / `node.ts`,\n// поэтому относительные пути идентичны. Это ОК для браузера: бандлеры\n// транслируют такие конструкции в статические asset-URL и `node:*` в бандл\n// не утаскивают.\n//\n// Ключи записи `<Name>: ds<Name>Config` в `granularityComponentConfigs`\n// критичны для regex‑парсинга в `apps/showcase/scripts/generate-component-api.mjs`,\n// не ломайте формат.\nimport {\n defineGranularProvider,\n type GranularComponentDescriptor,\n type GranularProvider,\n} from '@feugene/unocss-preset-granular/contract'\nimport { grAlertConfig } from '../components/GrAlert/config'\nimport { grAvatarConfig } from '../components/GrAvatar/config'\nimport { grBadgeConfig } from '../components/GrBadge/config'\nimport { grBadgeWrapConfig } from '../components/GrBadgeWrap/config'\nimport { grBottomNavConfig } from '../components/GrBottomNav/config'\nimport { grButtonConfig } from '../components/GrButton/config'\nimport { grButtonGroupConfig } from '../components/GrButtonGroup/config'\nimport { grCardConfig } from '../components/GrCard/config'\nimport { grCheckboxConfig } from '../components/GrCheckbox/config'\nimport { grCollapseConfig } from '../components/GrCollapse/config'\nimport { grConfirmDialogConfig } from '../components/GrConfirmDialog/config'\nimport { grDataTableConfig } from '../components/GrDataTable/config'\nimport { grDialogConfig } from '../components/GrDialog/config'\nimport { grDrawerConfig } from '../components/GrDrawer/config'\nimport { grDropdownConfig } from '../components/GrDropdown/config'\nimport { grDropdownMenuConfig } from '../components/GrDropdownMenu/config'\nimport { grEmptyStateConfig } from '../components/GrEmptyState/config'\nimport { grFileUploadConfig } from '../components/GrFileUpload/config'\nimport { grFormFieldConfig } from '../components/GrFormField/config'\nimport { grFormFileConfig } from '../components/GrFormFile/config'\nimport { grFormSectionConfig } from '../components/GrFormSection/config'\nimport { grIconConfig } from '../components/GrIcon/config'\nimport { grImageViewerConfig } from '../components/GrImageViewer/config'\nimport { grInputConfig } from '../components/GrInput/config'\nimport { grInputTagConfig } from '../components/GrInputTag/config'\nimport { grLinkConfig } from '../components/GrLink/config'\nimport { grListConfig } from '../components/GrList/config'\nimport { grLoadingConfig } from '../components/GrLoading/config'\nimport { grModalConfig } from '../components/GrModal/config'\nimport { grNavbarConfig } from '../components/GrNavbar/config'\nimport { grNumberInputConfig } from '../components/GrNumberInput/config'\nimport { grPaginationConfig } from '../components/GrPagination/config'\nimport { grProgressBarConfig } from '../components/GrProgressBar/config'\nimport { grPromptDialogConfig } from '../components/GrPromptDialog/config'\nimport { grRadioConfig } from '../components/GrRadio/config'\nimport { grRadioGroupConfig } from '../components/GrRadioGroup/config'\nimport { grSegmentedConfig } from '../components/GrSegmented/config'\nimport { grSelectConfig } from '../components/GrSelect/config'\nimport { grSidebarConfig } from '../components/GrSidebar/config'\nimport { grSkeletonConfig } from '../components/GrSkeleton/config'\nimport { grSwitchConfig } from '../components/GrSwitch/config'\nimport { grTableConfig } from '../components/GrTable/config'\nimport { grTabsConfig } from '../components/GrTabs/config'\nimport { grTextareaConfig } from '../components/GrTextarea/config'\nimport { grToasterConfig } from '../components/GrToaster/config'\nimport { grTooltipConfig } from '../components/GrTooltip/config'\nimport { grTreeConfig } from '../components/GrTree/config'\nimport { grTreeSelectConfig } from '../components/GrTreeSelect/config'\n\n/** Идентификатор провайдера — совпадает с именем пакета. */\nexport const GRANULARITY_PROVIDER_ID = '@feugene/granularity'\n\n// runtime-concat: литерал `new URL('..', import.meta.url)` rolldown заменяет\n// на `data:`-URL, поэтому собираем корень пакета из `import.meta.url` вручную\n// (отрезая два последних сегмента: имя файла и каталог `granular-provider/`).\nconst packageBaseUrl = `${import.meta.url.slice(\n 0,\n import.meta.url.lastIndexOf('/', import.meta.url.lastIndexOf('/') - 1) + 1,\n)}`\n\n/** Встроенные темы пакета. Единственный источник правды о списке тем. */\nexport const granularityThemeNames = ['light', 'dark'] as const\nexport type GranularityThemeName = (typeof granularityThemeNames)[number]\n\n/** Темы, активные по умолчанию, если окружение не переопределяет выбор. */\nexport const granularityDefaultThemes: readonly GranularityThemeName[] = ['light']\n\nconst theme = {\n baseCssUrl: new URL('../styles/base.css', import.meta.url).href,\n tokensCssUrl: new URL('../styles/tokens.css', import.meta.url).href,\n themes: {\n light: new URL('../styles/themes/light.css', import.meta.url).href,\n dark: new URL('../styles/themes/dark.css', import.meta.url).href,\n },\n defaultThemes: granularityDefaultThemes,\n} as const\n\n/**\n * Полный реестр публичных компонентов пакета `@feugene/granularity`.\n *\n * Ключи — имена компонентов (совпадают с публичным subpath‑экспортом\n * `@feugene/granularity/components/<Name>`). Значения — browser‑safe\n * `ds<Name>Config` из `./config.ts` рядом с SFC.\n *\n * Для компонентов, у которых есть node-only вариант конфига\n * (например, `GrButton` с `tokenDefinitionsFromCssSync`), browser‑конфиг\n * остаётся здесь, а node‑вариант подставляется снаружи через\n * `createGranularityProvider(overrides)` — см. `./index.ts` (browser)\n * и `./node.ts` (node).\n *\n * Формат записи `<Name>: ds<Name>Config` критичен для regex‑парсинга\n * в `apps/showcase/scripts/generate-component-api.mjs`, не ломайте его.\n */\nexport const granularityComponentConfigs = {\n GrAlert: grAlertConfig,\n GrAvatar: grAvatarConfig,\n GrBadge: grBadgeConfig,\n GrBadgeWrap: grBadgeWrapConfig,\n GrBottomNav: grBottomNavConfig,\n GrButton: grButtonConfig,\n GrButtonGroup: grButtonGroupConfig,\n GrCard: grCardConfig,\n GrCheckbox: grCheckboxConfig,\n GrCollapse: grCollapseConfig,\n GrConfirmDialog: grConfirmDialogConfig,\n GrDataTable: grDataTableConfig,\n GrDialog: grDialogConfig,\n GrDrawer: grDrawerConfig,\n GrDropdown: grDropdownConfig,\n GrDropdownMenu: grDropdownMenuConfig,\n GrEmptyState: grEmptyStateConfig,\n GrFileUpload: grFileUploadConfig,\n GrFormField: grFormFieldConfig,\n GrFormFile: grFormFileConfig,\n GrFormSection: grFormSectionConfig,\n GrIcon: grIconConfig,\n GrImageViewer: grImageViewerConfig,\n GrInput: grInputConfig,\n GrInputTag: grInputTagConfig,\n GrLink: grLinkConfig,\n GrList: grListConfig,\n GrLoading: grLoadingConfig,\n GrModal: grModalConfig,\n GrNavbar: grNavbarConfig,\n GrNumberInput: grNumberInputConfig,\n GrPagination: grPaginationConfig,\n GrProgressBar: grProgressBarConfig,\n GrPromptDialog: grPromptDialogConfig,\n GrRadio: grRadioConfig,\n GrRadioGroup: grRadioGroupConfig,\n GrSegmented: grSegmentedConfig,\n GrSelect: grSelectConfig,\n GrSidebar: grSidebarConfig,\n GrSkeleton: grSkeletonConfig,\n GrSwitch: grSwitchConfig,\n GrTable: grTableConfig,\n GrTabs: grTabsConfig,\n GrTextarea: grTextareaConfig,\n GrToaster: grToasterConfig,\n GrTooltip: grTooltipConfig,\n GrTree: grTreeConfig,\n GrTreeSelect: grTreeSelectConfig,\n}\n\nexport type GranularityComponentName = keyof typeof granularityComponentConfigs\n\n/** Базовый (browser-safe) набор компонентов в порядке реестра. */\nconst baseComponents: readonly GranularComponentDescriptor[] = Object.values(\n granularityComponentConfigs,\n)\n\n/**\n * Собирает granular-provider пакета `@feugene/granularity`.\n *\n * Принимает массив `GranularComponentDescriptor`'ов — это компоненты,\n * у которых есть node-only вариант конфига (например, `GrButton` с\n * `tokenDefinitionsFromCssSync`). Дескрипторы с именем, которое уже\n * присутствует в базовом наборе, переопределяют его (побеждает\n * переданный снаружи), остальные — добавляются в конец списка.\n */\nexport function createGranularityProvider(\n overrides: readonly GranularComponentDescriptor[] = [],\n): GranularProvider {\n const overrideByName = new Map(\n overrides.map(component => [component.name, component]),\n )\n const components: GranularComponentDescriptor[] = [\n ...baseComponents.map(component => overrideByName.get(component.name) ?? component),\n ...overrides.filter(component => !baseComponents.some(base => base.name === component.name)),\n ]\n\n return defineGranularProvider({\n id: GRANULARITY_PROVIDER_ID,\n contractVersion: 1,\n packageBaseUrl,\n components,\n theme,\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,IAAa,iBAAiB,wBAAwB,OAAO,KAAK,KAAK;CACrE,MAAM;CACN,cAAc,CAAC,YAAY,UAAU;CACrC,UAAU;CACX,CAAC;;;;ACkEF,IAAa,0BAA0B;AAKvC,IAAM,iBAAiB,GAAG,OAAO,KAAK,IAAI,MACxC,GACA,OAAO,KAAK,IAAI,YAAY,KAAK,OAAO,KAAK,IAAI,YAAY,IAAI,GAAG,EAAE,GAAG,EAC1E;;AAGD,IAAa,wBAAwB,CAAC,SAAS,OAAO;;AAItD,IAAa,2BAA4D,CAAC,QAAQ;AAElF,IAAM,QAAQ;CACZ,YAAY,IAAA,IAAA,i2BAAA,KAAA,OAAA,KAAA,IAA8C,CAAC;CAC3D,cAAc,IAAA,IAAA,iuKAAA,KAAA,OAAA,KAAA,IAAgD,CAAC;CAC/D,QAAQ;EACN,OAAO,IAAA,IAAA,qrGAAA,KAAA,OAAA,KAAA,IAAsD,CAAC;EAC9D,MAAM,IAAA,IAAA,qxGAAA,KAAA,OAAA,KAAA,IAAqD,CAAC;EAC7D;CACD,eAAe;CAChB;;;;;;;;;;;;;;;;;AAkBD,IAAa,8BAA8B;CACzC,SAAS;CACT,UAAU;CACV,SAAS;CACT,aAAa;CACb,aAAa;CACb,UAAU;CACV,eAAe;CACf,QAAQ;CACR,YAAY;CACZ,YAAY;CACZ,iBAAiB;CACjB,aAAa;CACb,UAAU;CACV,UAAU;CACV,YAAY;CACZ,gBAAgB;CAChB,cAAc;CACd,cAAc;CACd,aAAa;CACb,YAAY;CACZ,eAAe;CACf,QAAQ;CACR,eAAe;CACf,SAAS;CACT,YAAY;CACZ,QAAQ;CACR,QAAQ;CACR,WAAW;CACX,SAAS;CACT,UAAU;CACV,eAAe;CACf,cAAc;CACd,eAAe;CACf,gBAAgB;CAChB,SAAS;CACT,cAAc;CACd,aAAa;CACb,UAAU;CACV,WAAW;CACX,YAAY;CACZ,UAAU;CACV,SAAS;CACT,QAAQ;CACR,YAAY;CACZ,WAAW;CACX,WAAW;CACX,QAAQ;CACR,cAAc;CACf;;AAKD,IAAM,iBAAyD,OAAO,OACpE,4BACD;;;;;;;;;;AAWD,SAAgB,0BACd,YAAoD,EAAE,EACpC;CAClB,MAAM,iBAAiB,IAAI,IACzB,UAAU,KAAI,cAAa,CAAC,UAAU,MAAM,UAAU,CAAC,CACxD;AAMD,QAAO,uBAAuB;EAC5B,IAAI;EACJ,iBAAiB;EACjB;EACA,YATgD,CAChD,GAAG,eAAe,KAAI,cAAa,eAAe,IAAI,UAAU,KAAK,IAAI,UAAU,EACnF,GAAG,UAAU,QAAO,cAAa,CAAC,eAAe,MAAK,SAAQ,KAAK,SAAS,UAAU,KAAK,CAAC,CAC7F;EAOC;EACD,CAAC"}
@@ -1,4 +1,4 @@
1
- import { a as grLinkClass, i as focusRingClass, r as baseRootClass } from "../../../chunks/config-Cf0J6wCX.js";
1
+ import { a as grLinkClass, i as focusRingClass, r as baseRootClass } from "../../../chunks/config-DUtUkSzc.js";
2
2
  import { computed, createElementBlock, defineComponent, mergeProps, openBlock, renderSlot, unref, useAttrs } from "vue";
3
3
  //#region src/components/GrLink/GrLink.vue?vue&type=script&setup=true&lang.ts
4
4
  var _hoisted_1 = [
@@ -1 +1 @@
1
- {"version":3,"file":"GrLink-C7-Y1u88.js","names":[],"sources":["../../../../src/components/GrLink/GrLink.vue","../../../../src/components/GrLink/GrLink.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrLink — DS-примитив ссылки.\n *\n * Корневой тег зависит от пропов:\n * - `<a>` — когда заданы `href` и не `disabled`;\n * - `<span>` — во всех остальных случаях (включая `disabled`, даже если `href` задан).\n *\n * Это осознанное решение, чтобы отключённая ссылка не была кликабельной и\n * не участвовала в порядке табуляции. Учтите это в внешних CSS-селекторах.\n */\nimport { computed, useAttrs } from 'vue'\n\nimport {\n baseRootClass,\n grLinkClass,\n type GrLinkSize,\n type GrLinkUnderline,\n type GrLinkVariant,\n focusRingClass,\n} from './grLinkStyles'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst props = withDefaults(defineProps<{\n href?: string\n external?: boolean\n target?: string\n rel?: string\n disabled?: boolean\n ariaLabel?: string\n variant?: GrLinkVariant\n underline?: GrLinkUnderline\n size?: GrLinkSize\n}>(), {\n href: undefined,\n external: false,\n target: undefined,\n rel: undefined,\n disabled: false,\n ariaLabel: undefined,\n variant: 'primary',\n underline: 'auto',\n size: 'md',\n})\n\nconst attrs = useAttrs()\n\nconst isAnchor = computed(() => !!props.href && !props.disabled)\n\nconst resolvedTarget = computed(() => {\n if (props.target)\n return props.target\n\n if (props.external)\n return '_blank'\n\n return undefined\n})\n\nconst resolvedRel = computed(() => {\n if (props.rel)\n return props.rel\n\n // Авто-защита для любых ссылок, открывающихся в новой вкладке,\n // а не только когда выставлен `external`.\n if (resolvedTarget.value === '_blank')\n return 'noopener noreferrer'\n\n return undefined\n})\n\nconst rootClass = computed(() => {\n const variantClass = grLinkClass({\n size: props.size,\n underline: props.underline,\n variant: props.variant,\n disabled: props.disabled,\n })\n\n // На disabled-ветке (`<span>`) focus-ring не нужен: элемент не фокусируется,\n // а если снаружи ему навесят `tabindex`, фокус-рамка на «отключённой» ссылке смотрелась бы странно.\n return props.disabled\n ? `${baseRootClass} ${variantClass}`\n : `${baseRootClass} ${focusRingClass} ${variantClass}`\n})\n</script>\n\n<template>\n <a\n v-if=\"isAnchor\"\n v-bind=\"attrs\"\n :href=\"href\"\n :target=\"resolvedTarget\"\n :rel=\"resolvedRel\"\n :aria-label=\"ariaLabel\"\n :class=\"rootClass\"\n >\n <slot />\n </a>\n\n <span\n v-else\n v-bind=\"attrs\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"rootClass\"\n >\n <slot />\n </span>\n</template>","<script setup lang=\"ts\">\n/**\n * GrLink — DS-примитив ссылки.\n *\n * Корневой тег зависит от пропов:\n * - `<a>` — когда заданы `href` и не `disabled`;\n * - `<span>` — во всех остальных случаях (включая `disabled`, даже если `href` задан).\n *\n * Это осознанное решение, чтобы отключённая ссылка не была кликабельной и\n * не участвовала в порядке табуляции. Учтите это в внешних CSS-селекторах.\n */\nimport { computed, useAttrs } from 'vue'\n\nimport {\n baseRootClass,\n grLinkClass,\n type GrLinkSize,\n type GrLinkUnderline,\n type GrLinkVariant,\n focusRingClass,\n} from './grLinkStyles'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst props = withDefaults(defineProps<{\n href?: string\n external?: boolean\n target?: string\n rel?: string\n disabled?: boolean\n ariaLabel?: string\n variant?: GrLinkVariant\n underline?: GrLinkUnderline\n size?: GrLinkSize\n}>(), {\n href: undefined,\n external: false,\n target: undefined,\n rel: undefined,\n disabled: false,\n ariaLabel: undefined,\n variant: 'primary',\n underline: 'auto',\n size: 'md',\n})\n\nconst attrs = useAttrs()\n\nconst isAnchor = computed(() => !!props.href && !props.disabled)\n\nconst resolvedTarget = computed(() => {\n if (props.target)\n return props.target\n\n if (props.external)\n return '_blank'\n\n return undefined\n})\n\nconst resolvedRel = computed(() => {\n if (props.rel)\n return props.rel\n\n // Авто-защита для любых ссылок, открывающихся в новой вкладке,\n // а не только когда выставлен `external`.\n if (resolvedTarget.value === '_blank')\n return 'noopener noreferrer'\n\n return undefined\n})\n\nconst rootClass = computed(() => {\n const variantClass = grLinkClass({\n size: props.size,\n underline: props.underline,\n variant: props.variant,\n disabled: props.disabled,\n })\n\n // На disabled-ветке (`<span>`) focus-ring не нужен: элемент не фокусируется,\n // а если снаружи ему навесят `tabindex`, фокус-рамка на «отключённой» ссылке смотрелась бы странно.\n return props.disabled\n ? `${baseRootClass} ${variantClass}`\n : `${baseRootClass} ${focusRingClass} ${variantClass}`\n})\n</script>\n\n<template>\n <a\n v-if=\"isAnchor\"\n v-bind=\"attrs\"\n :href=\"href\"\n :target=\"resolvedTarget\"\n :rel=\"resolvedRel\"\n :aria-label=\"ariaLabel\"\n :class=\"rootClass\"\n >\n <slot />\n </a>\n\n <span\n v-else\n v-bind=\"attrs\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"rootClass\"\n >\n <slot />\n </span>\n</template>"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BA,MAAM,QAAQ;EAsBd,MAAM,QAAQ,UAAS;EAEvB,MAAM,WAAW,eAAe,CAAC,CAAC,MAAM,QAAQ,CAAC,MAAM,SAAQ;EAE/D,MAAM,iBAAiB,eAAe;AACpC,OAAI,MAAM,OACR,QAAO,MAAM;AAEf,OAAI,MAAM,SACR,QAAO;IAGV;EAED,MAAM,cAAc,eAAe;AACjC,OAAI,MAAM,IACR,QAAO,MAAM;AAIf,OAAI,eAAe,UAAU,SAC3B,QAAO;IAGV;EAED,MAAM,YAAY,eAAe;GAC/B,MAAM,eAAe,YAAY;IAC/B,MAAM,MAAM;IACZ,WAAW,MAAM;IACjB,SAAS,MAAM;IACf,UAAU,MAAM;IACjB,CAAA;AAID,UAAO,MAAM,WACT,GAAG,cAAc,GAAG,iBACpB,GAAG,cAAc,GAAG,eAAe,GAAG;IAC3C;;UAKS,SAAA,SAAA,WAAA,EADR,mBAUI,KAVJ,WAUI,EAAA,KAAA,GAAA,EARM,MAAA,MAAK,EAAA;IACZ,MAAM,QAAA;IACN,QAAQ,eAAA;IACR,KAAK,YAAA;IACL,cAAY,QAAA;IACZ,OAAO,UAAA;QAER,WAAQ,KAAA,QAAA,UAAA,CAAA,EAAA,IAAA,WAAA,KAAA,WAAA,EAGV,mBAQO,QARP,WAQO,EAAA,KAAA,GAAA,EANG,MAAA,MAAK,EAAA;IACZ,cAAY,QAAA;IACZ,iBAAe,QAAA,WAAQ,SAAY,KAAA;IACnC,OAAO,UAAA;QAER,WAAQ,KAAA,QAAA,UAAA,CAAA,EAAA,IAAA,WAAA"}
1
+ {"version":3,"file":"GrLink-BbN7R3iP.js","names":[],"sources":["../../../../src/components/GrLink/GrLink.vue","../../../../src/components/GrLink/GrLink.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrLink — DS-примитив ссылки.\n *\n * Корневой тег зависит от пропов:\n * - `<a>` — когда заданы `href` и не `disabled`;\n * - `<span>` — во всех остальных случаях (включая `disabled`, даже если `href` задан).\n *\n * Это осознанное решение, чтобы отключённая ссылка не была кликабельной и\n * не участвовала в порядке табуляции. Учтите это в внешних CSS-селекторах.\n */\nimport { computed, useAttrs } from 'vue'\n\nimport {\n baseRootClass,\n grLinkClass,\n type GrLinkSize,\n type GrLinkUnderline,\n type GrLinkVariant,\n focusRingClass,\n} from './grLinkStyles'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst props = withDefaults(defineProps<{\n href?: string\n external?: boolean\n target?: string\n rel?: string\n disabled?: boolean\n ariaLabel?: string\n variant?: GrLinkVariant\n underline?: GrLinkUnderline\n size?: GrLinkSize\n}>(), {\n href: undefined,\n external: false,\n target: undefined,\n rel: undefined,\n disabled: false,\n ariaLabel: undefined,\n variant: 'primary',\n underline: 'auto',\n size: 'md',\n})\n\nconst attrs = useAttrs()\n\nconst isAnchor = computed(() => !!props.href && !props.disabled)\n\nconst resolvedTarget = computed(() => {\n if (props.target)\n return props.target\n\n if (props.external)\n return '_blank'\n\n return undefined\n})\n\nconst resolvedRel = computed(() => {\n if (props.rel)\n return props.rel\n\n // Авто-защита для любых ссылок, открывающихся в новой вкладке,\n // а не только когда выставлен `external`.\n if (resolvedTarget.value === '_blank')\n return 'noopener noreferrer'\n\n return undefined\n})\n\nconst rootClass = computed(() => {\n const variantClass = grLinkClass({\n size: props.size,\n underline: props.underline,\n variant: props.variant,\n disabled: props.disabled,\n })\n\n // На disabled-ветке (`<span>`) focus-ring не нужен: элемент не фокусируется,\n // а если снаружи ему навесят `tabindex`, фокус-рамка на «отключённой» ссылке смотрелась бы странно.\n return props.disabled\n ? `${baseRootClass} ${variantClass}`\n : `${baseRootClass} ${focusRingClass} ${variantClass}`\n})\n</script>\n\n<template>\n <a\n v-if=\"isAnchor\"\n v-bind=\"attrs\"\n :href=\"href\"\n :target=\"resolvedTarget\"\n :rel=\"resolvedRel\"\n :aria-label=\"ariaLabel\"\n :class=\"rootClass\"\n >\n <slot />\n </a>\n\n <span\n v-else\n v-bind=\"attrs\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"rootClass\"\n >\n <slot />\n </span>\n</template>","<script setup lang=\"ts\">\n/**\n * GrLink — DS-примитив ссылки.\n *\n * Корневой тег зависит от пропов:\n * - `<a>` — когда заданы `href` и не `disabled`;\n * - `<span>` — во всех остальных случаях (включая `disabled`, даже если `href` задан).\n *\n * Это осознанное решение, чтобы отключённая ссылка не была кликабельной и\n * не участвовала в порядке табуляции. Учтите это в внешних CSS-селекторах.\n */\nimport { computed, useAttrs } from 'vue'\n\nimport {\n baseRootClass,\n grLinkClass,\n type GrLinkSize,\n type GrLinkUnderline,\n type GrLinkVariant,\n focusRingClass,\n} from './grLinkStyles'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst props = withDefaults(defineProps<{\n href?: string\n external?: boolean\n target?: string\n rel?: string\n disabled?: boolean\n ariaLabel?: string\n variant?: GrLinkVariant\n underline?: GrLinkUnderline\n size?: GrLinkSize\n}>(), {\n href: undefined,\n external: false,\n target: undefined,\n rel: undefined,\n disabled: false,\n ariaLabel: undefined,\n variant: 'primary',\n underline: 'auto',\n size: 'md',\n})\n\nconst attrs = useAttrs()\n\nconst isAnchor = computed(() => !!props.href && !props.disabled)\n\nconst resolvedTarget = computed(() => {\n if (props.target)\n return props.target\n\n if (props.external)\n return '_blank'\n\n return undefined\n})\n\nconst resolvedRel = computed(() => {\n if (props.rel)\n return props.rel\n\n // Авто-защита для любых ссылок, открывающихся в новой вкладке,\n // а не только когда выставлен `external`.\n if (resolvedTarget.value === '_blank')\n return 'noopener noreferrer'\n\n return undefined\n})\n\nconst rootClass = computed(() => {\n const variantClass = grLinkClass({\n size: props.size,\n underline: props.underline,\n variant: props.variant,\n disabled: props.disabled,\n })\n\n // На disabled-ветке (`<span>`) focus-ring не нужен: элемент не фокусируется,\n // а если снаружи ему навесят `tabindex`, фокус-рамка на «отключённой» ссылке смотрелась бы странно.\n return props.disabled\n ? `${baseRootClass} ${variantClass}`\n : `${baseRootClass} ${focusRingClass} ${variantClass}`\n})\n</script>\n\n<template>\n <a\n v-if=\"isAnchor\"\n v-bind=\"attrs\"\n :href=\"href\"\n :target=\"resolvedTarget\"\n :rel=\"resolvedRel\"\n :aria-label=\"ariaLabel\"\n :class=\"rootClass\"\n >\n <slot />\n </a>\n\n <span\n v-else\n v-bind=\"attrs\"\n :aria-label=\"ariaLabel\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :class=\"rootClass\"\n >\n <slot />\n </span>\n</template>"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BA,MAAM,QAAQ;EAsBd,MAAM,QAAQ,UAAS;EAEvB,MAAM,WAAW,eAAe,CAAC,CAAC,MAAM,QAAQ,CAAC,MAAM,SAAQ;EAE/D,MAAM,iBAAiB,eAAe;AACpC,OAAI,MAAM,OACR,QAAO,MAAM;AAEf,OAAI,MAAM,SACR,QAAO;IAGV;EAED,MAAM,cAAc,eAAe;AACjC,OAAI,MAAM,IACR,QAAO,MAAM;AAIf,OAAI,eAAe,UAAU,SAC3B,QAAO;IAGV;EAED,MAAM,YAAY,eAAe;GAC/B,MAAM,eAAe,YAAY;IAC/B,MAAM,MAAM;IACZ,WAAW,MAAM;IACjB,SAAS,MAAM;IACf,UAAU,MAAM;IACjB,CAAA;AAID,UAAO,MAAM,WACT,GAAG,cAAc,GAAG,iBACpB,GAAG,cAAc,GAAG,eAAe,GAAG;IAC3C;;UAKS,SAAA,SAAA,WAAA,EADR,mBAUI,KAVJ,WAUI,EAAA,KAAA,GAAA,EARM,MAAA,MAAK,EAAA;IACZ,MAAM,QAAA;IACN,QAAQ,eAAA;IACR,KAAK,YAAA;IACL,cAAY,QAAA;IACZ,OAAO,UAAA;QAER,WAAQ,KAAA,QAAA,UAAA,CAAA,EAAA,IAAA,WAAA,KAAA,WAAA,EAGV,mBAQO,QARP,WAQO,EAAA,KAAA,GAAA,EANG,MAAA,MAAK,EAAA;IACZ,cAAY,QAAA;IACZ,iBAAe,QAAA,WAAQ,SAAY,KAAA;IACnC,OAAO,UAAA;QAER,WAAQ,KAAA,QAAA,UAAA,CAAA,EAAA,IAAA,WAAA"}
@@ -1,3 +1,3 @@
1
- import { n as grLinkSafelist, t as grLinkConfig } from "../../chunks/config-Cf0J6wCX.js";
2
- import { t as GrLink_default } from "./chunks/GrLink-C7-Y1u88.js";
1
+ import { n as grLinkSafelist, t as grLinkConfig } from "../../chunks/config-DUtUkSzc.js";
2
+ import { t as GrLink_default } from "./chunks/GrLink-BbN7R3iP.js";
3
3
  export { GrLink_default as GrLink, GrLink_default as default, grLinkConfig, grLinkSafelist };
@@ -1,6 +1,6 @@
1
1
  import { n as grButtonSafelist } from "./chunks/safelist-BY7z8fOl.js";
2
2
  import { n as grProgressBarSafelist } from "./chunks/config-Da90XGsi.js";
3
- import { a as granularityThemeNames, i as granularityDefaultThemes, n as createGranularityProvider, r as granularityComponentConfigs, t as GRANULARITY_PROVIDER_ID } from "./chunks/shared-Cu5QkNmt.js";
3
+ import { a as granularityThemeNames, i as granularityDefaultThemes, n as createGranularityProvider, r as granularityComponentConfigs, t as GRANULARITY_PROVIDER_ID } from "./chunks/shared-buYOkZSv.js";
4
4
  import { defineGranularComponent } from "@feugene/unocss-preset-granular/contract";
5
5
  import { tokenDefinitionsFromCssSync } from "@feugene/unocss-preset-granular/node";
6
6
  //#region src/components/GrButton/config.node.ts
@@ -1,4 +1,4 @@
1
- import { a as granularityThemeNames, i as granularityDefaultThemes, n as createGranularityProvider, r as granularityComponentConfigs, t as GRANULARITY_PROVIDER_ID } from "./chunks/shared-Cu5QkNmt.js";
1
+ import { a as granularityThemeNames, i as granularityDefaultThemes, n as createGranularityProvider, r as granularityComponentConfigs, t as GRANULARITY_PROVIDER_ID } from "./chunks/shared-buYOkZSv.js";
2
2
  //#region src/granular-provider/index.ts
3
3
  var granularityProvider = createGranularityProvider();
4
4
  //#endregion
package/dist/index.js CHANGED
@@ -68,8 +68,8 @@ import { n as grInputSafelist, t as grInputConfig } from "./chunks/config-D19pyP
68
68
  import "./components/GrInput/index.js";
69
69
  import { n as grInputTagSafelist, t as grInputTagConfig } from "./chunks/config-DgRJlF00.js";
70
70
  import { t as GrInputTag_default } from "./components/GrInputTag/chunks/GrInputTag-B0x4U0Yk.js";
71
- import { n as grLinkSafelist, t as grLinkConfig } from "./chunks/config-Cf0J6wCX.js";
72
- import { t as GrLink_default } from "./components/GrLink/chunks/GrLink-C7-Y1u88.js";
71
+ import { n as grLinkSafelist, t as grLinkConfig } from "./chunks/config-DUtUkSzc.js";
72
+ import { t as GrLink_default } from "./components/GrLink/chunks/GrLink-BbN7R3iP.js";
73
73
  import { n as GrList_default, t as GrListItem_default } from "./components/GrList/chunks/GrList--Ib4zLNw.js";
74
74
  import { t as grListConfig } from "./chunks/config-fCcRwjIB.js";
75
75
  import { n as grLoadingSafelist, t as grLoadingConfig } from "./chunks/config-BN-B2K4r.js";
@@ -1,4 +1,4 @@
1
- export type GrLinkVariant = 'primary' | 'default' | 'muted' | 'danger';
1
+ export type GrLinkVariant = 'primary' | 'default' | 'muted' | 'muted-primary' | 'danger';
2
2
  export type GrLinkUnderline = 'auto' | 'always' | 'none';
3
3
  export type GrLinkSize = 'sm' | 'md' | 'lg';
4
4
  export declare const baseRootClass = "inline-flex items-center gap-1 rounded-[6px] transition-colors duration-150";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@feugene/granularity",
3
3
  "description": "Granularity design system package with Vue 3 components, consumed via the `@feugene/unocss-preset-granular` preset.",
4
- "version": "0.4.2",
4
+ "version": "0.4.3",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": {
7
7
  "name": "Evgeniy Fureev",
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-Cf0J6wCX.js","names":[],"sources":["../../src/components/GrLink/grLinkStyles.ts","../../src/components/GrLink/safelist.ts","../../src/components/GrLink/config.ts"],"sourcesContent":["export type GrLinkVariant = 'primary' | 'default' | 'muted' | 'danger'\nexport type GrLinkUnderline = 'auto' | 'always' | 'none'\nexport type GrLinkSize = 'sm' | 'md' | 'lg'\n\n// Базовые классы корневого элемента (`<a>`/`<span>`). Вынесены сюда,\n// чтобы быть единственным источником истины как для шаблона, так и для safelist.\nexport const baseRootClass = 'inline-flex items-center gap-1 rounded-[6px] transition-colors duration-150'\nexport const focusRingClass = 'focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)]'\n\nexport const sizeClassBySize: Record<GrLinkSize, string> = {\n sm: 'text-sm',\n md: 'text-[14px]',\n lg: 'text-base',\n}\n\nexport const variantClassByVariant: Record<GrLinkVariant, string> = {\n primary:\n 'text-[var(--primary)] visited:text-[var(--primary)] hover:text-[var(--primary-hover)] active:text-[var(--primary-active)]',\n default: 'text-[var(--fg)] hover:text-[var(--primary)] active:text-[var(--primary-active)]',\n muted: 'text-[var(--muted-fg)] hover:text-[var(--fg)] active:text-[var(--fg)]',\n danger: 'text-[var(--ds-danger)] hover:text-[var(--ds-danger-hover)] active:text-[var(--ds-danger-active)]',\n}\n\nexport const disabledStateClass = 'cursor-not-allowed opacity-60 text-[var(--muted-fg)]'\n\nconst UNDERLINE_VALUES: readonly GrLinkUnderline[] = ['auto', 'always', 'none']\n\nfunction underlineClass(underline: GrLinkUnderline, disabled: boolean): string {\n if (disabled) return 'no-underline'\n if (underline === 'always') return 'underline underline-offset-4'\n if (underline === 'none') return 'no-underline'\n return 'no-underline hover:underline hover:underline-offset-4'\n}\n\n// Derived from `underlineClass` so that there is a single source of truth:\n// any change/extension of the underline logic is automatically reflected\n// in the safelist without manual updates.\nexport const underlineClasses: readonly string[] = [...new Set(\n UNDERLINE_VALUES.flatMap(u => [underlineClass(u, false), underlineClass(u, true)]),\n)]\n\nfunction disabledClass(disabled: boolean): string {\n return disabled ? disabledStateClass : ''\n}\n\nexport function grLinkClass(options: { size: GrLinkSize, underline: GrLinkUnderline, variant: GrLinkVariant, disabled: boolean }): string {\n return [\n sizeClassBySize[options.size],\n underlineClass(options.underline, options.disabled),\n variantClassByVariant[options.variant],\n disabledClass(options.disabled),\n ]\n .filter(Boolean)\n .join(' ')\n}\n","import { splitClassTokens } from '../shared/classTokens'\nimport {\n baseRootClass,\n disabledStateClass,\n focusRingClass,\n sizeClassBySize,\n underlineClasses,\n variantClassByVariant,\n} from './grLinkStyles'\n\nexport const grLinkSafelist = [...new Set([\n ...splitClassTokens(baseRootClass),\n ...splitClassTokens(focusRingClass),\n ...Object.values(sizeClassBySize).flatMap(splitClassTokens),\n ...underlineClasses.flatMap(splitClassTokens),\n ...Object.values(variantClassByVariant).flatMap(splitClassTokens),\n ...splitClassTokens(disabledStateClass),\n])]\n","import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nimport { grLinkSafelist } from './safelist'\n\nexport const grLinkConfig = defineGranularComponent(import.meta.url, {\n name: 'GrLink',\n safelist: grLinkSafelist,\n})"],"mappings":";;;AAMA,IAAa,gBAAgB;AAC7B,IAAa,iBAAiB;AAE9B,IAAa,kBAA8C;CACzD,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AAED,IAAa,wBAAuD;CAClE,SACE;CACF,SAAS;CACT,OAAO;CACP,QAAQ;CACT;AAED,IAAa,qBAAqB;AAElC,IAAM,mBAA+C;CAAC;CAAQ;CAAU;CAAO;AAE/E,SAAS,eAAe,WAA4B,UAA2B;AAC7E,KAAI,SAAU,QAAO;AACrB,KAAI,cAAc,SAAU,QAAO;AACnC,KAAI,cAAc,OAAQ,QAAO;AACjC,QAAO;;AAMT,IAAa,mBAAsC,CAAC,GAAG,IAAI,IACzD,iBAAiB,SAAQ,MAAK,CAAC,eAAe,GAAG,MAAM,EAAE,eAAe,GAAG,KAAK,CAAC,CAAC,CACnF,CAAC;AAEF,SAAS,cAAc,UAA2B;AAChD,QAAO,WAAW,qBAAqB;;AAGzC,SAAgB,YAAY,SAA8G;AACxI,QAAO;EACL,gBAAgB,QAAQ;EACxB,eAAe,QAAQ,WAAW,QAAQ,SAAS;EACnD,sBAAsB,QAAQ;EAC9B,cAAc,QAAQ,SAAS;EAChC,CACE,OAAO,QAAQ,CACf,KAAK,IAAI;;;;AC3Cd,IAAa,iBAAiB,CAAC,GAAG,IAAI,IAAI;CACxC,GAAG,iBAAiB,cAAc;CAClC,GAAG,iBAAiB,eAAe;CACnC,GAAG,OAAO,OAAO,gBAAgB,CAAC,QAAQ,iBAAiB;CAC3D,GAAG,iBAAiB,QAAQ,iBAAiB;CAC7C,GAAG,OAAO,OAAO,sBAAsB,CAAC,QAAQ,iBAAiB;CACjE,GAAG,iBAAiB,mBAAmB;CACxC,CAAC,CAAC;;;ACbH,IAAa,eAAe,wBAAwB,OAAO,KAAK,KAAK;CACnE,MAAM;CACN,UAAU;CACX,CAAA"}