@sky.ui/core 0.0.41 → 0.0.43

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.
Files changed (109) hide show
  1. package/dist/custom-elements.json +1277 -541
  2. package/dist/helper/controllers/animation-controller.d.ts +4 -4
  3. package/dist/helper/controllers/animation-controller.js.map +1 -1
  4. package/dist/helper/controllers/index.d.ts +1 -0
  5. package/dist/helper/controllers/index.js +1 -1
  6. package/dist/helper/controllers/popover-controller.d.ts +1 -1
  7. package/dist/helper/controllers/popover-controller.js.map +1 -1
  8. package/dist/helper/controllers/preset-controller.d.ts +55 -0
  9. package/dist/helper/controllers/preset-controller.js +2 -0
  10. package/dist/helper/controllers/preset-controller.js.map +1 -0
  11. package/dist/helper/iconify-offline.js.map +1 -1
  12. package/dist/helper/index.js +1 -1
  13. package/dist/helper/internals/form-control-base.d.ts +2 -2
  14. package/dist/helper/internals/form-control-base.js.map +1 -1
  15. package/dist/helper/styles/focus-ring.d.ts +10 -0
  16. package/dist/helper/styles/focus-ring.js +10 -0
  17. package/dist/helper/styles/focus-ring.js.map +1 -0
  18. package/dist/helper/utils/color-resolver.d.ts +0 -14
  19. package/dist/helper/utils/color-resolver.js +1 -1
  20. package/dist/helper/utils/color-resolver.js.map +1 -1
  21. package/dist/helper/utils/component-presets.d.ts +132 -0
  22. package/dist/helper/utils/component-presets.js +2 -0
  23. package/dist/helper/utils/component-presets.js.map +1 -0
  24. package/dist/helper/utils/contrast-color.d.ts +2 -2
  25. package/dist/helper/utils/contrast-color.js.map +1 -1
  26. package/dist/helper/utils/index.d.ts +1 -0
  27. package/dist/helper/utils/index.js +1 -1
  28. package/dist/helper/utils/size-resolver.js.map +1 -1
  29. package/dist/index.js +1 -1
  30. package/dist/sky-alert/sky-alert.d.ts +12 -4
  31. package/dist/sky-alert/sky-alert.js +4 -4
  32. package/dist/sky-alert/sky-alert.js.map +1 -1
  33. package/dist/sky-appbar/sky-appbar.d.ts +9 -3
  34. package/dist/sky-appbar/sky-appbar.js +4 -4
  35. package/dist/sky-appbar/sky-appbar.js.map +1 -1
  36. package/dist/sky-avatar/sky-avatar.d.ts +5 -1
  37. package/dist/sky-avatar/sky-avatar.js +7 -7
  38. package/dist/sky-avatar/sky-avatar.js.map +1 -1
  39. package/dist/sky-badge/sky-badge.d.ts +6 -2
  40. package/dist/sky-badge/sky-badge.js +6 -6
  41. package/dist/sky-badge/sky-badge.js.map +1 -1
  42. package/dist/sky-button/sky-button.d.ts +24 -4
  43. package/dist/sky-button/sky-button.js +9 -8
  44. package/dist/sky-button/sky-button.js.map +1 -1
  45. package/dist/sky-card/sky-card.d.ts +10 -2
  46. package/dist/sky-card/sky-card.js +4 -4
  47. package/dist/sky-card/sky-card.js.map +1 -1
  48. package/dist/sky-checkbox/sky-checkbox.d.ts +6 -3
  49. package/dist/sky-checkbox/sky-checkbox.js +47 -40
  50. package/dist/sky-checkbox/sky-checkbox.js.map +1 -1
  51. package/dist/sky-chip/sky-chip.d.ts +6 -2
  52. package/dist/sky-chip/sky-chip.js +10 -9
  53. package/dist/sky-chip/sky-chip.js.map +1 -1
  54. package/dist/sky-col/sky-col.d.ts +5 -1
  55. package/dist/sky-col/sky-col.js +4 -4
  56. package/dist/sky-col/sky-col.js.map +1 -1
  57. package/dist/sky-combobox/sky-combobox.d.ts +9 -2
  58. package/dist/sky-combobox/sky-combobox.js +27 -58
  59. package/dist/sky-combobox/sky-combobox.js.map +1 -1
  60. package/dist/sky-dialog/sky-dialog.d.ts +5 -1
  61. package/dist/sky-dialog/sky-dialog.js +3 -3
  62. package/dist/sky-dialog/sky-dialog.js.map +1 -1
  63. package/dist/sky-divider/sky-divider.d.ts +5 -1
  64. package/dist/sky-divider/sky-divider.js +5 -5
  65. package/dist/sky-divider/sky-divider.js.map +1 -1
  66. package/dist/sky-flexbox/sky-flexbox.d.ts +5 -1
  67. package/dist/sky-flexbox/sky-flexbox.js +4 -4
  68. package/dist/sky-flexbox/sky-flexbox.js.map +1 -1
  69. package/dist/sky-flexcol/sky-flexcol.d.ts +5 -1
  70. package/dist/sky-flexcol/sky-flexcol.js +2 -2
  71. package/dist/sky-flexcol/sky-flexcol.js.map +1 -1
  72. package/dist/sky-form/sky-form.d.ts +5 -1
  73. package/dist/sky-form/sky-form.js +2 -2
  74. package/dist/sky-form/sky-form.js.map +1 -1
  75. package/dist/sky-grid/sky-grid.d.ts +5 -1
  76. package/dist/sky-grid/sky-grid.js +3 -3
  77. package/dist/sky-grid/sky-grid.js.map +1 -1
  78. package/dist/sky-icon/sky-icon.d.ts +4 -1
  79. package/dist/sky-icon/sky-icon.js +4 -4
  80. package/dist/sky-icon/sky-icon.js.map +1 -1
  81. package/dist/sky-image/sky-image.d.ts +5 -1
  82. package/dist/sky-image/sky-image.js +5 -5
  83. package/dist/sky-image/sky-image.js.map +1 -1
  84. package/dist/sky-image/srcset-utils.js.map +1 -1
  85. package/dist/sky-input/sky-input.d.ts +5 -1
  86. package/dist/sky-input/sky-input.js +111 -111
  87. package/dist/sky-input/sky-input.js.map +1 -1
  88. package/dist/sky-list/sky-list.d.ts +5 -1
  89. package/dist/sky-list/sky-list.js +3 -3
  90. package/dist/sky-list/sky-list.js.map +1 -1
  91. package/dist/sky-listitem/sky-listitem.d.ts +5 -1
  92. package/dist/sky-listitem/sky-listitem.js +3 -3
  93. package/dist/sky-listitem/sky-listitem.js.map +1 -1
  94. package/dist/sky-radio/sky-radio.d.ts +8 -3
  95. package/dist/sky-radio/sky-radio.js +4 -3
  96. package/dist/sky-radio/sky-radio.js.map +1 -1
  97. package/dist/sky-row/sky-row.d.ts +4 -1
  98. package/dist/sky-row/sky-row.js +2 -2
  99. package/dist/sky-row/sky-row.js.map +1 -1
  100. package/dist/sky-sheet/sky-sheet.d.ts +7 -2
  101. package/dist/sky-sheet/sky-sheet.js +2 -2
  102. package/dist/sky-sheet/sky-sheet.js.map +1 -1
  103. package/dist/sky-simple-table/sky-simple-table.d.ts +5 -1
  104. package/dist/sky-simple-table/sky-simple-table.js +3 -3
  105. package/dist/sky-simple-table/sky-simple-table.js.map +1 -1
  106. package/dist/sky-theme-provider/sky-theme-provider.d.ts +1 -1
  107. package/dist/sky-theme-provider/sky-theme-provider.js +2 -2
  108. package/dist/sky-theme-provider/sky-theme-provider.js.map +1 -1
  109. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"contrast-color.js","sources":["../../../src/helper/utils/contrast-color.ts"],"sourcesContent":["/**\n * CSS `contrast-color()` helpers for solid fills, plus JS luminance helpers\n * for canvas / SVG / preview surfaces where native CSS contrast cannot apply.\n *\n * Use only on opaque / solid surfaces. Soft tints, glass, and hover washes\n * should keep theme ink tokens (`--sky-text-primary`, soft semantic darks).\n *\n * Always declare a CSS fallback first; wrap the enhance rule in `@supports`.\n *\n * @see components-raw/CONTRAST_COLOR_AUDIT_PLAN.md\n */\n\nexport type RgbChannels = { r: number; g: number; b: number };\n\n/**\n * Parse `#rgb` / `#rrggbb` / `rgb()` / `rgba()` into 0–255 channels.\n * Returns `null` for CSS vars, named colors, oklch, etc.\n */\nexport function parseCssRgb(color: string): RgbChannels | null {\n const trimmed = color.trim();\n if (!trimmed) return null;\n\n if (trimmed.startsWith(\"#\")) {\n const hex = trimmed.slice(1);\n if (hex.length === 3 || hex.length === 4) {\n const r = parseInt(hex[0] + hex[0], 16);\n const g = parseInt(hex[1] + hex[1], 16);\n const b = parseInt(hex[2] + hex[2], 16);\n if ([r, g, b].some((n) => Number.isNaN(n))) return null;\n return { r, g, b };\n }\n if (hex.length === 6 || hex.length === 8) {\n const r = parseInt(hex.slice(0, 2), 16);\n const g = parseInt(hex.slice(2, 4), 16);\n const b = parseInt(hex.slice(4, 6), 16);\n if ([r, g, b].some((n) => Number.isNaN(n))) return null;\n return { r, g, b };\n }\n return null;\n }\n\n const m = trimmed.match(\n /^rgba?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)/i,\n );\n if (!m) return null;\n return {\n r: Math.min(255, Math.max(0, Number(m[1]))),\n g: Math.min(255, Math.max(0, Number(m[2]))),\n b: Math.min(255, Math.max(0, Number(m[3]))),\n };\n}\n\n/**\n * Rec.601 perceived luminance in 0–1 (matches historical chart/theme-gen usage).\n */\nexport function perceivedLuminance(rgb: RgbChannels): number {\n return (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;\n}\n\nfunction srgbChannelToLinear(v: number): number {\n const c = v / 255;\n return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\n/** WCAG 2.1 relative luminance in 0–1. */\nexport function relativeLuminance(rgb: RgbChannels): number {\n return (\n 0.2126 * srgbChannelToLinear(rgb.r) +\n 0.7152 * srgbChannelToLinear(rgb.g) +\n 0.0722 * srgbChannelToLinear(rgb.b)\n );\n}\n\nexport type LuminanceMode = \"perceived\" | \"wcag\";\n\nfunction luminanceOf(\n rgb: RgbChannels,\n mode: LuminanceMode = \"perceived\",\n): number {\n return mode === \"wcag\" ? relativeLuminance(rgb) : perceivedLuminance(rgb);\n}\n\n/**\n * True when the fill is “light” enough that dark FG/overlays read better.\n * Unparseable colors return `false` (assume dark fill / light FG).\n */\nexport function isLightFill(\n color: string,\n threshold = 0.5,\n mode: LuminanceMode = \"perceived\",\n): boolean {\n const rgb = parseCssRgb(color);\n if (!rgb) return false;\n return luminanceOf(rgb, mode) > threshold;\n}\n\nexport type ContrastOnFillOptions = {\n /** Returned / used when the fill is light. */\n onLight?: string;\n /** Returned / used when the fill is dark. */\n onDark?: string;\n /** Luminance cutover. Default `0.5`. */\n threshold?: number;\n /** Default `perceived` (Rec.601). Use `wcag` for AA-aligned picks. */\n mode?: LuminanceMode;\n /** When parse fails. Defaults to `onDark`. */\n fallback?: string;\n};\n\n/**\n * Pick an opaque FG string for canvas / SVG paints against a solid fill.\n * Defaults: black on light fills, white on dark fills.\n */\nexport function contrastOnFill(\n color: string,\n options: ContrastOnFillOptions = {},\n): string {\n const {\n onLight = \"#000000\",\n onDark = \"#ffffff\",\n threshold = 0.5,\n mode = \"perceived\",\n fallback = onDark,\n } = options;\n const rgb = parseCssRgb(color);\n if (!rgb) return fallback;\n return luminanceOf(rgb, mode) > threshold ? onLight : onDark;\n}\n\n/**\n * Semi-transparent overlay for patterns / ripples on a solid fill.\n */\nexport function contrastOverlay(\n color: string,\n options: ContrastOnFillOptions = {},\n): string {\n return contrastOnFill(color, {\n onLight: \"rgba(0,0,0,0.55)\",\n onDark: \"rgba(255,255,255,0.6)\",\n threshold: 0.5,\n mode: \"perceived\",\n ...options,\n });\n}\n\n/**\n * Theme preview ink: primary on light swatches, inverse on dark.\n * Unparseable / non-hex CSS values fall back to `onLight` (theme text).\n */\nexport function contrastThemeInk(\n color: string,\n options: ContrastOnFillOptions = {},\n): string {\n return contrastOnFill(color, {\n onLight: \"var(--sky-text-primary)\",\n onDark: \"var(--sky-text-inverse)\",\n threshold: 0.6,\n mode: \"perceived\",\n fallback: \"var(--sky-text-primary)\",\n ...options,\n });\n}\n\n/** Feature query used by every `@supports` enhance block. */\nexport const CONTRAST_COLOR_SUPPORT_QUERY = \"(color: contrast-color(red))\" as const;\n\n/** Fallback FG when the fill is assumed dark (most brand solids). */\nexport const ON_COLOR_FALLBACK_LIGHT = \"var(--sky-on-color-fallback-light, var(--sky-text-white))\" as const;\n\n/** Fallback FG when the fill is assumed light (e.g. warning / success). */\nexport const ON_COLOR_FALLBACK_DARK = \"var(--sky-on-color-fallback-dark, var(--sky-text-black))\" as const;\n\nfunction asCssVarRef(fillVar: string): string {\n const trimmed = fillVar.trim();\n if (trimmed.startsWith(\"var(\")) return trimmed;\n if (trimmed.startsWith(\"--\")) return `var(${trimmed})`;\n return trimmed;\n}\n\n/**\n * Returns `contrast-color(var(--fill))` (or `contrast-color(<color>)`).\n */\nexport function cssContrastColor(fillVar: string): string {\n return `contrast-color(${asCssVarRef(fillVar)})`;\n}\n\nexport type CssOnFillOptions = {\n /**\n * Selector whose `color` should follow the fill\n * (e.g. `.chip`, `button`, `:host([variant=\"solid\"]) button`).\n */\n selector: string;\n /**\n * Fill custom property or `var()` expression to contrast against\n * (e.g. `--chip-bg-color`, `var(--btn-bg-color)`).\n */\n fillVar: string;\n /**\n * Pre-`@supports` fallback. Defaults to on-color light (white) token.\n * Pass `false` to omit the fallback declaration (when the selector already sets `color`).\n */\n fallback?: string | false;\n /**\n * Appended to `selector` inside `@supports` only\n * (e.g. `:not([data-text-explicit])`).\n */\n enhanceSuffix?: string;\n /** CSS property to set. Default `color`. */\n property?: string;\n};\n\n/**\n * Fallback-first + `@supports` enhance block for a solid fill foreground.\n *\n * @example\n * ```ts\n * css`\n * ${unsafeCSS(cssOnFill({\n * selector: \".chip\",\n * fillVar: \"--chip-bg-color\",\n * fallback: \"var(--chip-text-color)\",\n * enhanceSuffix: \":not([data-text-explicit])\",\n * }))}\n * `\n * ```\n */\nexport function cssOnFill(options: CssOnFillOptions): string {\n const {\n selector,\n fillVar,\n fallback = ON_COLOR_FALLBACK_LIGHT,\n enhanceSuffix = \"\",\n property = \"color\",\n } = options;\n\n const fill = asCssVarRef(fillVar);\n const enhanceSelector = `${selector}${enhanceSuffix}`;\n const fallbackRule =\n fallback === false\n ? \"\"\n : `${selector} {\\n ${property}: ${fallback};\\n}\\n`;\n\n return `${fallbackRule}@supports ${CONTRAST_COLOR_SUPPORT_QUERY} {\n ${enhanceSelector} {\n ${property}: ${cssContrastColor(fill)};\n }\n}`;\n}\n\n/**\n * Multi-rule `@supports` enhance only (no fallback declarations).\n * Use when selectors already set fallback `color` via other rules / inline vars.\n *\n * @example\n * ```ts\n * css`\n * button { color: var(--btn-color); }\n * ${unsafeCSS(cssOnFillEnhance([\n * { selector: ':host([variant=\"solid\"]:not([data-text-explicit])) button', fillVar: '--btn-bg-color' },\n * ]))}\n * `\n * ```\n */\nexport function cssOnFillEnhance(\n rules: Array<{\n selector: string;\n fillVar: string;\n property?: string;\n }>,\n): string {\n if (!rules.length) return \"\";\n\n const body = rules\n .map(({ selector, fillVar, property = \"color\" }) => {\n return ` ${selector} {\\n ${property}: ${cssContrastColor(fillVar)};\\n }`;\n })\n .join(\"\\n\");\n\n return `@supports ${CONTRAST_COLOR_SUPPORT_QUERY} {\\n${body}\\n}`;\n}\n"],"names":["parseCssRgb","color","trimmed","trim","startsWith","hex","slice","length","r","parseInt","g","b","some","n","Number","isNaN","m","match","Math","min","max","perceivedLuminance","rgb","srgbChannelToLinear","v","c","pow","relativeLuminance","luminanceOf","mode","isLightFill","threshold","contrastOnFill","options","onLight","onDark","fallback","contrastOverlay","contrastThemeInk","CONTRAST_COLOR_SUPPORT_QUERY","ON_COLOR_FALLBACK_LIGHT","ON_COLOR_FALLBACK_DARK","asCssVarRef","fillVar","cssContrastColor","cssOnFill","selector","enhanceSuffix","property","fill","cssOnFillEnhance","rules","body","map","join"],"mappings":"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"}
1
+ {"version":3,"file":"contrast-color.js","sources":["../../../src/helper/utils/contrast-color.ts"],"sourcesContent":["/**\r\n * CSS `contrast-color()` helpers for solid fills, plus JS luminance helpers\r\n * for canvas / SVG / preview surfaces where native CSS contrast cannot apply.\r\n *\r\n * Use only on opaque / solid surfaces. Soft tints, glass, and hover washes\r\n * should keep theme ink tokens (`--sky-text-primary`, soft semantic darks).\r\n *\r\n * Always declare a CSS fallback first; wrap the enhance rule in `@supports`.\r\n *\r\n * @see components-raw/CONTRAST_COLOR_AUDIT_PLAN.md\r\n */\r\n\r\nexport type RgbChannels = { r: number; g: number; b: number };\r\n\r\n/**\r\n * Parse `#rgb` / `#rrggbb` / `rgb()` / `rgba()` into 0–255 channels.\r\n * Returns `null` for CSS vars, named colors, oklch, etc.\r\n */\r\nexport function parseCssRgb(color: string): RgbChannels | null {\r\n const trimmed = color.trim();\r\n if (!trimmed) return null;\r\n\r\n if (trimmed.startsWith(\"#\")) {\r\n const hex = trimmed.slice(1);\r\n if (hex.length === 3 || hex.length === 4) {\r\n const r = parseInt(hex[0] + hex[0], 16);\r\n const g = parseInt(hex[1] + hex[1], 16);\r\n const b = parseInt(hex[2] + hex[2], 16);\r\n if ([r, g, b].some((n) => Number.isNaN(n))) return null;\r\n return { r, g, b };\r\n }\r\n if (hex.length === 6 || hex.length === 8) {\r\n const r = parseInt(hex.slice(0, 2), 16);\r\n const g = parseInt(hex.slice(2, 4), 16);\r\n const b = parseInt(hex.slice(4, 6), 16);\r\n if ([r, g, b].some((n) => Number.isNaN(n))) return null;\r\n return { r, g, b };\r\n }\r\n return null;\r\n }\r\n\r\n const m = trimmed.match(\r\n /^rgba?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)/i,\r\n );\r\n if (!m) return null;\r\n return {\r\n r: Math.min(255, Math.max(0, Number(m[1]))),\r\n g: Math.min(255, Math.max(0, Number(m[2]))),\r\n b: Math.min(255, Math.max(0, Number(m[3]))),\r\n };\r\n}\r\n\r\n/**\r\n * Rec.601 perceived luminance in 0–1 (matches historical chart/theme-gen usage).\r\n */\r\nexport function perceivedLuminance(rgb: RgbChannels): number {\r\n return (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;\r\n}\r\n\r\nfunction srgbChannelToLinear(v: number): number {\r\n const c = v / 255;\r\n return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\r\n}\r\n\r\n/** WCAG 2.1 relative luminance in 0–1. */\r\nexport function relativeLuminance(rgb: RgbChannels): number {\r\n return (\r\n 0.2126 * srgbChannelToLinear(rgb.r) +\r\n 0.7152 * srgbChannelToLinear(rgb.g) +\r\n 0.0722 * srgbChannelToLinear(rgb.b)\r\n );\r\n}\r\n\r\nexport type LuminanceMode = \"perceived\" | \"wcag\";\r\n\r\nfunction luminanceOf(\r\n rgb: RgbChannels,\r\n mode: LuminanceMode = \"perceived\",\r\n): number {\r\n return mode === \"wcag\" ? relativeLuminance(rgb) : perceivedLuminance(rgb);\r\n}\r\n\r\n/**\r\n * True when the fill is “light” enough that dark FG/overlays read better.\r\n * Unparseable colors return `false` (assume dark fill / light FG).\r\n */\r\nexport function isLightFill(\r\n color: string,\r\n threshold = 0.5,\r\n mode: LuminanceMode = \"perceived\",\r\n): boolean {\r\n const rgb = parseCssRgb(color);\r\n if (!rgb) return false;\r\n return luminanceOf(rgb, mode) > threshold;\r\n}\r\n\r\nexport type ContrastOnFillOptions = {\r\n /** Returned / used when the fill is light. */\r\n onLight?: string;\r\n /** Returned / used when the fill is dark. */\r\n onDark?: string;\r\n /** Luminance cutover. Default `0.5`. */\r\n threshold?: number;\r\n /** Default `perceived` (Rec.601). Use `wcag` for AA-aligned picks. */\r\n mode?: LuminanceMode;\r\n /** When parse fails. Defaults to `onDark`. */\r\n fallback?: string;\r\n};\r\n\r\n/**\r\n * Pick an opaque FG string for canvas / SVG paints against a solid fill.\r\n * Defaults: black on light fills, white on dark fills.\r\n */\r\nexport function contrastOnFill(\r\n color: string,\r\n options: ContrastOnFillOptions = {},\r\n): string {\r\n const {\r\n onLight = \"#000000\",\r\n onDark = \"#ffffff\",\r\n threshold = 0.5,\r\n mode = \"perceived\",\r\n fallback = onDark,\r\n } = options;\r\n const rgb = parseCssRgb(color);\r\n if (!rgb) return fallback;\r\n return luminanceOf(rgb, mode) > threshold ? onLight : onDark;\r\n}\r\n\r\n/**\r\n * Semi-transparent overlay for patterns / ripples on a solid fill.\r\n */\r\nexport function contrastOverlay(\r\n color: string,\r\n options: ContrastOnFillOptions = {},\r\n): string {\r\n return contrastOnFill(color, {\r\n onLight: \"rgba(0,0,0,0.55)\",\r\n onDark: \"rgba(255,255,255,0.6)\",\r\n threshold: 0.5,\r\n mode: \"perceived\",\r\n ...options,\r\n });\r\n}\r\n\r\n/**\r\n * Theme preview ink: primary on light swatches, inverse on dark.\r\n * Unparseable / non-hex CSS values fall back to `onLight` (theme text).\r\n */\r\nexport function contrastThemeInk(\r\n color: string,\r\n options: ContrastOnFillOptions = {},\r\n): string {\r\n return contrastOnFill(color, {\r\n onLight: \"var(--sky-text-primary)\",\r\n onDark: \"var(--sky-text-inverse)\",\r\n threshold: 0.6,\r\n mode: \"perceived\",\r\n fallback: \"var(--sky-text-primary)\",\r\n ...options,\r\n });\r\n}\r\n\r\n/** Feature query used by every `@supports` enhance block. */\r\nexport const CONTRAST_COLOR_SUPPORT_QUERY = \"(color: contrast-color(red))\" as const;\r\n\r\n/** Fallback FG when the fill is assumed dark (most brand solids / no-@supports). */\r\nexport const ON_COLOR_FALLBACK_LIGHT = \"var(--sky-on-color-fallback-light, var(--sky-text-white))\" as const;\r\n\r\n/** Fallback FG when a JS luminance check finds a light fill (canvas / SVG only). */\r\nexport const ON_COLOR_FALLBACK_DARK = \"var(--sky-on-color-fallback-dark, var(--sky-text-black))\" as const;\r\n\r\nfunction asCssVarRef(fillVar: string): string {\r\n const trimmed = fillVar.trim();\r\n if (trimmed.startsWith(\"var(\")) return trimmed;\r\n if (trimmed.startsWith(\"--\")) return `var(${trimmed})`;\r\n return trimmed;\r\n}\r\n\r\n/**\r\n * Returns `contrast-color(var(--fill))` (or `contrast-color(<color>)`).\r\n */\r\nexport function cssContrastColor(fillVar: string): string {\r\n return `contrast-color(${asCssVarRef(fillVar)})`;\r\n}\r\n\r\nexport type CssOnFillOptions = {\r\n /**\r\n * Selector whose `color` should follow the fill\r\n * (e.g. `.chip`, `button`, `:host([variant=\"solid\"]) button`).\r\n */\r\n selector: string;\r\n /**\r\n * Fill custom property or `var()` expression to contrast against\r\n * (e.g. `--chip-bg-color`, `var(--btn-bg-color)`).\r\n */\r\n fillVar: string;\r\n /**\r\n * Pre-`@supports` fallback. Defaults to on-color light (white) token.\r\n * Pass `false` to omit the fallback declaration (when the selector already sets `color`).\r\n */\r\n fallback?: string | false;\r\n /**\r\n * Appended to `selector` inside `@supports` only\r\n * (e.g. `:not([data-text-explicit])`).\r\n */\r\n enhanceSuffix?: string;\r\n /** CSS property to set. Default `color`. */\r\n property?: string;\r\n};\r\n\r\n/**\r\n * Fallback-first + `@supports` enhance block for a solid fill foreground.\r\n *\r\n * @example\r\n * ```ts\r\n * css`\r\n * ${unsafeCSS(cssOnFill({\r\n * selector: \".chip\",\r\n * fillVar: \"--chip-bg-color\",\r\n * fallback: \"var(--chip-text-color)\",\r\n * enhanceSuffix: \":not([data-text-explicit])\",\r\n * }))}\r\n * `\r\n * ```\r\n */\r\nexport function cssOnFill(options: CssOnFillOptions): string {\r\n const {\r\n selector,\r\n fillVar,\r\n fallback = ON_COLOR_FALLBACK_LIGHT,\r\n enhanceSuffix = \"\",\r\n property = \"color\",\r\n } = options;\r\n\r\n const fill = asCssVarRef(fillVar);\r\n const enhanceSelector = `${selector}${enhanceSuffix}`;\r\n const fallbackRule =\r\n fallback === false\r\n ? \"\"\r\n : `${selector} {\\n ${property}: ${fallback};\\n}\\n`;\r\n\r\n return `${fallbackRule}@supports ${CONTRAST_COLOR_SUPPORT_QUERY} {\r\n ${enhanceSelector} {\r\n ${property}: ${cssContrastColor(fill)};\r\n }\r\n}`;\r\n}\r\n\r\n/**\r\n * Multi-rule `@supports` enhance only (no fallback declarations).\r\n * Use when selectors already set fallback `color` via other rules / inline vars.\r\n *\r\n * @example\r\n * ```ts\r\n * css`\r\n * button { color: var(--btn-color); }\r\n * ${unsafeCSS(cssOnFillEnhance([\r\n * { selector: ':host([variant=\"solid\"]:not([data-text-explicit])) button', fillVar: '--btn-bg-color' },\r\n * ]))}\r\n * `\r\n * ```\r\n */\r\nexport function cssOnFillEnhance(\r\n rules: Array<{\r\n selector: string;\r\n fillVar: string;\r\n property?: string;\r\n }>,\r\n): string {\r\n if (!rules.length) return \"\";\r\n\r\n const body = rules\r\n .map(({ selector, fillVar, property = \"color\" }) => {\r\n return ` ${selector} {\\n ${property}: ${cssContrastColor(fillVar)};\\n }`;\r\n })\r\n .join(\"\\n\");\r\n\r\n return `@supports ${CONTRAST_COLOR_SUPPORT_QUERY} {\\n${body}\\n}`;\r\n}\r\n"],"names":["parseCssRgb","color","trimmed","trim","startsWith","hex","slice","length","r","parseInt","g","b","some","n","Number","isNaN","m","match","Math","min","max","perceivedLuminance","rgb","srgbChannelToLinear","v","c","pow","relativeLuminance","luminanceOf","mode","isLightFill","threshold","contrastOnFill","options","onLight","onDark","fallback","contrastOverlay","contrastThemeInk","CONTRAST_COLOR_SUPPORT_QUERY","ON_COLOR_FALLBACK_LIGHT","ON_COLOR_FALLBACK_DARK","asCssVarRef","fillVar","cssContrastColor","cssOnFill","selector","enhanceSuffix","property","fill","cssOnFillEnhance","rules","body","map","join"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export * from "./color-resolver";
2
+ export * from "./component-presets";
2
3
  export * from "./contrast-color";
3
4
  export * from "./size-resolver";
@@ -1,2 +1,2 @@
1
- export{ColorResolver,DEFAULT_COLOR_TOKENS,colorResolver,createGradient,darkShade,fadeMix,hoverShade,isDefaultColorToken,lightShade,parseGradientSpec,resolveAccentColorForToken,resolveColor,resolveGradientStop,resolveInkColorForToken,resolveSemanticSurfaceKey,resolveTextColorForToken,semanticSoftSurfaceTokens,skyBorderPrimaryShorthand,skyBorderWidthSolid,tuneSurfaceVariantForDefaultColor}from"./color-resolver.js";export{CONTRAST_COLOR_SUPPORT_QUERY,ON_COLOR_FALLBACK_DARK,ON_COLOR_FALLBACK_LIGHT,contrastOnFill,contrastOverlay,contrastThemeInk,cssContrastColor,cssOnFill,cssOnFillEnhance,isLightFill,parseCssRgb,perceivedLuminance,relativeLuminance}from"./contrast-color.js";export{resolveRadius}from"./size-resolver.js";
1
+ export{ColorResolver,DEFAULT_COLOR_TOKENS,colorResolver,createGradient,darkShade,fadeMix,hoverShade,isDefaultColorToken,lightShade,parseGradientSpec,resolveAccentColorForToken,resolveColor,resolveGradientStop,resolveInkColorForToken,resolveSemanticSurfaceKey,semanticSoftSurfaceTokens,skyBorderPrimaryShorthand,skyBorderWidthSolid,tuneSurfaceVariantForDefaultColor}from"./color-resolver.js";export{applyPresetLayer,camelToKebab,captureInitialUserAttributes,clearAppliedPresetLayer,configContext,findNearestPresetsConfig,getPresetLayer,isUserSetProp,lookupPresetSection,markUserSetProp,mergePresetsConfig,presetKeyAliases,refreshUserAttributes,resolveComponentProps,toPresetTagKey}from"./component-presets.js";export{CONTRAST_COLOR_SUPPORT_QUERY,ON_COLOR_FALLBACK_DARK,ON_COLOR_FALLBACK_LIGHT,contrastOnFill,contrastOverlay,contrastThemeInk,cssContrastColor,cssOnFill,cssOnFillEnhance,isLightFill,parseCssRgb,perceivedLuminance,relativeLuminance}from"./contrast-color.js";export{resolveRadius}from"./size-resolver.js";
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"size-resolver.js","sources":["../../../src/helper/utils/size-resolver.ts"],"sourcesContent":["/**\r\n * Resolves a radius input into a valid CSS radius value.\r\n * @param input - The radius input (`sm`, `md`, `lg`, `full`, `none`, or CSS length).\r\n * @returns The resolved CSS radius value.\r\n */\r\nexport function resolveRadius(input: string) {\r\n const map: Record<string, string> = {\r\n none: \"0px\",\r\n sm: \"var(--sky-radius-primary)\",\r\n md: \"var(--sky-radius-secondary)\",\r\n lg: \"var(--sky-radius-tertiary)\",\r\n full: \"9999px\",\r\n };\r\n return Object.prototype.hasOwnProperty.call(map, input)\r\n ? map[input]\r\n : input;\r\n }"],"names":["resolveRadius","input","map","none","sm","md","lg","full","Object","prototype","hasOwnProperty","call"],"mappings":"AAKO,SAASA,EAAcC,GAC1B,MAAMC,EAA8B,CAClCC,KAAM,MACNC,GAAI,4BACJC,GAAI,8BACJC,GAAI,6BACJC,KAAM,UAER,OAAOC,OAAOC,UAAUC,eAAeC,KAAKT,EAAKD,GAC7CC,EAAID,GACJA,CACN"}
1
+ {"version":3,"file":"size-resolver.js","sources":["../../../src/helper/utils/size-resolver.ts"],"sourcesContent":["/**\r\n * Resolves a radius input into a valid CSS radius value.\r\n * @param input - The radius input (`sm`, `md`, `lg`, `full`, `none`, or CSS length).\r\n * @returns The resolved CSS radius value.\r\n */\r\nexport function resolveRadius(input: string) {\r\n const map: Record<string, string> = {\r\n none: '0px',\r\n sm: 'var(--sky-radius-primary)',\r\n md: 'var(--sky-radius-secondary)',\r\n lg: 'var(--sky-radius-tertiary)',\r\n full: '9999px',\r\n };\r\n return Object.prototype.hasOwnProperty.call(map, input) ? map[input] : input;\r\n}\r\n"],"names":["resolveRadius","input","map","none","sm","md","lg","full","Object","prototype","hasOwnProperty","call"],"mappings":"AAKO,SAASA,EAAcC,GAC5B,MAAMC,EAA8B,CAClCC,KAAM,MACNC,GAAI,4BACJC,GAAI,8BACJC,GAAI,6BACJC,KAAM,UAER,OAAOC,OAAOC,UAAUC,eAAeC,KAAKT,EAAKD,GAASC,EAAID,GAASA,CACzE"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export{html}from"lit";export{AnimationController}from"./helper/controllers/animation-controller.js";export{CONTRAST_COLOR_SUPPORT_QUERY,ON_COLOR_FALLBACK_DARK,ON_COLOR_FALLBACK_LIGHT,contrastOnFill,contrastOverlay,contrastThemeInk,cssContrastColor,cssOnFill,cssOnFillEnhance,isLightFill,parseCssRgb,perceivedLuminance,relativeLuminance}from"./helper/utils/contrast-color.js";export{ColorResolver,DEFAULT_COLOR_TOKENS,colorResolver,createGradient,darkShade,fadeMix,hoverShade,isDefaultColorToken,lightShade,parseGradientSpec,resolveAccentColorForToken,resolveColor,resolveGradientStop,resolveInkColorForToken,resolveSemanticSurfaceKey,resolveTextColorForToken,semanticSoftSurfaceTokens,skyBorderPrimaryShorthand,skyBorderWidthSolid,tuneSurfaceVariantForDefaultColor}from"./helper/utils/color-resolver.js";export{FormControlBase}from"./helper/internals/form-control-base.js";export{PopoverController}from"./helper/controllers/popover-controller.js";export{SkyAlert}from"./sky-alert/sky-alert.js";export{SkyAppbar}from"./sky-appbar/sky-appbar.js";export{SkyAvatar}from"./sky-avatar/sky-avatar.js";export{SkyBadge}from"./sky-badge/sky-badge.js";export{SkyButton}from"./sky-button/sky-button.js";export{SkyCard}from"./sky-card/sky-card.js";export{SkyCheckbox}from"./sky-checkbox/sky-checkbox.js";export{SkyChip}from"./sky-chip/sky-chip.js";export{SkyCol}from"./sky-col/sky-col.js";export{SkyCombobox}from"./sky-combobox/sky-combobox.js";export{SkyDialog}from"./sky-dialog/sky-dialog.js";export{SkyDivider}from"./sky-divider/sky-divider.js";export{SkyFlexbox}from"./sky-flexbox/sky-flexbox.js";export{SkyFlexcol}from"./sky-flexcol/sky-flexcol.js";export{SkyForm}from"./sky-form/sky-form.js";export{SkyGrid}from"./sky-grid/sky-grid.js";export{SkyIcon}from"./sky-icon/sky-icon.js";export{SkyImage}from"./sky-image/sky-image.js";export{SkyInput}from"./sky-input/sky-input.js";export{SkyList}from"./sky-list/sky-list.js";export{SkyListitem}from"./sky-listitem/sky-listitem.js";export{SkyRadio}from"./sky-radio/sky-radio.js";export{SkyRow}from"./sky-row/sky-row.js";export{SkySheet,resolveSheetRadius}from"./sky-sheet/sky-sheet.js";export{SkySimpleTable}from"./sky-simple-table/sky-simple-table.js";export{SkyThemeProvider,defaultTheme,getCurrentTheme,getThemePreference,mergeTheme,onThemeChange,resolveActualTheme,themeContext}from"./sky-theme-provider/sky-theme-provider.js";export{extractIconNames,fetchIconsForOffline,registerOfflineIcons}from"./helper/iconify-offline.js";export{resolveRadius}from"./helper/utils/size-resolver.js";
1
+ export{html}from"lit";export{AnimationController}from"./helper/controllers/animation-controller.js";export{CONTRAST_COLOR_SUPPORT_QUERY,ON_COLOR_FALLBACK_DARK,ON_COLOR_FALLBACK_LIGHT,contrastOnFill,contrastOverlay,contrastThemeInk,cssContrastColor,cssOnFill,cssOnFillEnhance,isLightFill,parseCssRgb,perceivedLuminance,relativeLuminance}from"./helper/utils/contrast-color.js";export{ColorResolver,DEFAULT_COLOR_TOKENS,colorResolver,createGradient,darkShade,fadeMix,hoverShade,isDefaultColorToken,lightShade,parseGradientSpec,resolveAccentColorForToken,resolveColor,resolveGradientStop,resolveInkColorForToken,resolveSemanticSurfaceKey,semanticSoftSurfaceTokens,skyBorderPrimaryShorthand,skyBorderWidthSolid,tuneSurfaceVariantForDefaultColor}from"./helper/utils/color-resolver.js";export{FormControlBase}from"./helper/internals/form-control-base.js";export{PopoverController}from"./helper/controllers/popover-controller.js";export{PresetController}from"./helper/controllers/preset-controller.js";export{SkyAlert}from"./sky-alert/sky-alert.js";export{SkyAppbar}from"./sky-appbar/sky-appbar.js";export{SkyAvatar}from"./sky-avatar/sky-avatar.js";export{SkyBadge}from"./sky-badge/sky-badge.js";export{SkyButton}from"./sky-button/sky-button.js";export{SkyCard}from"./sky-card/sky-card.js";export{SkyCheckbox}from"./sky-checkbox/sky-checkbox.js";export{SkyChip}from"./sky-chip/sky-chip.js";export{SkyCol}from"./sky-col/sky-col.js";export{SkyCombobox}from"./sky-combobox/sky-combobox.js";export{SkyDialog}from"./sky-dialog/sky-dialog.js";export{SkyDivider}from"./sky-divider/sky-divider.js";export{SkyFlexbox}from"./sky-flexbox/sky-flexbox.js";export{SkyFlexcol}from"./sky-flexcol/sky-flexcol.js";export{SkyForm}from"./sky-form/sky-form.js";export{SkyGrid}from"./sky-grid/sky-grid.js";export{SkyIcon}from"./sky-icon/sky-icon.js";export{SkyImage}from"./sky-image/sky-image.js";export{SkyInput}from"./sky-input/sky-input.js";export{SkyList}from"./sky-list/sky-list.js";export{SkyListitem}from"./sky-listitem/sky-listitem.js";export{SkyRadio}from"./sky-radio/sky-radio.js";export{SkyRow}from"./sky-row/sky-row.js";export{SkySheet,resolveSheetRadius}from"./sky-sheet/sky-sheet.js";export{SkySimpleTable}from"./sky-simple-table/sky-simple-table.js";export{SkyThemeProvider,defaultTheme,getCurrentTheme,getThemePreference,mergeTheme,onThemeChange,resolveActualTheme,themeContext}from"./sky-theme-provider/sky-theme-provider.js";export{applyPresetLayer,camelToKebab,captureInitialUserAttributes,clearAppliedPresetLayer,configContext,findNearestPresetsConfig,getPresetLayer,isUserSetProp,lookupPresetSection,markUserSetProp,mergePresetsConfig,presetKeyAliases,refreshUserAttributes,resolveComponentProps,toPresetTagKey}from"./helper/utils/component-presets.js";export{extractIconNames,fetchIconsForOffline,registerOfflineIcons}from"./helper/iconify-offline.js";export{resolveRadius}from"./helper/utils/size-resolver.js";
2
2
  //# sourceMappingURL=index.js.map
@@ -14,7 +14,7 @@ export type SkyAlertRoleType = "alert" | "alertdialog";
14
14
  * @status stable
15
15
  * @since 1.0.0
16
16
  *
17
- * @documentation https://library.sky-ui.com/components/alert
17
+ * @documentation https://sky-ui.com/components/alert
18
18
  * @dependency sky-icon
19
19
  *
20
20
  * @slot - Custom message content (used when `message` is empty).
@@ -32,6 +32,7 @@ export type SkyAlertRoleType = "alert" | "alertdialog";
32
32
  * @property {SkyAlertVariant} variant - Visual style variant.
33
33
  * @property {boolean} loading - Shows a loading overlay.
34
34
  * @property {SkyAlertRoleType} roleType - ARIA role for the alert container.
35
+ * @property {string} preset - Named prop preset from nearest `sky-config-provider`. Default: `""`.
35
36
  * @method close Dispatches `alert-closed` and removes the alert from the DOM.
36
37
  *
37
38
  * @fires {CustomEvent<SkyAlertClosedEventDetail>} alert-closed - Fired when the alert is dismissed via the close button; bubbles and is composed.
@@ -108,14 +109,21 @@ export declare class SkyAlert extends LitElement {
108
109
  private _sizeCache;
109
110
  /** True when the actions slot has assigned content (used to show separator only when needed). */
110
111
  private _hasActionsSlotContent;
111
- static styles: import("lit").CSSResult;
112
+ /** Named prop preset from nearest `sky-config-provider`. */
113
+ preset: string;
114
+ private _presets;
115
+ static styles: import("lit").CSSResult[];
112
116
  /**
113
117
  * Resolves size to get padding, font sizes, and other metrics.
114
118
  * Result is memoized by `size` to avoid recomputing when only color/variant/radius change.
115
119
  */
116
120
  private _resolveSize;
117
- /** Recomputes style variables when visual inputs change. */
118
- willUpdate(changedProperties: PropertyValues): void;
121
+ /**
122
+ * Lit order: willUpdate → controllers hostUpdate (presets) → update/render.
123
+ * Rebuild CSS vars here so preset-applied color/variant are visible.
124
+ */
125
+ update(changedProperties: PropertyValues): void;
126
+ private _lastPresetRevision;
119
127
  /** Initializes actions-slot presence state after first render. */
120
128
  firstUpdated(): void;
121
129
  /** Computes CSS custom properties from current variant, size, and color inputs. */
@@ -1,4 +1,4 @@
1
- import{unsafeCSS as t,css as e,LitElement as r,html as i}from"lit";import{property as o,state as s,customElement as n}from"lit/decorators.js";import{styleMap as a}from"lit/directives/style-map.js";import{classMap as l}from"lit/directives/class-map.js";import{when as p}from"lit/directives/when.js";import{resolveRadius as d}from"../helper/utils/size-resolver.js";import{resolveColor as c,resolveTextColorForToken as h,resolveSemanticSurfaceKey as g,semanticSoftSurfaceTokens as y,tuneSurfaceVariantForDefaultColor as m,isDefaultColorToken as v,skyBorderPrimaryShorthand as b,hoverShade as x,fadeMix as f}from"../helper/utils/color-resolver.js";import{cssOnFillEnhance as u}from"../helper/utils/contrast-color.js";import{SkyIcon as k}from"../sky-icon/sky-icon.js";var z=Object.defineProperty,S=Object.getOwnPropertyDescriptor,C=(t,e,r,i)=>{for(var o,s=i>1?void 0:i?S(e,r):e,n=t.length-1;n>=0;n--)(o=t[n])&&(s=(i?o(e,r,s):o(s))||s);return i&&s&&z(e,r,s),s};let $=class extends r{constructor(){super(...arguments),this.title="",this.message="",this.removable=!1,this.color="primary",this.size="md",this.radius="md",this.icon=null,this.strip="none",this.stripColor="currentColor",this.variant="solid",this.loading=!1,this.roleType="alert",this._styleVars={},this._sizeCache=null,this._hasActionsSlotContent=!1}_resolveSize(t){const e=String(t).trim();if(this._sizeCache&&this._sizeCache.size===e)return this._sizeCache.result;const r={xs:{padding:"3px 7px",titleFontSize:"12px",messageFontSize:"11px",gap:"4px",icon:"14px",closeSize:"18px",closeFontSize:"12px",spinner:"12px",stripWidth:"2px",minHeight:"28px"},sm:{padding:"5px 9px",titleFontSize:"14px",messageFontSize:"13px",gap:"6px",icon:"16px",closeSize:"20px",closeFontSize:"14px",spinner:"14px",stripWidth:"3px",minHeight:"32px"},md:{padding:"8px 12px",titleFontSize:"16px",messageFontSize:"14px",gap:"8px",icon:"20px",closeSize:"24px",closeFontSize:"16px",spinner:"16px",stripWidth:"4px",minHeight:"36px"},lg:{padding:"10px 14px",titleFontSize:"18px",messageFontSize:"15px",gap:"10px",icon:"22px",closeSize:"28px",closeFontSize:"18px",spinner:"18px",stripWidth:"5px",minHeight:"40px"},xl:{padding:"12px 16px",titleFontSize:"20px",messageFontSize:"16px",gap:"12px",icon:"24px",closeSize:"32px",closeFontSize:"20px",spinner:"20px",stripWidth:"6px",minHeight:"44px"}};if(r[t])return this._sizeCache={size:e,result:r[t]},r[t];const i=String(t).trim().match(/^([\d.]+)(px|rem|em)?$/i),o=i?.[2]||"px",s=i?parseFloat(i[1]):16,n=t=>`${Math.round(100*t)/100}${o}`,a=(t,e,r)=>Math.max(e,Math.min(r,t)),l=`${s}${o}`,p=a(.875*s,11,16),d=a(.5*s,3,12),c=a(.75*s,7,16),h=a(.5*s,4,12),g=a(1.25*s,14,24),y=a(1.5*s,18,32),m=a(1*s,12,20),v=a(1*s,12,20),b=a(.25*s,2,6),x=a(2.25*s,28,44);return{padding:`${n(d)} ${n(c)}`,titleFontSize:l,messageFontSize:n(p),gap:n(h),icon:n(g),closeSize:n(y),closeFontSize:n(m),spinner:n(v),stripWidth:n(b),minHeight:n(x)}}willUpdate(t){super.willUpdate(t),(t.has("color")||t.has("variant")||t.has("stripColor")||t.has("radius")||t.has("size"))&&this._updateStyleVars()}firstUpdated(){queueMicrotask(()=>this._checkActionsSlot())}_updateStyleVars(){const t=c(this.color),e=h(this.color),r="currentColor"===this.stripColor?t:c(this.stripColor),i=this._resolveSize(this.size),o=g(this.color),s={solid:{bg:t,color:e,border:"none"},flat:o?y(o):{bg:f(t,20),color:x(t,30),border:"none"},faded:o?y(o,{bordered:!0}):{bg:"var(--sky-hover-tertiary)",color:t,border:"1px solid var(--sky-text-tertiary)"},bordered:{bg:"transparent",color:o?`var(--sky-${o}-primary-dark)`:t,border:`2px solid ${t}`},light:{bg:"transparent",color:o?`var(--sky-${o}-primary-dark)`:t,border:"none"}},n=this.variant in s?this.variant:"flat";let a=m(this.color,n,s[n]);!v(this.color)||"flat"!==n&&"faded"!==n||(a={...a,bg:"var(--sky-glass-solid)",color:"var(--sky-text-primary)",border:"faded"===n?b():"none"});let l="var(--sky-hover-primary)",p="currentColor",u="var(--sky-hover-secondary)",k="currentColor";"solid"===n?(l=f(e,20),p=e,u=f(e,30),k=e):"flat"!==n&&"faded"!==n||(o?(l=`var(--sky-${o}-g0)`,p=a.color,u=`var(--sky-${o}-g1)`,k=a.color):v(this.color)?(l="var(--sky-hover-primary)",p=a.color,u="var(--sky-hover-secondary)",k=a.color):(l=f(t,15),p=a.color,u=f(t,25),k=a.color)),this._styleVars={"--alert-bg":a.bg,"--alert-color":a.color,"--alert-border":a.border,"--alert-radius":d(this.radius),"--alert-padding":i.padding,"--alert-gap":i.gap,"--alert-min-height":i.minHeight,"--title-font-size":i.titleFontSize,"--message-font-size":i.messageFontSize,"--icon-size":i.icon,"--close-size":i.closeSize,"--close-font-size":i.closeFontSize,"--spinner-size":i.spinner,"--strip-color":r,"--strip-width":i.stripWidth,"--close-bg":l,"--close-color":p,"--close-hover-bg":u,"--close-hover-color":k}}close(){const t=new CustomEvent("alert-closed",{detail:{title:this.title,message:this.message},bubbles:!0,composed:!0});this.dispatchEvent(t),this.remove()}getAriaRole(){return this.roleType}_checkActionsSlot(){const t=this.renderRoot?.querySelector('slot[name="actions"]');if(!t)return;const e=t.assignedNodes({flatten:!0}).some(t=>t.nodeType!==Node.TEXT_NODE||(t.textContent?.trim().length??0)>0);e!==this._hasActionsSlotContent&&(this._hasActionsSlotContent=e)}_onActionsSlotChange(t){const e=t.target.assignedNodes({flatten:!0}).some(t=>t.nodeType!==Node.TEXT_NODE||(t.textContent?.trim().length??0)>0);this._hasActionsSlotContent=e}render(){const t=this.getAriaRole(),e=l({alert:!0,[this.variant]:!0,"strip-start":"start"===this.strip||"both"===this.strip,"strip-end":"end"===this.strip||"both"===this.strip});return i`
1
+ import{unsafeCSS as t,css as e,LitElement as r,html as i}from"lit";import{property as o,state as s,customElement as n}from"lit/decorators.js";import{styleMap as a}from"lit/directives/style-map.js";import{classMap as l}from"lit/directives/class-map.js";import{when as p}from"lit/directives/when.js";import{resolveRadius as d}from"../helper/utils/size-resolver.js";import{resolveColor as c,resolveSemanticSurfaceKey as h,semanticSoftSurfaceTokens as g,tuneSurfaceVariantForDefaultColor as y,isDefaultColorToken as m,skyBorderPrimaryShorthand as v,hoverShade as b,fadeMix as x}from"../helper/utils/color-resolver.js";import{cssOnFillEnhance as f,ON_COLOR_FALLBACK_LIGHT as u}from"../helper/utils/contrast-color.js";import{SkyIcon as k}from"../sky-icon/sky-icon.js";import{PresetController as z}from"../helper/controllers/preset-controller.js";import{skyFocusRingHostStyles as S}from"../helper/styles/focus-ring.js";var C=Object.defineProperty,_=Object.getOwnPropertyDescriptor,$=(t,e,r,i)=>{for(var o,s=i>1?void 0:i?_(e,r):e,n=t.length-1;n>=0;n--)(o=t[n])&&(s=(i?o(e,r,s):o(s))||s);return i&&s&&C(e,r,s),s};let F=class extends r{constructor(){super(...arguments),this.title="",this.message="",this.removable=!1,this.color="primary",this.size="md",this.radius="md",this.icon=null,this.strip="none",this.stripColor="currentColor",this.variant="solid",this.loading=!1,this.roleType="alert",this._styleVars={},this._sizeCache=null,this._hasActionsSlotContent=!1,this.preset="",this._presets=new z(this),this._lastPresetRevision=-1}_resolveSize(t){const e=String(t).trim();if(this._sizeCache&&this._sizeCache.size===e)return this._sizeCache.result;const r={xs:{padding:"3px 7px",titleFontSize:"12px",messageFontSize:"11px",gap:"4px",icon:"14px",closeSize:"18px",closeFontSize:"12px",spinner:"12px",stripWidth:"2px",minHeight:"28px"},sm:{padding:"5px 9px",titleFontSize:"14px",messageFontSize:"13px",gap:"6px",icon:"16px",closeSize:"20px",closeFontSize:"14px",spinner:"14px",stripWidth:"3px",minHeight:"32px"},md:{padding:"8px 12px",titleFontSize:"16px",messageFontSize:"14px",gap:"8px",icon:"20px",closeSize:"24px",closeFontSize:"16px",spinner:"16px",stripWidth:"4px",minHeight:"36px"},lg:{padding:"10px 14px",titleFontSize:"18px",messageFontSize:"15px",gap:"10px",icon:"22px",closeSize:"28px",closeFontSize:"18px",spinner:"18px",stripWidth:"5px",minHeight:"40px"},xl:{padding:"12px 16px",titleFontSize:"20px",messageFontSize:"16px",gap:"12px",icon:"24px",closeSize:"32px",closeFontSize:"20px",spinner:"20px",stripWidth:"6px",minHeight:"44px"}};if(r[t])return this._sizeCache={size:e,result:r[t]},r[t];const i=String(t).trim().match(/^([\d.]+)(px|rem|em)?$/i),o=i?.[2]||"px",s=i?parseFloat(i[1]):16,n=t=>`${Math.round(100*t)/100}${o}`,a=(t,e,r)=>Math.max(e,Math.min(r,t)),l=`${s}${o}`,p=a(.875*s,11,16),d=a(.5*s,3,12),c=a(.75*s,7,16),h=a(.5*s,4,12),g=a(1.25*s,14,24),y=a(1.5*s,18,32),m=a(1*s,12,20),v=a(1*s,12,20),b=a(.25*s,2,6),x=a(2.25*s,28,44);return{padding:`${n(d)} ${n(c)}`,titleFontSize:l,messageFontSize:n(p),gap:n(h),icon:n(g),closeSize:n(y),closeFontSize:n(m),spinner:n(v),stripWidth:n(b),minHeight:n(x)}}update(t){(t.has("color")||t.has("variant")||t.has("stripColor")||t.has("radius")||t.has("size")||t.has("preset")||this._presets.revision!==this._lastPresetRevision)&&(this._lastPresetRevision=this._presets.revision,this._updateStyleVars()),super.update(t)}firstUpdated(){queueMicrotask(()=>this._checkActionsSlot())}_updateStyleVars(){const t=c(this.color),e=u,r="currentColor"===this.stripColor?t:c(this.stripColor),i=this._resolveSize(this.size),o=h(this.color),s={solid:{bg:t,color:e,border:"none"},flat:o?g(o):{bg:x(t,20),color:b(t,30),border:"none"},faded:o?g(o,{bordered:!0}):{bg:"var(--sky-hover-tertiary)",color:t,border:"1px solid var(--sky-text-tertiary)"},bordered:{bg:"transparent",color:o?`var(--sky-${o}-primary-dark)`:t,border:`2px solid ${t}`},light:{bg:"transparent",color:o?`var(--sky-${o}-primary-dark)`:t,border:"none"}},n=this.variant in s?this.variant:"flat";let a=y(this.color,n,s[n]);!m(this.color)||"flat"!==n&&"faded"!==n||(a={...a,bg:"var(--sky-glass-solid)",color:"var(--sky-text-primary)",border:"faded"===n?v():"none"});let l="var(--sky-hover-primary)",p="currentColor",f="var(--sky-hover-secondary)",k="currentColor";"solid"===n?(l=x(e,20),p=e,f=x(e,30),k=e):"flat"!==n&&"faded"!==n||(o?(l=`var(--sky-${o}-g0)`,p=a.color,f=`var(--sky-${o}-g1)`,k=a.color):m(this.color)?(l="var(--sky-hover-primary)",p=a.color,f="var(--sky-hover-secondary)",k=a.color):(l=x(t,15),p=a.color,f=x(t,25),k=a.color)),this._styleVars={"--alert-bg":a.bg,"--alert-color":a.color,"--alert-border":a.border,"--alert-radius":d(this.radius),"--alert-padding":i.padding,"--alert-gap":i.gap,"--alert-min-height":i.minHeight,"--title-font-size":i.titleFontSize,"--message-font-size":i.messageFontSize,"--icon-size":i.icon,"--close-size":i.closeSize,"--close-font-size":i.closeFontSize,"--spinner-size":i.spinner,"--strip-color":r,"--strip-width":i.stripWidth,"--close-bg":l,"--close-color":p,"--close-hover-bg":f,"--close-hover-color":k,"--sky-focus-ring-color":t}}close(){const t=new CustomEvent("alert-closed",{detail:{title:this.title,message:this.message},bubbles:!0,composed:!0});this.dispatchEvent(t),this.remove()}getAriaRole(){return this.roleType}_checkActionsSlot(){const t=this.renderRoot?.querySelector('slot[name="actions"]');if(!t)return;const e=t.assignedNodes({flatten:!0}).some(t=>t.nodeType!==Node.TEXT_NODE||(t.textContent?.trim().length??0)>0);e!==this._hasActionsSlotContent&&(this._hasActionsSlotContent=e)}_onActionsSlotChange(t){const e=t.target.assignedNodes({flatten:!0}).some(t=>t.nodeType!==Node.TEXT_NODE||(t.textContent?.trim().length??0)>0);this._hasActionsSlotContent=e}render(){const t=this.getAriaRole(),e=l({alert:!0,[this.variant]:!0,"strip-start":"start"===this.strip||"both"===this.strip,"strip-end":"end"===this.strip||"both"===this.strip});return i`
2
2
  <div
3
3
  part="alert"
4
4
  class=${e}
@@ -41,7 +41,7 @@ import{unsafeCSS as t,css as e,LitElement as r,html as i}from"lit";import{proper
41
41
  </div>
42
42
  `)}
43
43
  </div>
44
- `}};$.dependencies={"sky-icon":k},$.styles=e`
44
+ `}};F.dependencies={"sky-icon":k},F.styles=[S,e`
45
45
  :host {
46
46
  display: block;
47
47
  font-family: var(--sky-font);
@@ -279,6 +279,6 @@ import{unsafeCSS as t,css as e,LitElement as r,html as i}from"lit";import{proper
279
279
  }
280
280
  }
281
281
 
282
- ${t(u([{selector:".alert.solid",fillVar:"--alert-bg"}]))}
283
- `,C([o({type:String})],$.prototype,"title",2),C([o({type:String})],$.prototype,"message",2),C([o({type:Boolean})],$.prototype,"removable",2),C([o({type:String})],$.prototype,"color",2),C([o({type:String})],$.prototype,"size",2),C([o({type:String})],$.prototype,"radius",2),C([o({type:String})],$.prototype,"icon",2),C([o({type:String,reflect:!0})],$.prototype,"strip",2),C([o({type:String})],$.prototype,"stripColor",2),C([o({type:String,reflect:!0})],$.prototype,"variant",2),C([o({type:Boolean})],$.prototype,"loading",2),C([o({type:String,reflect:!0})],$.prototype,"roleType",2),C([s()],$.prototype,"_hasActionsSlotContent",2),$=C([n("sky-alert")],$);export{$ as SkyAlert};
282
+ ${t(f([{selector:".alert.solid",fillVar:"--alert-bg"}]))}
283
+ `],$([o({type:String})],F.prototype,"title",2),$([o({type:String})],F.prototype,"message",2),$([o({type:Boolean})],F.prototype,"removable",2),$([o({type:String})],F.prototype,"color",2),$([o({type:String})],F.prototype,"size",2),$([o({type:String})],F.prototype,"radius",2),$([o({type:String})],F.prototype,"icon",2),$([o({type:String,reflect:!0})],F.prototype,"strip",2),$([o({type:String})],F.prototype,"stripColor",2),$([o({type:String,reflect:!0})],F.prototype,"variant",2),$([o({type:Boolean})],F.prototype,"loading",2),$([o({type:String,reflect:!0})],F.prototype,"roleType",2),$([s()],F.prototype,"_hasActionsSlotContent",2),$([o({type:String,reflect:!0})],F.prototype,"preset",2),F=$([n("sky-alert")],F);export{F as SkyAlert};
284
284
  //# sourceMappingURL=sky-alert.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sky-alert.js","sources":["../../src/sky-alert/sky-alert.ts"],"sourcesContent":["import { LitElement, html, css, PropertyValues, unsafeCSS } from \"lit\";\r\nimport { customElement, property, state } from \"lit/decorators.js\";\r\nimport { styleMap } from \"lit/directives/style-map.js\";\r\nimport { classMap } from \"lit/directives/class-map.js\";\r\nimport { when } from \"lit/directives/when.js\";\r\nimport { resolveRadius } from \"../helper/utils/size-resolver\";\r\nimport {\r\n resolveColor,\r\n resolveTextColorForToken,\r\n fadeMix,\r\n hoverShade,\r\n isDefaultColorToken,\r\n tuneSurfaceVariantForDefaultColor,\r\n resolveSemanticSurfaceKey,\r\n semanticSoftSurfaceTokens,\r\n skyBorderPrimaryShorthand,\r\n} from \"../helper/utils/color-resolver\";\r\nimport { cssOnFillEnhance } from \"../helper/utils/contrast-color\";\r\nimport { SkyIcon } from \"../sky-icon/sky-icon.js\";\r\n\r\nexport type SkyAlertClosedEventDetail = { title: string; message: string };\r\nexport type SkyAlertStrip = \"start\" | \"end\" | \"both\" | \"none\";\r\nexport type SkyAlertVariant = \"flat\" | \"bordered\" | \"light\" | \"faded\" | \"solid\";\r\nexport type SkyAlertRoleType = \"alert\" | \"alertdialog\";\r\n/** Resolved size metrics returned by `SkyAlert._resolveSize()`. */\r\ntype SkyAlertResolvedSize = {\r\n padding: string;\r\n titleFontSize: string;\r\n messageFontSize: string;\r\n gap: string;\r\n icon: string;\r\n closeSize: string;\r\n closeFontSize: string;\r\n spinner: string;\r\n stripWidth: string;\r\n minHeight: string;\r\n};\r\n\r\n/**\r\n * @element sky-alert\r\n *\r\n * @summary Status alert banner with variants, optional icon, strip accents, actions, dismiss behavior, and loading state.\r\n *\r\n * @status stable\r\n * @since 1.0.0\r\n *\r\n * @documentation https://library.sky-ui.com/components/alert\r\n * @dependency sky-icon\r\n *\r\n * @slot - Custom message content (used when `message` is empty).\r\n * @slot actions - Action buttons or links displayed on the trailing side.\r\n *\r\n * @property {string} title - Title text shown above the message.\r\n * @property {string} message - Message text rendered inside the alert.\r\n * @property {boolean} removable - Shows a dismiss button when enabled.\r\n * @property {string} color - Base color token or CSS color used by the alert.\r\n * @property {string} size - Preset size token (`xs | sm | md | lg | xl`) or CSS length.\r\n * @property {string} radius - Radius token or CSS length.\r\n * @property {string | null} icon - Optional leading icon name for `<sky-icon>`.\r\n * @property {SkyAlertStrip} strip - Strip accent placement.\r\n * @property {string} stripColor - Strip accent color token or CSS color.\r\n * @property {SkyAlertVariant} variant - Visual style variant.\r\n * @property {boolean} loading - Shows a loading overlay.\r\n * @property {SkyAlertRoleType} roleType - ARIA role for the alert container.\r\n * @method close Dispatches `alert-closed` and removes the alert from the DOM.\r\n *\r\n * @fires {CustomEvent<SkyAlertClosedEventDetail>} alert-closed - Fired when the alert is dismissed via the close button; bubbles and is composed.\r\n *\r\n * @csspart alert - The outer alert container.\r\n * @csspart icon - The optional leading icon.\r\n * @csspart content - The content container (title + message/slot).\r\n * @csspart title - The title text element.\r\n * @csspart message - The message text element (when `message` is provided).\r\n * @csspart actions - The trailing actions container.\r\n * @csspart close-button - The dismiss button (when `removable`).\r\n * @csspart loading-overlay - Overlay shown when `loading` is true.\r\n * @csspart loading-spinner - Spinner element shown inside the loading overlay.\r\n *\r\n * @Behavior\r\n * - `message` content takes priority over default-slot message content.\r\n * - Dismissing a removable alert dispatches `alert-closed` and removes the element.\r\n * - `strip` controls accent placement (`start`, `end`, `both`, `none`).\r\n * - `role-type=\"alert\"` maps to `aria-live=\"assertive\"`; `alertdialog` maps to `aria-live=\"polite\"`.\r\n * - Respects reduced motion preferences for entry, button hover rotation, and spinner animation.\r\n *\r\n * @example\r\n * ```html\r\n * <sky-alert title=\"Upload Complete\" message=\"Your file is now available.\" variant=\"bordered\" strip=\"start\" removable>\r\n * <button slot=\"actions\">View</button>\r\n * </sky-alert>\r\n * ```\r\n * ```vue\r\n * <template>\r\n * <sky-alert title=\"Upload Complete\" message=\"Your file is now available.\" variant=\"bordered\" strip=\"start\" removable>\r\n * <button slot=\"actions\">View</button>\r\n * </sky-alert>\r\n * </template>\r\n * ```\r\n * ```jsx\r\n * export default function Demo() {\r\n * return (\r\n * <sky-alert title=\"Upload Complete\" message=\"Your file is now available.\" variant=\"bordered\" strip=\"start\" removable>\r\n * <button slot=\"actions\">View</button>\r\n * </sky-alert>\r\n * );\r\n * }\r\n * ```\r\n */\r\n\r\n@customElement(\"sky-alert\")\r\nexport class SkyAlert extends LitElement {\r\n\r\n static dependencies: Record<string, CustomElementConstructor> = {\r\n \"sky-icon\": SkyIcon,\r\n };\r\n\r\n /** Title text displayed above the message. @default \"\" */\r\n @property({ type: String }) title: string = \"\";\r\n\r\n /** Message text displayed inside the alert. @default \"\" */\r\n @property({ type: String }) message: string = \"\";\r\n\r\n /** Shows a close button that dismisses the alert. @default false */\r\n @property({ type: Boolean }) removable: boolean = false;\r\n\r\n /** Base color token or CSS color. @default \"primary\" */\r\n @property({ type: String }) color: string = \"primary\";\r\n\r\n /** Size token (`xs | sm | md | lg | xl`) or CSS length. @default \"md\" */\r\n @property({ type: String }) size: string = \"md\";\r\n\r\n /** Radius token or CSS length. @default \"md\" */\r\n @property({ type: String }) radius: string = \"md\";\r\n\r\n /** Optional leading icon name for `<sky-icon>`. @default null */\r\n @property({ type: String }) icon: string | null = null;\r\n\r\n /** Strip accent position. @default \"none\" */\r\n @property({ type: String, reflect: true }) strip: SkyAlertStrip = \"none\";\r\n\r\n /** Strip accent color. @default \"currentColor\" */\r\n @property({ type: String })\r\n stripColor: string = \"currentColor\";\r\n\r\n /** Visual style variant. @default \"solid\" */\r\n @property({ type: String, reflect: true })\r\n variant: SkyAlertVariant = \"solid\";\r\n\r\n /** Shows a loading overlay. @default false */\r\n @property({ type: Boolean }) loading: boolean = false;\r\n\r\n /** ARIA role applied to the alert container. @default \"alert\" */\r\n @property({ type: String, reflect: true })\r\n roleType: SkyAlertRoleType = \"alert\";\r\n\r\n /** Internal style variables */\r\n private _styleVars: Record<string, string> = {};\r\n\r\n /** Cached result of _resolveSize for the last `size` value (avoids recomputing when only color/variant change). */\r\n private _sizeCache: { size: string; result: SkyAlertResolvedSize } | null = null;\r\n\r\n /** True when the actions slot has assigned content (used to show separator only when needed). */\r\n @state() private _hasActionsSlotContent = false;\r\n\r\n static override styles = css`\r\n :host {\r\n display: block;\r\n font-family: var(--sky-font);\r\n width: 100%;\r\n }\r\n\r\n .alert {\r\n position: relative;\r\n width: 100%;\r\n box-sizing: border-box;\r\n display: flex;\r\n align-items: stretch;\r\n gap: var(--alert-gap, var(--sky-space-2, 8px));\r\n padding: var(--alert-padding);\r\n border-radius: var(--alert-radius);\r\n border: var(--alert-border, none);\r\n color: var(--alert-color, var(--sky-text-primary));\r\n background-color: var(--alert-bg, transparent);\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n transition: var(--sky-transition-default);\r\n min-height: var(--alert-min-height, 36px);\r\n animation: skyc-fade-in var(--sky-duration-fast, 120ms) var(--sky-ease-out, ease-out);\r\n }\r\n\r\n /* Strip styles (logical properties for RTL) */\r\n .alert.strip-start::before,\r\n .alert.strip-end::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n width: var(--strip-width, 4px);\r\n background: var(--strip-color, currentColor);\r\n z-index: 1;\r\n }\r\n\r\n .alert.strip-start::before {\r\n inset-inline-start: 0;\r\n border-start-start-radius: inherit;\r\n border-end-start-radius: inherit;\r\n }\r\n\r\n .alert.strip-end::after {\r\n inset-inline-end: 0;\r\n border-start-end-radius: inherit;\r\n border-end-end-radius: inherit;\r\n }\r\n\r\n .alert.strip-start {\r\n border-start-start-radius: 0 !important;\r\n border-end-start-radius: 0 !important;\r\n }\r\n .alert.strip-end {\r\n border-start-end-radius: 0 !important;\r\n border-end-end-radius: 0 !important;\r\n }\r\n\r\n .alert.strip-start.strip-end {\r\n border-radius: 0 !important;\r\n }\r\n\r\n /* Remove borders on strip sides */\r\n .alert.strip-start.bordered {\r\n border-inline-start: none !important;\r\n }\r\n .alert.strip-end.bordered {\r\n border-inline-end: none !important;\r\n }\r\n .alert.strip-start.strip-end.bordered {\r\n border-inline-start: none !important;\r\n border-inline-end: none !important;\r\n }\r\n\r\n .alert.faded.strip-start {\r\n border-inline-start: none !important;\r\n }\r\n .alert.faded.strip-end {\r\n border-inline-end: none !important;\r\n }\r\n .alert.faded.strip-start.strip-end {\r\n border-inline-start: none !important;\r\n border-inline-end: none !important;\r\n }\r\n\r\n .icon {\r\n align-self: flex-start;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: var(--icon-size, 20px);\r\n color: inherit;\r\n flex-shrink: 0;\r\n padding-block-start: 2px;\r\n }\r\n\r\n .content {\r\n flex: 1 1 auto;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n }\r\n\r\n .title {\r\n font: var(--sky-text-title);\r\n font-size: var(--title-font-size);\r\n color: inherit;\r\n margin: 0 0 var(--sky-space-1, 4px) 0;\r\n }\r\n\r\n .message {\r\n margin: 0;\r\n text-align: start;\r\n font: var(--sky-text-body);\r\n font-size: var(--message-font-size);\r\n color: inherit;\r\n }\r\n\r\n ::slotted(*) {\r\n font: var(--sky-text-body);\r\n font-size: var(--message-font-size);\r\n }\r\n\r\n .actions {\r\n display: inline-flex;\r\n gap: var(--sky-space-2, 8px);\r\n align-items: center;\r\n justify-content: flex-end;\r\n flex: 0 0 auto;\r\n align-self: stretch;\r\n border-inline-start: 1px solid var(--sky-border-light);\r\n padding-inline-start: var(--sky-space-2, 8px);\r\n margin-inline-start: var(--sky-space-1, 4px);\r\n }\r\n\r\n .actions-slot-placeholder {\r\n position: absolute;\r\n width: 0;\r\n height: 0;\r\n overflow: hidden;\r\n opacity: 0;\r\n pointer-events: none;\r\n }\r\n\r\n .close-button {\r\n margin-inline-start: var(--sky-space-1\\\\.5, 6px);\r\n display: inline-flex;\r\n aspect-ratio: 1 / 1;\r\n justify-content: center;\r\n align-items: center;\r\n width: var(--close-size, 24px);\r\n height: var(--close-size, 24px);\r\n box-sizing: border-box;\r\n background: var(--close-bg, var(--sky-hover-primary));\r\n border: none;\r\n border-radius: var(--sky-radius-full, 50%);\r\n font-size: var(--close-font-size, 16px);\r\n cursor: pointer;\r\n font-weight: var(--sky-font-weight-bold, 700);\r\n color: var(--close-color, currentColor);\r\n transition: var(--sky-transition-fast);\r\n -webkit-tap-highlight-color: transparent;\r\n }\r\n\r\n .close-button:hover {\r\n transform: rotate(90deg);\r\n background: var(--close-hover-bg, var(--sky-hover-secondary));\r\n color: var(--close-hover-color, currentColor);\r\n }\r\n\r\n .close-button:focus-visible {\r\n outline: none;\r\n box-shadow: var(--sky-focus-ring);\r\n background: var(--close-hover-bg, var(--sky-hover-secondary));\r\n color: var(--close-hover-color, currentColor);\r\n }\r\n\r\n .loading-overlay {\r\n position: absolute;\r\n inset: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: var(--sky-overlay-secondary);\r\n border-radius: inherit;\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n z-index: 2;\r\n }\r\n\r\n .loading-spinner {\r\n width: var(--spinner-size, 16px);\r\n height: var(--spinner-size, 16px);\r\n border: 2px solid currentColor;\r\n border-top-color: transparent;\r\n border-radius: var(--sky-radius-full, 50%);\r\n animation: skyc-spin 0.8s linear infinite;\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .alert {\r\n animation: none;\r\n transition: none;\r\n }\r\n\r\n .close-button {\r\n transition: none;\r\n }\r\n\r\n .close-button:hover,\r\n .close-button:focus-visible {\r\n transform: none;\r\n }\r\n\r\n .loading-spinner {\r\n animation: none;\r\n }\r\n }\r\n\r\n @keyframes skyc-spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n }\r\n\r\n @keyframes skyc-fade-in {\r\n from {\r\n opacity: 0;\r\n transform: translateY(-2px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n ${unsafeCSS(\r\n cssOnFillEnhance([\r\n {\r\n selector: \".alert.solid\",\r\n fillVar: \"--alert-bg\",\r\n },\r\n ]),\r\n )}\r\n `;\r\n\r\n /**\r\n * Resolves size to get padding, font sizes, and other metrics.\r\n * Result is memoized by `size` to avoid recomputing when only color/variant/radius change.\r\n */\r\n private _resolveSize(input: string): SkyAlertResolvedSize {\r\n const key = String(input).trim();\r\n if (this._sizeCache && this._sizeCache.size === key) return this._sizeCache.result;\r\n\r\n const presets: Record<\r\n string,\r\n {\r\n padding: string;\r\n titleFontSize: string;\r\n messageFontSize: string;\r\n gap: string;\r\n icon: string;\r\n closeSize: string;\r\n closeFontSize: string;\r\n spinner: string;\r\n stripWidth: string;\r\n minHeight: string;\r\n }\r\n > = {\r\n xs: {\r\n padding: \"3px 7px\",\r\n titleFontSize: \"12px\",\r\n messageFontSize: \"11px\",\r\n gap: \"4px\",\r\n icon: \"14px\",\r\n closeSize: \"18px\",\r\n closeFontSize: \"12px\",\r\n spinner: \"12px\",\r\n stripWidth: \"2px\",\r\n minHeight: \"28px\",\r\n },\r\n sm: {\r\n padding: \"5px 9px\",\r\n titleFontSize: \"14px\",\r\n messageFontSize: \"13px\",\r\n gap: \"6px\",\r\n icon: \"16px\",\r\n closeSize: \"20px\",\r\n closeFontSize: \"14px\",\r\n spinner: \"14px\",\r\n stripWidth: \"3px\",\r\n minHeight: \"32px\",\r\n },\r\n md: {\r\n padding: \"8px 12px\",\r\n titleFontSize: \"16px\",\r\n messageFontSize: \"14px\",\r\n gap: \"8px\",\r\n icon: \"20px\",\r\n closeSize: \"24px\",\r\n closeFontSize: \"16px\",\r\n spinner: \"16px\",\r\n stripWidth: \"4px\",\r\n minHeight: \"36px\",\r\n },\r\n lg: {\r\n padding: \"10px 14px\",\r\n titleFontSize: \"18px\",\r\n messageFontSize: \"15px\",\r\n gap: \"10px\",\r\n icon: \"22px\",\r\n closeSize: \"28px\",\r\n closeFontSize: \"18px\",\r\n spinner: \"18px\",\r\n stripWidth: \"5px\",\r\n minHeight: \"40px\",\r\n },\r\n xl: {\r\n padding: \"12px 16px\",\r\n titleFontSize: \"20px\",\r\n messageFontSize: \"16px\",\r\n gap: \"12px\",\r\n icon: \"24px\",\r\n closeSize: \"32px\",\r\n closeFontSize: \"20px\",\r\n spinner: \"20px\",\r\n stripWidth: \"6px\",\r\n minHeight: \"44px\",\r\n },\r\n };\r\n\r\n if (presets[input]) {\r\n this._sizeCache = { size: key, result: presets[input] };\r\n return presets[input];\r\n }\r\n\r\n const m = String(input)\r\n .trim()\r\n .match(/^([\\d.]+)(px|rem|em)?$/i);\r\n const unit = m?.[2] || \"px\";\r\n const fsNum = m ? parseFloat(m[1]) : 16;\r\n const fs = `${fsNum}${unit}`;\r\n\r\n const to = (n: number) => `${Math.round(n * 100) / 100}${unit}`;\r\n const clamp = (n: number, min: number, max: number) =>\r\n Math.max(min, Math.min(max, n));\r\n\r\n const titleFs = fs;\r\n const messageFs = clamp(fsNum * 0.875, 11, 16);\r\n const py = clamp(fsNum * 0.5, 3, 12);\r\n const px = clamp(fsNum * 0.75, 7, 16);\r\n const gap = clamp(fsNum * 0.5, 4, 12);\r\n const icon = clamp(fsNum * 1.25, 14, 24);\r\n const closeSize = clamp(fsNum * 1.5, 18, 32);\r\n const closeFont = clamp(fsNum * 1, 12, 20);\r\n const spinner = clamp(fsNum * 1, 12, 20);\r\n const stripWidth = clamp(fsNum * 0.25, 2, 6);\r\n const minHeight = clamp(fsNum * 2.25, 28, 44);\r\n\r\n return {\r\n padding: `${to(py)} ${to(px)}`,\r\n titleFontSize: titleFs,\r\n messageFontSize: to(messageFs),\r\n gap: to(gap),\r\n icon: to(icon),\r\n closeSize: to(closeSize),\r\n closeFontSize: to(closeFont),\r\n spinner: to(spinner),\r\n stripWidth: to(stripWidth),\r\n minHeight: to(minHeight),\r\n };\r\n }\r\n\r\n /** Recomputes style variables when visual inputs change. */\r\n override willUpdate(changedProperties: PropertyValues): void {\r\n super.willUpdate(changedProperties);\r\n\r\n if (\r\n changedProperties.has(\"color\") ||\r\n changedProperties.has(\"variant\") ||\r\n changedProperties.has(\"stripColor\") ||\r\n changedProperties.has(\"radius\") ||\r\n changedProperties.has(\"size\")\r\n ) {\r\n this._updateStyleVars();\r\n }\r\n }\r\n\r\n /** Initializes actions-slot presence state after first render. */\r\n override firstUpdated(): void {\r\n queueMicrotask(() => this._checkActionsSlot());\r\n }\r\n\r\n /** Computes CSS custom properties from current variant, size, and color inputs. */\r\n private _updateStyleVars(): void {\r\n const baseColor = resolveColor(this.color);\r\n const textColor = resolveTextColorForToken(this.color);\r\n const stripColorResolved = this.stripColor === \"currentColor\"\r\n ? baseColor\r\n : resolveColor(this.stripColor);\r\n\r\n const s = this._resolveSize(this.size);\r\n\r\n const semanticKey = resolveSemanticSurfaceKey(this.color);\r\n\r\n const variantStyles = {\r\n solid: {\r\n bg: baseColor,\r\n color: textColor,\r\n border: \"none\",\r\n },\r\n flat: semanticKey\r\n ? semanticSoftSurfaceTokens(semanticKey)\r\n : {\r\n bg: fadeMix(baseColor, 20),\r\n color: hoverShade(baseColor, 30),\r\n border: \"none\",\r\n },\r\n faded: semanticKey\r\n ? semanticSoftSurfaceTokens(semanticKey, { bordered: true })\r\n : {\r\n bg: \"var(--sky-hover-tertiary)\",\r\n color: baseColor,\r\n border: \"1px solid var(--sky-text-tertiary)\",\r\n },\r\n bordered: {\r\n bg: \"transparent\",\r\n color: semanticKey\r\n ? `var(--sky-${semanticKey}-primary-dark)`\r\n : baseColor,\r\n border: `2px solid ${baseColor}`,\r\n },\r\n light: {\r\n bg: \"transparent\",\r\n color: semanticKey\r\n ? `var(--sky-${semanticKey}-primary-dark)`\r\n : baseColor,\r\n border: \"none\",\r\n },\r\n } as const;\r\n\r\n const currentVariant = this.variant in variantStyles\r\n ? this.variant as keyof typeof variantStyles\r\n : \"flat\";\r\n\r\n let v = tuneSurfaceVariantForDefaultColor(\r\n this.color,\r\n currentVariant,\r\n variantStyles[currentVariant],\r\n );\r\n\r\n if (\r\n isDefaultColorToken(this.color) &&\r\n (currentVariant === \"flat\" || currentVariant === \"faded\")\r\n ) {\r\n v = {\r\n ...v,\r\n bg: \"var(--sky-glass-solid)\",\r\n color: \"var(--sky-text-primary)\",\r\n border: currentVariant === \"faded\" ? skyBorderPrimaryShorthand() : \"none\",\r\n };\r\n }\r\n\r\n let closeBg = \"var(--sky-hover-primary)\";\r\n let closeColor = \"currentColor\";\r\n let closeHoverBg = \"var(--sky-hover-secondary)\";\r\n let closeHoverColor = \"currentColor\";\r\n\r\n if (currentVariant === \"solid\") {\r\n closeBg = fadeMix(textColor, 20);\r\n closeColor = textColor;\r\n closeHoverBg = fadeMix(textColor, 30);\r\n closeHoverColor = textColor;\r\n } else if (currentVariant === \"flat\" || currentVariant === \"faded\") {\r\n if (semanticKey) {\r\n closeBg = `var(--sky-${semanticKey}-g0)`;\r\n closeColor = v.color;\r\n closeHoverBg = `var(--sky-${semanticKey}-g1)`;\r\n closeHoverColor = v.color;\r\n } else if (isDefaultColorToken(this.color)) {\r\n closeBg = \"var(--sky-hover-primary)\";\r\n closeColor = v.color;\r\n closeHoverBg = \"var(--sky-hover-secondary)\";\r\n closeHoverColor = v.color;\r\n } else {\r\n closeBg = fadeMix(baseColor, 15);\r\n closeColor = v.color;\r\n closeHoverBg = fadeMix(baseColor, 25);\r\n closeHoverColor = v.color;\r\n }\r\n }\r\n\r\n this._styleVars = {\r\n \"--alert-bg\": v.bg,\r\n \"--alert-color\": v.color,\r\n \"--alert-border\": v.border,\r\n \"--alert-radius\": resolveRadius(this.radius),\r\n \"--alert-padding\": s.padding,\r\n \"--alert-gap\": s.gap,\r\n \"--alert-min-height\": s.minHeight,\r\n \"--title-font-size\": s.titleFontSize,\r\n \"--message-font-size\": s.messageFontSize,\r\n \"--icon-size\": s.icon,\r\n \"--close-size\": s.closeSize,\r\n \"--close-font-size\": s.closeFontSize,\r\n \"--spinner-size\": s.spinner,\r\n \"--strip-color\": stripColorResolved,\r\n \"--strip-width\": s.stripWidth,\r\n \"--close-bg\": closeBg,\r\n \"--close-color\": closeColor,\r\n \"--close-hover-bg\": closeHoverBg,\r\n \"--close-hover-color\": closeHoverColor,\r\n };\r\n }\r\n\r\n /**\r\n * Dispatches `alert-closed` and removes the alert from the DOM.\r\n *\r\n * @returns {void}\r\n */\r\n public close(): void {\r\n const evt = new CustomEvent<SkyAlertClosedEventDetail>(\"alert-closed\", {\r\n detail: { title: this.title, message: this.message },\r\n bubbles: true,\r\n composed: true,\r\n });\r\n this.dispatchEvent(evt);\r\n this.remove();\r\n }\r\n\r\n /** Returns the ARIA role applied to the alert container. */\r\n private getAriaRole(): SkyAlertRoleType {\r\n return this.roleType;\r\n }\r\n\r\n /** Checks whether the actions slot currently has meaningful assigned content. */\r\n private _checkActionsSlot(): void {\r\n const slot = this.renderRoot?.querySelector<HTMLSlotElement>('slot[name=\"actions\"]');\r\n if (!slot) return;\r\n const nodes = slot.assignedNodes({ flatten: true });\r\n const hasContent = nodes.some(\r\n (n) => n.nodeType !== Node.TEXT_NODE || (n.textContent?.trim().length ?? 0) > 0,\r\n );\r\n if (hasContent !== this._hasActionsSlotContent) {\r\n this._hasActionsSlotContent = hasContent;\r\n }\r\n }\r\n\r\n /** Updates action-slot state when the slot assignment changes. */\r\n private _onActionsSlotChange(e: Event): void {\r\n const slot = e.target as HTMLSlotElement;\r\n const nodes = slot.assignedNodes({ flatten: true });\r\n const hasContent = nodes.some(\r\n (n) => n.nodeType !== Node.TEXT_NODE || (n.textContent?.trim().length ?? 0) > 0,\r\n );\r\n this._hasActionsSlotContent = hasContent;\r\n }\r\n\r\n override render() {\r\n const roleAttr = this.getAriaRole();\r\n const alertClasses = classMap({\r\n alert: true,\r\n [this.variant]: true,\r\n \"strip-start\": this.strip === \"start\" || this.strip === \"both\",\r\n \"strip-end\": this.strip === \"end\" || this.strip === \"both\",\r\n });\r\n\r\n return html`\r\n <div\r\n part=\"alert\"\r\n class=${alertClasses}\r\n role=\"${roleAttr}\"\r\n aria-live=\"${this.roleType === \"alert\" ? \"assertive\" : \"polite\"}\"\r\n style=${styleMap(this._styleVars)}\r\n >\r\n ${when(\r\n this.icon,\r\n () => html`<sky-icon part=\"icon\" class=\"icon\" icon=\"${this.icon!}\"></sky-icon>`,\r\n )}\r\n\r\n <div part=\"content\" class=\"content\">\r\n ${when(\r\n this.title,\r\n () => html`<div part=\"title\" class=\"title\">${this.title}</div>`,\r\n )}\r\n ${when(\r\n this.message,\r\n () => html`<p part=\"message\" class=\"message\">${this.message}</p>`,\r\n () => html`<slot></slot>`,\r\n )}\r\n </div>\r\n\r\n ${when(\r\n this._hasActionsSlotContent || this.removable,\r\n () => html`\r\n <div part=\"actions\" class=\"actions\">\r\n <slot name=\"actions\" @slotchange=${this._onActionsSlotChange}></slot>\r\n ${when(\r\n this.removable,\r\n () => html`\r\n <button\r\n part=\"close-button\"\r\n class=\"close-button\"\r\n type=\"button\"\r\n @click=${this.close}\r\n aria-label=\"Dismiss alert\"\r\n title=\"Dismiss\"\r\n >\r\n <sky-icon icon=\"ion:close\"></sky-icon>\r\n </button>\r\n `,\r\n )}\r\n </div>\r\n `,\r\n () => html`\r\n <div class=\"actions-slot-placeholder\" aria-hidden=\"true\">\r\n <slot name=\"actions\" @slotchange=${this._onActionsSlotChange}></slot>\r\n </div>\r\n `,\r\n )}\r\n\r\n ${when(\r\n this.loading,\r\n () => html`\r\n <div part=\"loading-overlay\" class=\"loading-overlay\">\r\n <div part=\"loading-spinner\" class=\"loading-spinner\"></div>\r\n </div>\r\n `,\r\n )}\r\n </div>\r\n `;\r\n }\r\n}"],"names":["SkyAlert","LitElement","constructor","super","arguments","this","title","message","removable","color","size","radius","icon","strip","stripColor","variant","loading","roleType","_styleVars","_sizeCache","_hasActionsSlotContent","_resolveSize","input","key","String","trim","result","presets","xs","padding","titleFontSize","messageFontSize","gap","closeSize","closeFontSize","spinner","stripWidth","minHeight","sm","md","lg","xl","m","match","unit","fsNum","parseFloat","to","n","Math","round","clamp","min","max","titleFs","messageFs","py","px","closeFont","willUpdate","changedProperties","has","_updateStyleVars","firstUpdated","queueMicrotask","_checkActionsSlot","baseColor","resolveColor","textColor","resolveTextColorForToken","stripColorResolved","s","semanticKey","resolveSemanticSurfaceKey","variantStyles","solid","bg","border","flat","semanticSoftSurfaceTokens","fadeMix","hoverShade","faded","bordered","light","currentVariant","v","tuneSurfaceVariantForDefaultColor","isDefaultColorToken","skyBorderPrimaryShorthand","closeBg","closeColor","closeHoverBg","closeHoverColor","resolveRadius","close","evt","CustomEvent","detail","bubbles","composed","dispatchEvent","remove","getAriaRole","slot","renderRoot","querySelector","hasContent","assignedNodes","flatten","some","nodeType","Node","TEXT_NODE","textContent","length","_onActionsSlotChange","e","target","render","roleAttr","alertClasses","classMap","alert","html","styleMap","when","dependencies","SkyIcon","styles","css","unsafeCSS","cssOnFillEnhance","selector","fillVar","__decorateClass","property","type","prototype","Boolean","reflect","state","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"sky-alert.js","sources":["../../src/sky-alert/sky-alert.ts"],"sourcesContent":["import { LitElement, html, css, PropertyValues, unsafeCSS } from \"lit\";\r\nimport { customElement, property, state } from \"lit/decorators.js\";\r\nimport { styleMap } from \"lit/directives/style-map.js\";\r\nimport { classMap } from \"lit/directives/class-map.js\";\r\nimport { when } from \"lit/directives/when.js\";\r\nimport { resolveRadius } from \"../helper/utils/size-resolver\";\r\nimport {\r\n resolveColor,\r\n fadeMix,\r\n hoverShade,\r\n isDefaultColorToken,\r\n tuneSurfaceVariantForDefaultColor,\r\n resolveSemanticSurfaceKey,\r\n semanticSoftSurfaceTokens,\r\n skyBorderPrimaryShorthand,\r\n} from \"../helper/utils/color-resolver\";\r\nimport { cssOnFillEnhance, ON_COLOR_FALLBACK_LIGHT } from \"../helper/utils/contrast-color\";\r\nimport { SkyIcon } from \"../sky-icon/sky-icon.js\";\r\nimport { PresetController } from \"../helper/controllers/preset-controller\";\r\nimport { skyFocusRingHostStyles } from \"../helper/styles/focus-ring\";\r\n\r\nexport type SkyAlertClosedEventDetail = { title: string; message: string };\r\nexport type SkyAlertStrip = \"start\" | \"end\" | \"both\" | \"none\";\r\nexport type SkyAlertVariant = \"flat\" | \"bordered\" | \"light\" | \"faded\" | \"solid\";\r\nexport type SkyAlertRoleType = \"alert\" | \"alertdialog\";\r\n/** Resolved size metrics returned by `SkyAlert._resolveSize()`. */\r\ntype SkyAlertResolvedSize = {\r\n padding: string;\r\n titleFontSize: string;\r\n messageFontSize: string;\r\n gap: string;\r\n icon: string;\r\n closeSize: string;\r\n closeFontSize: string;\r\n spinner: string;\r\n stripWidth: string;\r\n minHeight: string;\r\n};\r\n\r\n/**\r\n * @element sky-alert\r\n *\r\n * @summary Status alert banner with variants, optional icon, strip accents, actions, dismiss behavior, and loading state.\r\n *\r\n * @status stable\r\n * @since 1.0.0\r\n *\r\n * @documentation https://sky-ui.com/components/alert\r\n * @dependency sky-icon\r\n *\r\n * @slot - Custom message content (used when `message` is empty).\r\n * @slot actions - Action buttons or links displayed on the trailing side.\r\n *\r\n * @property {string} title - Title text shown above the message.\r\n * @property {string} message - Message text rendered inside the alert.\r\n * @property {boolean} removable - Shows a dismiss button when enabled.\r\n * @property {string} color - Base color token or CSS color used by the alert.\r\n * @property {string} size - Preset size token (`xs | sm | md | lg | xl`) or CSS length.\r\n * @property {string} radius - Radius token or CSS length.\r\n * @property {string | null} icon - Optional leading icon name for `<sky-icon>`.\r\n * @property {SkyAlertStrip} strip - Strip accent placement.\r\n * @property {string} stripColor - Strip accent color token or CSS color.\r\n * @property {SkyAlertVariant} variant - Visual style variant.\r\n * @property {boolean} loading - Shows a loading overlay.\r\n * @property {SkyAlertRoleType} roleType - ARIA role for the alert container.\r\n * @property {string} preset - Named prop preset from nearest `sky-config-provider`. Default: `\"\"`.\r\n * @method close Dispatches `alert-closed` and removes the alert from the DOM.\r\n *\r\n * @fires {CustomEvent<SkyAlertClosedEventDetail>} alert-closed - Fired when the alert is dismissed via the close button; bubbles and is composed.\r\n *\r\n * @csspart alert - The outer alert container.\r\n * @csspart icon - The optional leading icon.\r\n * @csspart content - The content container (title + message/slot).\r\n * @csspart title - The title text element.\r\n * @csspart message - The message text element (when `message` is provided).\r\n * @csspart actions - The trailing actions container.\r\n * @csspart close-button - The dismiss button (when `removable`).\r\n * @csspart loading-overlay - Overlay shown when `loading` is true.\r\n * @csspart loading-spinner - Spinner element shown inside the loading overlay.\r\n *\r\n * @Behavior\r\n * - `message` content takes priority over default-slot message content.\r\n * - Dismissing a removable alert dispatches `alert-closed` and removes the element.\r\n * - `strip` controls accent placement (`start`, `end`, `both`, `none`).\r\n * - `role-type=\"alert\"` maps to `aria-live=\"assertive\"`; `alertdialog` maps to `aria-live=\"polite\"`.\r\n * - Respects reduced motion preferences for entry, button hover rotation, and spinner animation.\r\n *\r\n * @example\r\n * ```html\r\n * <sky-alert title=\"Upload Complete\" message=\"Your file is now available.\" variant=\"bordered\" strip=\"start\" removable>\r\n * <button slot=\"actions\">View</button>\r\n * </sky-alert>\r\n * ```\r\n * ```vue\r\n * <template>\r\n * <sky-alert title=\"Upload Complete\" message=\"Your file is now available.\" variant=\"bordered\" strip=\"start\" removable>\r\n * <button slot=\"actions\">View</button>\r\n * </sky-alert>\r\n * </template>\r\n * ```\r\n * ```jsx\r\n * export default function Demo() {\r\n * return (\r\n * <sky-alert title=\"Upload Complete\" message=\"Your file is now available.\" variant=\"bordered\" strip=\"start\" removable>\r\n * <button slot=\"actions\">View</button>\r\n * </sky-alert>\r\n * );\r\n * }\r\n * ```\r\n */\r\n\r\n@customElement(\"sky-alert\")\r\nexport class SkyAlert extends LitElement {\r\n\r\n static dependencies: Record<string, CustomElementConstructor> = {\r\n \"sky-icon\": SkyIcon,\r\n };\r\n\r\n /** Title text displayed above the message. @default \"\" */\r\n @property({ type: String }) title: string = \"\";\r\n\r\n /** Message text displayed inside the alert. @default \"\" */\r\n @property({ type: String }) message: string = \"\";\r\n\r\n /** Shows a close button that dismisses the alert. @default false */\r\n @property({ type: Boolean }) removable: boolean = false;\r\n\r\n /** Base color token or CSS color. @default \"primary\" */\r\n @property({ type: String }) color: string = \"primary\";\r\n\r\n /** Size token (`xs | sm | md | lg | xl`) or CSS length. @default \"md\" */\r\n @property({ type: String }) size: string = \"md\";\r\n\r\n /** Radius token or CSS length. @default \"md\" */\r\n @property({ type: String }) radius: string = \"md\";\r\n\r\n /** Optional leading icon name for `<sky-icon>`. @default null */\r\n @property({ type: String }) icon: string | null = null;\r\n\r\n /** Strip accent position. @default \"none\" */\r\n @property({ type: String, reflect: true }) strip: SkyAlertStrip = \"none\";\r\n\r\n /** Strip accent color. @default \"currentColor\" */\r\n @property({ type: String })\r\n stripColor: string = \"currentColor\";\r\n\r\n /** Visual style variant. @default \"solid\" */\r\n @property({ type: String, reflect: true })\r\n variant: SkyAlertVariant = \"solid\";\r\n\r\n /** Shows a loading overlay. @default false */\r\n @property({ type: Boolean }) loading: boolean = false;\r\n\r\n /** ARIA role applied to the alert container. @default \"alert\" */\r\n @property({ type: String, reflect: true })\r\n roleType: SkyAlertRoleType = \"alert\";\r\n\r\n /** Internal style variables */\r\n private _styleVars: Record<string, string> = {};\r\n\r\n /** Cached result of _resolveSize for the last `size` value (avoids recomputing when only color/variant change). */\r\n private _sizeCache: { size: string; result: SkyAlertResolvedSize } | null = null;\r\n\r\n /** True when the actions slot has assigned content (used to show separator only when needed). */\r\n @state() private _hasActionsSlotContent = false;\r\n\r\n\r\n /** Named prop preset from nearest `sky-config-provider`. */\r\n @property({ type: String, reflect: true }) preset = \"\";\r\n\r\n private _presets = new PresetController(this);\r\n\r\n static override styles = [\r\n skyFocusRingHostStyles,\r\n css`\r\n :host {\r\n display: block;\r\n font-family: var(--sky-font);\r\n width: 100%;\r\n }\r\n\r\n .alert {\r\n position: relative;\r\n width: 100%;\r\n box-sizing: border-box;\r\n display: flex;\r\n align-items: stretch;\r\n gap: var(--alert-gap, var(--sky-space-2, 8px));\r\n padding: var(--alert-padding);\r\n border-radius: var(--alert-radius);\r\n border: var(--alert-border, none);\r\n color: var(--alert-color, var(--sky-text-primary));\r\n background-color: var(--alert-bg, transparent);\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n transition: var(--sky-transition-default);\r\n min-height: var(--alert-min-height, 36px);\r\n animation: skyc-fade-in var(--sky-duration-fast, 120ms) var(--sky-ease-out, ease-out);\r\n }\r\n\r\n /* Strip styles (logical properties for RTL) */\r\n .alert.strip-start::before,\r\n .alert.strip-end::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n width: var(--strip-width, 4px);\r\n background: var(--strip-color, currentColor);\r\n z-index: 1;\r\n }\r\n\r\n .alert.strip-start::before {\r\n inset-inline-start: 0;\r\n border-start-start-radius: inherit;\r\n border-end-start-radius: inherit;\r\n }\r\n\r\n .alert.strip-end::after {\r\n inset-inline-end: 0;\r\n border-start-end-radius: inherit;\r\n border-end-end-radius: inherit;\r\n }\r\n\r\n .alert.strip-start {\r\n border-start-start-radius: 0 !important;\r\n border-end-start-radius: 0 !important;\r\n }\r\n .alert.strip-end {\r\n border-start-end-radius: 0 !important;\r\n border-end-end-radius: 0 !important;\r\n }\r\n\r\n .alert.strip-start.strip-end {\r\n border-radius: 0 !important;\r\n }\r\n\r\n /* Remove borders on strip sides */\r\n .alert.strip-start.bordered {\r\n border-inline-start: none !important;\r\n }\r\n .alert.strip-end.bordered {\r\n border-inline-end: none !important;\r\n }\r\n .alert.strip-start.strip-end.bordered {\r\n border-inline-start: none !important;\r\n border-inline-end: none !important;\r\n }\r\n\r\n .alert.faded.strip-start {\r\n border-inline-start: none !important;\r\n }\r\n .alert.faded.strip-end {\r\n border-inline-end: none !important;\r\n }\r\n .alert.faded.strip-start.strip-end {\r\n border-inline-start: none !important;\r\n border-inline-end: none !important;\r\n }\r\n\r\n .icon {\r\n align-self: flex-start;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: var(--icon-size, 20px);\r\n color: inherit;\r\n flex-shrink: 0;\r\n padding-block-start: 2px;\r\n }\r\n\r\n .content {\r\n flex: 1 1 auto;\r\n min-width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n }\r\n\r\n .title {\r\n font: var(--sky-text-title);\r\n font-size: var(--title-font-size);\r\n color: inherit;\r\n margin: 0 0 var(--sky-space-1, 4px) 0;\r\n }\r\n\r\n .message {\r\n margin: 0;\r\n text-align: start;\r\n font: var(--sky-text-body);\r\n font-size: var(--message-font-size);\r\n color: inherit;\r\n }\r\n\r\n ::slotted(*) {\r\n font: var(--sky-text-body);\r\n font-size: var(--message-font-size);\r\n }\r\n\r\n .actions {\r\n display: inline-flex;\r\n gap: var(--sky-space-2, 8px);\r\n align-items: center;\r\n justify-content: flex-end;\r\n flex: 0 0 auto;\r\n align-self: stretch;\r\n border-inline-start: 1px solid var(--sky-border-light);\r\n padding-inline-start: var(--sky-space-2, 8px);\r\n margin-inline-start: var(--sky-space-1, 4px);\r\n }\r\n\r\n .actions-slot-placeholder {\r\n position: absolute;\r\n width: 0;\r\n height: 0;\r\n overflow: hidden;\r\n opacity: 0;\r\n pointer-events: none;\r\n }\r\n\r\n .close-button {\r\n margin-inline-start: var(--sky-space-1\\\\.5, 6px);\r\n display: inline-flex;\r\n aspect-ratio: 1 / 1;\r\n justify-content: center;\r\n align-items: center;\r\n width: var(--close-size, 24px);\r\n height: var(--close-size, 24px);\r\n box-sizing: border-box;\r\n background: var(--close-bg, var(--sky-hover-primary));\r\n border: none;\r\n border-radius: var(--sky-radius-full, 50%);\r\n font-size: var(--close-font-size, 16px);\r\n cursor: pointer;\r\n font-weight: var(--sky-font-weight-bold, 700);\r\n color: var(--close-color, currentColor);\r\n transition: var(--sky-transition-fast);\r\n -webkit-tap-highlight-color: transparent;\r\n }\r\n\r\n .close-button:hover {\r\n transform: rotate(90deg);\r\n background: var(--close-hover-bg, var(--sky-hover-secondary));\r\n color: var(--close-hover-color, currentColor);\r\n }\r\n\r\n .close-button:focus-visible {\r\n outline: none;\r\n box-shadow: var(--sky-focus-ring);\r\n background: var(--close-hover-bg, var(--sky-hover-secondary));\r\n color: var(--close-hover-color, currentColor);\r\n }\r\n\r\n .loading-overlay {\r\n position: absolute;\r\n inset: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: var(--sky-overlay-secondary);\r\n border-radius: inherit;\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n z-index: 2;\r\n }\r\n\r\n .loading-spinner {\r\n width: var(--spinner-size, 16px);\r\n height: var(--spinner-size, 16px);\r\n border: 2px solid currentColor;\r\n border-top-color: transparent;\r\n border-radius: var(--sky-radius-full, 50%);\r\n animation: skyc-spin 0.8s linear infinite;\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .alert {\r\n animation: none;\r\n transition: none;\r\n }\r\n\r\n .close-button {\r\n transition: none;\r\n }\r\n\r\n .close-button:hover,\r\n .close-button:focus-visible {\r\n transform: none;\r\n }\r\n\r\n .loading-spinner {\r\n animation: none;\r\n }\r\n }\r\n\r\n @keyframes skyc-spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n }\r\n\r\n @keyframes skyc-fade-in {\r\n from {\r\n opacity: 0;\r\n transform: translateY(-2px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n ${unsafeCSS(\r\n cssOnFillEnhance([\r\n {\r\n selector: \".alert.solid\",\r\n fillVar: \"--alert-bg\",\r\n },\r\n ]),\r\n )}\r\n `,\r\n ];\r\n\r\n /**\r\n * Resolves size to get padding, font sizes, and other metrics.\r\n * Result is memoized by `size` to avoid recomputing when only color/variant/radius change.\r\n */\r\n private _resolveSize(input: string): SkyAlertResolvedSize {\r\n const key = String(input).trim();\r\n if (this._sizeCache && this._sizeCache.size === key) return this._sizeCache.result;\r\n\r\n const presets: Record<\r\n string,\r\n {\r\n padding: string;\r\n titleFontSize: string;\r\n messageFontSize: string;\r\n gap: string;\r\n icon: string;\r\n closeSize: string;\r\n closeFontSize: string;\r\n spinner: string;\r\n stripWidth: string;\r\n minHeight: string;\r\n }\r\n > = {\r\n xs: {\r\n padding: \"3px 7px\",\r\n titleFontSize: \"12px\",\r\n messageFontSize: \"11px\",\r\n gap: \"4px\",\r\n icon: \"14px\",\r\n closeSize: \"18px\",\r\n closeFontSize: \"12px\",\r\n spinner: \"12px\",\r\n stripWidth: \"2px\",\r\n minHeight: \"28px\",\r\n },\r\n sm: {\r\n padding: \"5px 9px\",\r\n titleFontSize: \"14px\",\r\n messageFontSize: \"13px\",\r\n gap: \"6px\",\r\n icon: \"16px\",\r\n closeSize: \"20px\",\r\n closeFontSize: \"14px\",\r\n spinner: \"14px\",\r\n stripWidth: \"3px\",\r\n minHeight: \"32px\",\r\n },\r\n md: {\r\n padding: \"8px 12px\",\r\n titleFontSize: \"16px\",\r\n messageFontSize: \"14px\",\r\n gap: \"8px\",\r\n icon: \"20px\",\r\n closeSize: \"24px\",\r\n closeFontSize: \"16px\",\r\n spinner: \"16px\",\r\n stripWidth: \"4px\",\r\n minHeight: \"36px\",\r\n },\r\n lg: {\r\n padding: \"10px 14px\",\r\n titleFontSize: \"18px\",\r\n messageFontSize: \"15px\",\r\n gap: \"10px\",\r\n icon: \"22px\",\r\n closeSize: \"28px\",\r\n closeFontSize: \"18px\",\r\n spinner: \"18px\",\r\n stripWidth: \"5px\",\r\n minHeight: \"40px\",\r\n },\r\n xl: {\r\n padding: \"12px 16px\",\r\n titleFontSize: \"20px\",\r\n messageFontSize: \"16px\",\r\n gap: \"12px\",\r\n icon: \"24px\",\r\n closeSize: \"32px\",\r\n closeFontSize: \"20px\",\r\n spinner: \"20px\",\r\n stripWidth: \"6px\",\r\n minHeight: \"44px\",\r\n },\r\n };\r\n\r\n if (presets[input]) {\r\n this._sizeCache = { size: key, result: presets[input] };\r\n return presets[input];\r\n }\r\n\r\n const m = String(input)\r\n .trim()\r\n .match(/^([\\d.]+)(px|rem|em)?$/i);\r\n const unit = m?.[2] || \"px\";\r\n const fsNum = m ? parseFloat(m[1]) : 16;\r\n const fs = `${fsNum}${unit}`;\r\n\r\n const to = (n: number) => `${Math.round(n * 100) / 100}${unit}`;\r\n const clamp = (n: number, min: number, max: number) =>\r\n Math.max(min, Math.min(max, n));\r\n\r\n const titleFs = fs;\r\n const messageFs = clamp(fsNum * 0.875, 11, 16);\r\n const py = clamp(fsNum * 0.5, 3, 12);\r\n const px = clamp(fsNum * 0.75, 7, 16);\r\n const gap = clamp(fsNum * 0.5, 4, 12);\r\n const icon = clamp(fsNum * 1.25, 14, 24);\r\n const closeSize = clamp(fsNum * 1.5, 18, 32);\r\n const closeFont = clamp(fsNum * 1, 12, 20);\r\n const spinner = clamp(fsNum * 1, 12, 20);\r\n const stripWidth = clamp(fsNum * 0.25, 2, 6);\r\n const minHeight = clamp(fsNum * 2.25, 28, 44);\r\n\r\n return {\r\n padding: `${to(py)} ${to(px)}`,\r\n titleFontSize: titleFs,\r\n messageFontSize: to(messageFs),\r\n gap: to(gap),\r\n icon: to(icon),\r\n closeSize: to(closeSize),\r\n closeFontSize: to(closeFont),\r\n spinner: to(spinner),\r\n stripWidth: to(stripWidth),\r\n minHeight: to(minHeight),\r\n };\r\n }\r\n\r\n /**\r\n * Lit order: willUpdate → controllers hostUpdate (presets) → update/render.\r\n * Rebuild CSS vars here so preset-applied color/variant are visible.\r\n */\r\n override update(changedProperties: PropertyValues): void {\r\n if (\r\n changedProperties.has(\"color\") ||\r\n changedProperties.has(\"variant\") ||\r\n changedProperties.has(\"stripColor\") ||\r\n changedProperties.has(\"radius\") ||\r\n changedProperties.has(\"size\") ||\r\n changedProperties.has(\"preset\") ||\r\n this._presets.revision !== this._lastPresetRevision\r\n ) {\r\n this._lastPresetRevision = this._presets.revision;\r\n this._updateStyleVars();\r\n }\r\n super.update(changedProperties);\r\n }\r\n\r\n private _lastPresetRevision = -1;\r\n\r\n /** Initializes actions-slot presence state after first render. */\r\n override firstUpdated(): void {\r\n queueMicrotask(() => this._checkActionsSlot());\r\n }\r\n\r\n /** Computes CSS custom properties from current variant, size, and color inputs. */\r\n private _updateStyleVars(): void {\r\n const baseColor = resolveColor(this.color);\r\n const textColor = ON_COLOR_FALLBACK_LIGHT;\r\n const stripColorResolved = this.stripColor === \"currentColor\"\r\n ? baseColor\r\n : resolveColor(this.stripColor);\r\n\r\n const s = this._resolveSize(this.size);\r\n\r\n const semanticKey = resolveSemanticSurfaceKey(this.color);\r\n\r\n const variantStyles = {\r\n solid: {\r\n bg: baseColor,\r\n color: textColor,\r\n border: \"none\",\r\n },\r\n flat: semanticKey\r\n ? semanticSoftSurfaceTokens(semanticKey)\r\n : {\r\n bg: fadeMix(baseColor, 20),\r\n color: hoverShade(baseColor, 30),\r\n border: \"none\",\r\n },\r\n faded: semanticKey\r\n ? semanticSoftSurfaceTokens(semanticKey, { bordered: true })\r\n : {\r\n bg: \"var(--sky-hover-tertiary)\",\r\n color: baseColor,\r\n border: \"1px solid var(--sky-text-tertiary)\",\r\n },\r\n bordered: {\r\n bg: \"transparent\",\r\n color: semanticKey\r\n ? `var(--sky-${semanticKey}-primary-dark)`\r\n : baseColor,\r\n border: `2px solid ${baseColor}`,\r\n },\r\n light: {\r\n bg: \"transparent\",\r\n color: semanticKey\r\n ? `var(--sky-${semanticKey}-primary-dark)`\r\n : baseColor,\r\n border: \"none\",\r\n },\r\n } as const;\r\n\r\n const currentVariant = this.variant in variantStyles\r\n ? this.variant as keyof typeof variantStyles\r\n : \"flat\";\r\n\r\n let v = tuneSurfaceVariantForDefaultColor(\r\n this.color,\r\n currentVariant,\r\n variantStyles[currentVariant],\r\n );\r\n\r\n if (\r\n isDefaultColorToken(this.color) &&\r\n (currentVariant === \"flat\" || currentVariant === \"faded\")\r\n ) {\r\n v = {\r\n ...v,\r\n bg: \"var(--sky-glass-solid)\",\r\n color: \"var(--sky-text-primary)\",\r\n border: currentVariant === \"faded\" ? skyBorderPrimaryShorthand() : \"none\",\r\n };\r\n }\r\n\r\n let closeBg = \"var(--sky-hover-primary)\";\r\n let closeColor = \"currentColor\";\r\n let closeHoverBg = \"var(--sky-hover-secondary)\";\r\n let closeHoverColor = \"currentColor\";\r\n\r\n if (currentVariant === \"solid\") {\r\n closeBg = fadeMix(textColor, 20);\r\n closeColor = textColor;\r\n closeHoverBg = fadeMix(textColor, 30);\r\n closeHoverColor = textColor;\r\n } else if (currentVariant === \"flat\" || currentVariant === \"faded\") {\r\n if (semanticKey) {\r\n closeBg = `var(--sky-${semanticKey}-g0)`;\r\n closeColor = v.color;\r\n closeHoverBg = `var(--sky-${semanticKey}-g1)`;\r\n closeHoverColor = v.color;\r\n } else if (isDefaultColorToken(this.color)) {\r\n closeBg = \"var(--sky-hover-primary)\";\r\n closeColor = v.color;\r\n closeHoverBg = \"var(--sky-hover-secondary)\";\r\n closeHoverColor = v.color;\r\n } else {\r\n closeBg = fadeMix(baseColor, 15);\r\n closeColor = v.color;\r\n closeHoverBg = fadeMix(baseColor, 25);\r\n closeHoverColor = v.color;\r\n }\r\n }\r\n\r\n this._styleVars = {\r\n \"--alert-bg\": v.bg,\r\n \"--alert-color\": v.color,\r\n \"--alert-border\": v.border,\r\n \"--alert-radius\": resolveRadius(this.radius),\r\n \"--alert-padding\": s.padding,\r\n \"--alert-gap\": s.gap,\r\n \"--alert-min-height\": s.minHeight,\r\n \"--title-font-size\": s.titleFontSize,\r\n \"--message-font-size\": s.messageFontSize,\r\n \"--icon-size\": s.icon,\r\n \"--close-size\": s.closeSize,\r\n \"--close-font-size\": s.closeFontSize,\r\n \"--spinner-size\": s.spinner,\r\n \"--strip-color\": stripColorResolved,\r\n \"--strip-width\": s.stripWidth,\r\n \"--close-bg\": closeBg,\r\n \"--close-color\": closeColor,\r\n \"--close-hover-bg\": closeHoverBg,\r\n \"--close-hover-color\": closeHoverColor,\r\n \"--sky-focus-ring-color\": baseColor,\r\n };\r\n }\r\n\r\n /**\r\n * Dispatches `alert-closed` and removes the alert from the DOM.\r\n *\r\n * @returns {void}\r\n */\r\n public close(): void {\r\n const evt = new CustomEvent<SkyAlertClosedEventDetail>(\"alert-closed\", {\r\n detail: { title: this.title, message: this.message },\r\n bubbles: true,\r\n composed: true,\r\n });\r\n this.dispatchEvent(evt);\r\n this.remove();\r\n }\r\n\r\n /** Returns the ARIA role applied to the alert container. */\r\n private getAriaRole(): SkyAlertRoleType {\r\n return this.roleType;\r\n }\r\n\r\n /** Checks whether the actions slot currently has meaningful assigned content. */\r\n private _checkActionsSlot(): void {\r\n const slot = this.renderRoot?.querySelector<HTMLSlotElement>('slot[name=\"actions\"]');\r\n if (!slot) return;\r\n const nodes = slot.assignedNodes({ flatten: true });\r\n const hasContent = nodes.some(\r\n (n) => n.nodeType !== Node.TEXT_NODE || (n.textContent?.trim().length ?? 0) > 0,\r\n );\r\n if (hasContent !== this._hasActionsSlotContent) {\r\n this._hasActionsSlotContent = hasContent;\r\n }\r\n }\r\n\r\n /** Updates action-slot state when the slot assignment changes. */\r\n private _onActionsSlotChange(e: Event): void {\r\n const slot = e.target as HTMLSlotElement;\r\n const nodes = slot.assignedNodes({ flatten: true });\r\n const hasContent = nodes.some(\r\n (n) => n.nodeType !== Node.TEXT_NODE || (n.textContent?.trim().length ?? 0) > 0,\r\n );\r\n this._hasActionsSlotContent = hasContent;\r\n }\r\n\r\n override render() {\r\n const roleAttr = this.getAriaRole();\r\n const alertClasses = classMap({\r\n alert: true,\r\n [this.variant]: true,\r\n \"strip-start\": this.strip === \"start\" || this.strip === \"both\",\r\n \"strip-end\": this.strip === \"end\" || this.strip === \"both\",\r\n });\r\n\r\n return html`\r\n <div\r\n part=\"alert\"\r\n class=${alertClasses}\r\n role=\"${roleAttr}\"\r\n aria-live=\"${this.roleType === \"alert\" ? \"assertive\" : \"polite\"}\"\r\n style=${styleMap(this._styleVars)}\r\n >\r\n ${when(\r\n this.icon,\r\n () => html`<sky-icon part=\"icon\" class=\"icon\" icon=\"${this.icon!}\"></sky-icon>`,\r\n )}\r\n\r\n <div part=\"content\" class=\"content\">\r\n ${when(\r\n this.title,\r\n () => html`<div part=\"title\" class=\"title\">${this.title}</div>`,\r\n )}\r\n ${when(\r\n this.message,\r\n () => html`<p part=\"message\" class=\"message\">${this.message}</p>`,\r\n () => html`<slot></slot>`,\r\n )}\r\n </div>\r\n\r\n ${when(\r\n this._hasActionsSlotContent || this.removable,\r\n () => html`\r\n <div part=\"actions\" class=\"actions\">\r\n <slot name=\"actions\" @slotchange=${this._onActionsSlotChange}></slot>\r\n ${when(\r\n this.removable,\r\n () => html`\r\n <button\r\n part=\"close-button\"\r\n class=\"close-button\"\r\n type=\"button\"\r\n @click=${this.close}\r\n aria-label=\"Dismiss alert\"\r\n title=\"Dismiss\"\r\n >\r\n <sky-icon icon=\"ion:close\"></sky-icon>\r\n </button>\r\n `,\r\n )}\r\n </div>\r\n `,\r\n () => html`\r\n <div class=\"actions-slot-placeholder\" aria-hidden=\"true\">\r\n <slot name=\"actions\" @slotchange=${this._onActionsSlotChange}></slot>\r\n </div>\r\n `,\r\n )}\r\n\r\n ${when(\r\n this.loading,\r\n () => html`\r\n <div part=\"loading-overlay\" class=\"loading-overlay\">\r\n <div part=\"loading-spinner\" class=\"loading-spinner\"></div>\r\n </div>\r\n `,\r\n )}\r\n </div>\r\n `;\r\n }\r\n}"],"names":["SkyAlert","LitElement","constructor","super","arguments","this","title","message","removable","color","size","radius","icon","strip","stripColor","variant","loading","roleType","_styleVars","_sizeCache","_hasActionsSlotContent","preset","_presets","PresetController","_lastPresetRevision","_resolveSize","input","key","String","trim","result","presets","xs","padding","titleFontSize","messageFontSize","gap","closeSize","closeFontSize","spinner","stripWidth","minHeight","sm","md","lg","xl","m","match","unit","fsNum","parseFloat","to","n","Math","round","clamp","min","max","titleFs","messageFs","py","px","closeFont","update","changedProperties","has","revision","_updateStyleVars","firstUpdated","queueMicrotask","_checkActionsSlot","baseColor","resolveColor","textColor","ON_COLOR_FALLBACK_LIGHT","stripColorResolved","s","semanticKey","resolveSemanticSurfaceKey","variantStyles","solid","bg","border","flat","semanticSoftSurfaceTokens","fadeMix","hoverShade","faded","bordered","light","currentVariant","v","tuneSurfaceVariantForDefaultColor","isDefaultColorToken","skyBorderPrimaryShorthand","closeBg","closeColor","closeHoverBg","closeHoverColor","resolveRadius","close","evt","CustomEvent","detail","bubbles","composed","dispatchEvent","remove","getAriaRole","slot","renderRoot","querySelector","hasContent","assignedNodes","flatten","some","nodeType","Node","TEXT_NODE","textContent","length","_onActionsSlotChange","e","target","render","roleAttr","alertClasses","classMap","alert","html","styleMap","when","dependencies","SkyIcon","styles","skyFocusRingHostStyles","css","unsafeCSS","cssOnFillEnhance","selector","fillVar","__decorateClass","property","type","prototype","Boolean","reflect","state","customElement"],"mappings":"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"}
@@ -7,7 +7,7 @@ import { LitElement, PropertyValues } from "lit";
7
7
  * @status stable
8
8
  * @since 1.0.0
9
9
  *
10
- * @documentation https://library.sky-ui.com/components/appbar
10
+ * @documentation https://sky-ui.com/components/appbar
11
11
  * @dependency sky-icon
12
12
  *
13
13
  * @slot button - Leading area (e.g., menu/back button). Defaults to a hamburger icon.
@@ -20,6 +20,7 @@ import { LitElement, PropertyValues } from "lit";
20
20
  * @property {boolean} dense - Enables compact vertical spacing.
21
21
  * @property {boolean} elevated - Applies elevated shadow styling.
22
22
  * @property {string} leadingLabel - Accessible label for default leading button fallback.
23
+ * @property {string} preset - Named prop preset from nearest `sky-config-provider`. Default: `""`.
23
24
  *
24
25
  * @csspart content - Wrapper that contains the leading slot, title, and actions.
25
26
  * @csspart leading - Container for the leading slot (e.g. menu button).
@@ -27,7 +28,8 @@ import { LitElement, PropertyValues } from "lit";
27
28
  * @csspart actions - The trailing actions container.
28
29
  *
29
30
  * @Behavior
30
- * - `color` resolves background via `resolveColor()` and text/icon color via `resolveTextColorForToken()`.
31
+ * - `color` resolves background via `resolveColor()`; solid FG uses on-color
32
+ * fallback + `contrast-color()` against the fill.
31
33
  * - `url` renders a background layer behind content.
32
34
  * - `banner` should be true only for the primary page app bar landmark.
33
35
  * - In RTL contexts, the default leading icon is mirrored unless reduced motion is enabled.
@@ -63,7 +65,8 @@ export declare class SkyAppbar extends LitElement {
63
65
  /** Title text displayed in the app bar. @default "App Bar" */
64
66
  title: string;
65
67
  /**
66
- * Bar background token or CSS color; when set, foreground uses `resolveTextColorForToken` for contrast.
68
+ * Bar background token or CSS color; when set, foreground uses on-color
69
+ * fallback enhanced by `contrast-color()` against the fill.
67
70
  * @default "default"
68
71
  */
69
72
  color: string;
@@ -77,6 +80,9 @@ export declare class SkyAppbar extends LitElement {
77
80
  elevated: boolean;
78
81
  /** Accessible label for the default leading button when no slot content is provided. @default "Open menu" */
79
82
  leadingLabel: string;
83
+ /** Named prop preset from nearest `sky-config-provider`. */
84
+ preset: string;
85
+ private _presets;
80
86
  static styles: import("lit").CSSResult;
81
87
  /** Applies glass vs solid surface tokens from `color`. */
82
88
  private _applyColorSurface;
@@ -1,4 +1,4 @@
1
- import{unsafeCSS as t,css as e,LitElement as r,nothing as o,html as a}from"lit";import{property as n,customElement as s}from"lit/decorators.js";import{isDefaultColorToken as i,resolveColor as l,resolveTextColorForToken as d}from"../helper/utils/color-resolver.js";import{cssOnFillEnhance as c}from"../helper/utils/contrast-color.js";import{SkyIcon as p}from"../sky-icon/sky-icon.js";var b=Object.defineProperty,y=Object.getOwnPropertyDescriptor,u=(t,e,r,o)=>{for(var a,n=o>1?void 0:o?y(e,r):e,s=t.length-1;s>=0;s--)(a=t[s])&&(n=(o?a(e,r,n):a(n))||n);return o&&n&&b(e,r,n),n};let k=class extends r{constructor(){super(...arguments),this.title="App Bar",this.color="default",this.url="",this.banner=!0,this.dense=!1,this.elevated=!1,this.leadingLabel="Open menu"}_applyColorSurface(){if(!i(this.color))return this.setAttribute("data-surface","solid"),this.style.setProperty("--appbar-bg-color",l(this.color)),void this.style.setProperty("--appbar-text-color",d(this.color));this.removeAttribute("data-surface"),this.style.removeProperty("--appbar-bg-color"),this.style.removeProperty("--appbar-text-color")}connectedCallback(){super.connectedCallback(),this._applyColorSurface(),this._applyBackgroundImage()}_applyBackgroundImage(){const t=this.url?`url(${this.url})`:"none";this.style.setProperty("--appbar-bg-image",t)}updated(t){t.has("color")&&this._applyColorSurface(),t.has("url")&&this._applyBackgroundImage()}render(){return a`
1
+ import{unsafeCSS as t,css as e,LitElement as r,nothing as o,html as a}from"lit";import{property as s,customElement as n}from"lit/decorators.js";import{isDefaultColorToken as i,resolveColor as l}from"../helper/utils/color-resolver.js";import{cssOnFillEnhance as d,ON_COLOR_FALLBACK_LIGHT as p}from"../helper/utils/contrast-color.js";import{SkyIcon as c}from"../sky-icon/sky-icon.js";import{PresetController as b}from"../helper/controllers/preset-controller.js";var y=Object.defineProperty,u=Object.getOwnPropertyDescriptor,k=(t,e,r,o)=>{for(var a,s=o>1?void 0:o?u(e,r):e,n=t.length-1;n>=0;n--)(a=t[n])&&(s=(o?a(e,r,s):a(s))||s);return o&&s&&y(e,r,s),s};let h=class extends r{constructor(){super(...arguments),this.title="App Bar",this.color="default",this.url="",this.banner=!0,this.dense=!1,this.elevated=!1,this.leadingLabel="Open menu",this.preset="",this._presets=new b(this)}_applyColorSurface(){if(!i(this.color))return this.setAttribute("data-surface","solid"),this.style.setProperty("--appbar-bg-color",l(this.color)),void this.style.setProperty("--appbar-text-color",p);this.removeAttribute("data-surface"),this.style.removeProperty("--appbar-bg-color"),this.style.removeProperty("--appbar-text-color")}connectedCallback(){super.connectedCallback(),this._applyColorSurface(),this._applyBackgroundImage()}_applyBackgroundImage(){const t=this.url?`url(${this.url})`:"none";this.style.setProperty("--appbar-bg-image",t)}updated(t){t.has("color")&&this._applyColorSurface(),t.has("url")&&this._applyBackgroundImage()}render(){return a`
2
2
  ${this.url?a`
3
3
  <div class="background" aria-hidden="true"></div>
4
4
  <div class="background-overlay" aria-hidden="true"></div>
@@ -26,7 +26,7 @@ import{unsafeCSS as t,css as e,LitElement as r,nothing as o,html as a}from"lit";
26
26
  <slot></slot>
27
27
  </div>
28
28
  </div>
29
- `}};k.dependencies={"sky-icon":p},k.styles=e`
29
+ `}};h.dependencies={"sky-icon":c},h.styles=e`
30
30
  :host {
31
31
  width: 100%;
32
32
  display: flex;
@@ -211,6 +211,6 @@ import{unsafeCSS as t,css as e,LitElement as r,nothing as o,html as a}from"lit";
211
211
  }
212
212
  }
213
213
 
214
- ${t(c([{selector:':host([data-surface="solid"])',fillVar:"--appbar-bg-color"}]))}
215
- `,u([n({type:String})],k.prototype,"title",2),u([n({type:String})],k.prototype,"color",2),u([n({type:String})],k.prototype,"url",2),u([n({type:Boolean})],k.prototype,"banner",2),u([n({type:Boolean})],k.prototype,"dense",2),u([n({type:Boolean})],k.prototype,"elevated",2),u([n({type:String})],k.prototype,"leadingLabel",2),k=u([s("sky-appbar")],k);export{k as SkyAppbar};
214
+ ${t(d([{selector:':host([data-surface="solid"])',fillVar:"--appbar-bg-color"}]))}
215
+ `,k([s({type:String})],h.prototype,"title",2),k([s({type:String})],h.prototype,"color",2),k([s({type:String})],h.prototype,"url",2),k([s({type:Boolean})],h.prototype,"banner",2),k([s({type:Boolean})],h.prototype,"dense",2),k([s({type:Boolean})],h.prototype,"elevated",2),k([s({type:String})],h.prototype,"leadingLabel",2),k([s({type:String,reflect:!0})],h.prototype,"preset",2),h=k([n("sky-appbar")],h);export{h as SkyAppbar};
216
216
  //# sourceMappingURL=sky-appbar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sky-appbar.js","sources":["../../src/sky-appbar/sky-appbar.ts"],"sourcesContent":["import { LitElement, html, css, PropertyValues, nothing, unsafeCSS } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport {\n resolveColor,\n resolveTextColorForToken,\n isDefaultColorToken,\n} from \"../helper/utils/color-resolver\";\nimport { cssOnFillEnhance } from \"../helper/utils/contrast-color\";\nimport { SkyIcon } from \"../sky-icon/sky-icon.js\";\n\n/**\n * @element sky-appbar\n *\n * @summary Application top bar with title, optional leading control, trailing actions, and optional color/image background.\n *\n * @status stable\n * @since 1.0.0\n *\n * @documentation https://library.sky-ui.com/components/appbar\n * @dependency sky-icon\n *\n * @slot button - Leading area (e.g., menu/back button). Defaults to a hamburger icon.\n * @slot - Trailing actions (icons/buttons). This is the default slot.\n *\n * @property {string} title - Title text displayed in the app bar.\n * @property {string} color - Semantic token or CSS color for bar background; foreground color is derived for contrast.\n * @property {string} url - Background image URL.\n * @property {boolean} banner - Uses `role=\"banner\"` when true, otherwise `role=\"group\"`.\n * @property {boolean} dense - Enables compact vertical spacing.\n * @property {boolean} elevated - Applies elevated shadow styling.\n * @property {string} leadingLabel - Accessible label for default leading button fallback.\n *\n * @csspart content - Wrapper that contains the leading slot, title, and actions.\n * @csspart leading - Container for the leading slot (e.g. menu button).\n * @csspart title - The title area (contains .title-text with the title string).\n * @csspart actions - The trailing actions container.\n *\n * @Behavior\n * - `color` resolves background via `resolveColor()` and text/icon color via `resolveTextColorForToken()`.\n * - `url` renders a background layer behind content.\n * - `banner` should be true only for the primary page app bar landmark.\n * - In RTL contexts, the default leading icon is mirrored unless reduced motion is enabled.\n *\n * @example\n * ```html\n * <sky-appbar title=\"Dashboard\" color=\"primary\" dense>\n * <button slot=\"button\">Menu</button>\n * <sky-icon icon=\"ion:search\"></sky-icon>\n * </sky-appbar>\n * ```\n * ```vue\n * <template>\n * <sky-appbar title=\"Dashboard\" color=\"primary\" dense>\n * <button slot=\"button\">Menu</button>\n * <sky-icon icon=\"ion:search\"></sky-icon>\n * </sky-appbar>\n * </template>\n * ```\n * ```jsx\n * export default function Demo() {\n * return (\n * <sky-appbar title=\"Dashboard\" color=\"primary\" dense>\n * <button slot=\"button\">Menu</button>\n * <sky-icon icon=\"ion:search\"></sky-icon>\n * </sky-appbar>\n * );\n * }\n * ```\n */\n@customElement(\"sky-appbar\")\nexport class SkyAppbar extends LitElement {\n\n static dependencies: Record<string, CustomElementConstructor> = {\n \"sky-icon\": SkyIcon,\n };\n\n /** Title text displayed in the app bar. @default \"App Bar\" */\n @property({ type: String }) title = \"App Bar\";\n\n /**\n * Bar background token or CSS color; when set, foreground uses `resolveTextColorForToken` for contrast.\n * @default \"default\"\n */\n @property({ type: String }) color = \"default\";\n\n /** Background image URL. @default \"\" */\n @property({ type: String }) url = \"\";\n\n /** When true, the bar has role=\"banner\" (main app header). Set false for secondary bars. @default true */\n @property({ type: Boolean }) banner = true;\n\n /** When true, reduces vertical padding for a compact bar. @default false */\n @property({ type: Boolean }) dense = false;\n\n /** When true, applies stronger shadow (e.g. for sticky bar after scroll). @default false */\n @property({ type: Boolean }) elevated = false;\n\n /** Accessible label for the default leading button when no slot content is provided. @default \"Open menu\" */\n @property({ type: String }) leadingLabel = \"Open menu\";\n\n static override styles = css`\n :host {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: relative;\n font-family: var(--sky-font);\n overflow: hidden;\n color: var(--appbar-text-color, var(--sky-text-primary));\n transition: var(--sky-transition-default);\n }\n\n :host(:not([data-surface=\"solid\"])) {\n background: var(--sky-glass-secondary);\n background-image: var(--sky-glass-surface);\n backdrop-filter:\n var(--sky-blur-secondary)\n var(--sky-saturation-secondary)\n var(--sky-brightness-secondary);\n -webkit-backdrop-filter:\n var(--sky-blur-secondary)\n var(--sky-saturation-secondary)\n var(--sky-brightness-secondary);\n border-bottom: var(--sky-border-secondary);\n box-shadow:\n var(--sky-box-shadow-inset),\n var(--sky-box-shadow-primary);\n }\n\n :host([data-surface=\"solid\"]) {\n background-color: var(--appbar-bg-color);\n color: var(--appbar-text-color);\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n border-bottom: var(--sky-border-primary);\n box-shadow: var(--sky-box-shadow-primary);\n }\n\n :host([elevated]:not([data-surface=\"solid\"])) {\n box-shadow:\n var(--sky-box-shadow-inset),\n var(--sky-box-shadow-secondary);\n }\n\n :host([elevated][data-surface=\"solid\"]) {\n box-shadow: var(--sky-box-shadow-secondary);\n }\n\n .background {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n background-image: var(--appbar-bg-image, none);\n background-size: cover;\n background-position: center;\n z-index: -2;\n pointer-events: none;\n }\n\n .background-overlay {\n position: absolute;\n inset: 0;\n background: var(--appbar-bg-overlay, transparent);\n z-index: -1;\n pointer-events: none;\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n }\n\n .content {\n display: flex;\n padding: var(--sky-space-2, 8px) var(--sky-space-4, 16px);\n align-items: center;\n justify-content: space-between;\n width: 100%;\n position: relative;\n gap: var(--sky-space-2, 8px);\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n }\n\n :host([dense]) .content {\n padding-block: var(--sky-space-1, 4px);\n }\n\n .title-area {\n flex: 1 1 auto;\n min-width: 0;\n padding-inline-start: var(--sky-space-2\\\\.5, 10px);\n }\n\n .title-text {\n font: var(--sky-text-title);\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n }\n\n .leading {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n }\n\n .leading ::slotted(*) {\n cursor: pointer;\n }\n\n .leading-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin: 0;\n padding: 0;\n border: none;\n background: none;\n cursor: pointer;\n font: inherit;\n color: inherit;\n -webkit-tap-highlight-color: transparent;\n min-width: var(--sky-touch-target, 44px);\n min-height: var(--sky-touch-target, 44px);\n box-sizing: border-box;\n border-radius: var(--sky-radius-primary);\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n transition: var(--sky-transition-fast);\n }\n\n .leading-button:hover {\n background: var(--sky-hover-primary);\n }\n\n .leading-button:focus-visible,\n .leading ::slotted(*:focus-visible),\n .actions ::slotted(*:focus-visible) {\n outline: none;\n box-shadow: var(--sky-focus-ring);\n }\n\n .icon {\n cursor: pointer;\n font-size: var(--sky-font-size-xl, 1.25rem);\n display: flex;\n align-items: center;\n }\n\n .actions {\n display: flex;\n align-items: center;\n gap: var(--sky-space-2, 8px);\n padding-inline-start: var(--sky-space-2\\\\.5, 10px);\n flex-shrink: 0;\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n }\n\n .actions ::slotted(button),\n .actions ::slotted([role=\"button\"]) {\n min-width: var(--sky-touch-target, 44px);\n min-height: var(--sky-touch-target, 44px);\n box-sizing: border-box;\n }\n\n :host-context([dir=\"rtl\"]) .leading-button .icon {\n transform: scaleX(-1);\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host,\n .content,\n .leading-button,\n .leading ::slotted(*),\n .actions ::slotted(*) {\n transition: none;\n }\n\n :host-context([dir=\"rtl\"]) .leading-button .icon {\n transform: none;\n }\n }\n\n ${unsafeCSS(\n cssOnFillEnhance([\n {\n selector: ':host([data-surface=\"solid\"])',\n fillVar: \"--appbar-bg-color\",\n },\n ]),\n )}\n `;\n\n /** Applies glass vs solid surface tokens from `color`. */\n private _applyColorSurface(): void {\n if (!isDefaultColorToken(this.color)) {\n this.setAttribute(\"data-surface\", \"solid\");\n this.style.setProperty(\"--appbar-bg-color\", resolveColor(this.color));\n this.style.setProperty(\n \"--appbar-text-color\",\n resolveTextColorForToken(this.color),\n );\n return;\n }\n\n this.removeAttribute(\"data-surface\");\n this.style.removeProperty(\"--appbar-bg-color\");\n this.style.removeProperty(\"--appbar-text-color\");\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._applyColorSurface();\n this._applyBackgroundImage();\n }\n\n /** Sets background image CSS variable from `url`. */\n private _applyBackgroundImage(): void {\n const image = this.url ? `url(${this.url})` : \"none\";\n this.style.setProperty(\"--appbar-bg-image\", image);\n }\n\n /** Updates host style variables when visual input properties change. */\n protected override updated(changedProperties: PropertyValues): void {\n if (changedProperties.has(\"color\")) {\n this._applyColorSurface();\n }\n\n if (changedProperties.has(\"url\")) {\n this._applyBackgroundImage();\n }\n }\n\n override render() {\n return html`\n ${this.url\n ? html`\n <div class=\"background\" aria-hidden=\"true\"></div>\n <div class=\"background-overlay\" aria-hidden=\"true\"></div>\n `\n : nothing}\n <div\n class=\"content\"\n part=\"content\"\n role=\"${this.banner ? \"banner\" : \"group\"}\"\n >\n <div class=\"leading\" part=\"leading\">\n <slot name=\"button\">\n <button\n type=\"button\"\n class=\"leading-button\"\n aria-label=\"${this.leadingLabel}\"\n >\n <sky-icon class=\"icon\" icon=\"mdi:menu\"></sky-icon>\n </button>\n </slot>\n </div>\n <div class=\"title-area\" part=\"title\">\n <span class=\"title-text\">${this.title}</span>\n </div>\n <div class=\"actions\" part=\"actions\">\n <slot></slot>\n </div>\n </div>\n `;\n }\n}\n"],"names":["SkyAppbar","LitElement","constructor","super","arguments","this","title","color","url","banner","dense","elevated","leadingLabel","_applyColorSurface","isDefaultColorToken","setAttribute","style","setProperty","resolveColor","resolveTextColorForToken","removeAttribute","removeProperty","connectedCallback","_applyBackgroundImage","image","updated","changedProperties","has","render","html","nothing","dependencies","SkyIcon","styles","css","unsafeCSS","cssOnFillEnhance","selector","fillVar","__decorateClass","property","type","String","prototype","Boolean","customElement"],"mappings":"+jBAsEO,IAAMA,EAAN,cAAwBC,EAAxB,WAAAC,GAAAC,SAAAC,WAOuBC,KAAAC,MAAQ,UAMRD,KAAAE,MAAQ,UAGRF,KAAAG,IAAM,GAGLH,KAAAI,QAAS,EAGTJ,KAAAK,OAAQ,EAGRL,KAAAM,UAAW,EAGZN,KAAAO,aAAe,WAAA,CAsMnC,kBAAAC,GACN,IAAKC,EAAoBT,KAAKE,OAO5B,OANAF,KAAKU,aAAa,eAAgB,SAClCV,KAAKW,MAAMC,YAAY,oBAAqBC,EAAab,KAAKE,aAC9DF,KAAKW,MAAMC,YACT,sBACAE,EAAyBd,KAAKE,QAKlCF,KAAKe,gBAAgB,gBACrBf,KAAKW,MAAMK,eAAe,qBAC1BhB,KAAKW,MAAMK,eAAe,sBAC5B,CAES,iBAAAC,GACPnB,MAAMmB,oBACNjB,KAAKQ,qBACLR,KAAKkB,uBACP,CAGQ,qBAAAA,GACN,MAAMC,EAAQnB,KAAKG,IAAM,OAAOH,KAAKG,OAAS,OAC9CH,KAAKW,MAAMC,YAAY,oBAAqBO,EAC9C,CAGmB,OAAAC,CAAQC,GACrBA,EAAkBC,IAAI,UACxBtB,KAAKQ,qBAGHa,EAAkBC,IAAI,QACxBtB,KAAKkB,uBAET,CAES,MAAAK,GACP,OAAOC,CAAA;QACHxB,KAAKG,IACHqB,CAAA;;;YAIAC;;;;gBAIMzB,KAAKI,OAAS,SAAW;;;;;;;4BAObJ,KAAKO;;;;;;;qCAOIP,KAAKC;;;;;;KAOxC,GAzSWN,EAEJ+B,aAAyD,CAC9D,WAAYC,GAHHhC,EA8BKiC,OAASC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAyLrBC,EACAC,EAAiB,CACf,CACEC,SAAU,gCACVC,QAAS;IApNWC,EAAA,CAA3BC,EAAS,CAAEC,KAAMC,UAPP1C,EAOiB2C,UAAA,QAAA,GAMAJ,EAAA,CAA3BC,EAAS,CAAEC,KAAMC,UAbP1C,EAaiB2C,UAAA,QAAA,GAGAJ,EAAA,CAA3BC,EAAS,CAAEC,KAAMC,UAhBP1C,EAgBiB2C,UAAA,MAAA,GAGCJ,EAAA,CAA5BC,EAAS,CAAEC,KAAMG,WAnBP5C,EAmBkB2C,UAAA,SAAA,GAGAJ,EAAA,CAA5BC,EAAS,CAAEC,KAAMG,WAtBP5C,EAsBkB2C,UAAA,QAAA,GAGAJ,EAAA,CAA5BC,EAAS,CAAEC,KAAMG,WAzBP5C,EAyBkB2C,UAAA,WAAA,GAGDJ,EAAA,CAA3BC,EAAS,CAAEC,KAAMC,UA5BP1C,EA4BiB2C,UAAA,eAAA,GA5BjB3C,EAANuC,EAAA,CADNM,EAAc,eACF7C"}
1
+ {"version":3,"file":"sky-appbar.js","sources":["../../src/sky-appbar/sky-appbar.ts"],"sourcesContent":["import { LitElement, html, css, PropertyValues, nothing, unsafeCSS } from \"lit\";\r\nimport { customElement, property } from \"lit/decorators.js\";\r\nimport {\r\n resolveColor,\r\n isDefaultColorToken,\r\n} from \"../helper/utils/color-resolver\";\r\nimport { cssOnFillEnhance, ON_COLOR_FALLBACK_LIGHT } from \"../helper/utils/contrast-color\";\r\nimport { SkyIcon } from \"../sky-icon/sky-icon.js\";\r\nimport { PresetController } from \"../helper/controllers/preset-controller\";\r\n\r\n/**\r\n * @element sky-appbar\r\n *\r\n * @summary Application top bar with title, optional leading control, trailing actions, and optional color/image background.\r\n *\r\n * @status stable\r\n * @since 1.0.0\r\n *\r\n * @documentation https://sky-ui.com/components/appbar\r\n * @dependency sky-icon\r\n *\r\n * @slot button - Leading area (e.g., menu/back button). Defaults to a hamburger icon.\r\n * @slot - Trailing actions (icons/buttons). This is the default slot.\r\n *\r\n * @property {string} title - Title text displayed in the app bar.\r\n * @property {string} color - Semantic token or CSS color for bar background; foreground color is derived for contrast.\r\n * @property {string} url - Background image URL.\r\n * @property {boolean} banner - Uses `role=\"banner\"` when true, otherwise `role=\"group\"`.\r\n * @property {boolean} dense - Enables compact vertical spacing.\r\n * @property {boolean} elevated - Applies elevated shadow styling.\r\n * @property {string} leadingLabel - Accessible label for default leading button fallback.\r\n * @property {string} preset - Named prop preset from nearest `sky-config-provider`. Default: `\"\"`.\r\n *\r\n * @csspart content - Wrapper that contains the leading slot, title, and actions.\r\n * @csspart leading - Container for the leading slot (e.g. menu button).\r\n * @csspart title - The title area (contains .title-text with the title string).\r\n * @csspart actions - The trailing actions container.\r\n *\r\n * @Behavior\r\n * - `color` resolves background via `resolveColor()`; solid FG uses on-color\r\n * fallback + `contrast-color()` against the fill.\r\n * - `url` renders a background layer behind content.\r\n * - `banner` should be true only for the primary page app bar landmark.\r\n * - In RTL contexts, the default leading icon is mirrored unless reduced motion is enabled.\r\n *\r\n * @example\r\n * ```html\r\n * <sky-appbar title=\"Dashboard\" color=\"primary\" dense>\r\n * <button slot=\"button\">Menu</button>\r\n * <sky-icon icon=\"ion:search\"></sky-icon>\r\n * </sky-appbar>\r\n * ```\r\n * ```vue\r\n * <template>\r\n * <sky-appbar title=\"Dashboard\" color=\"primary\" dense>\r\n * <button slot=\"button\">Menu</button>\r\n * <sky-icon icon=\"ion:search\"></sky-icon>\r\n * </sky-appbar>\r\n * </template>\r\n * ```\r\n * ```jsx\r\n * export default function Demo() {\r\n * return (\r\n * <sky-appbar title=\"Dashboard\" color=\"primary\" dense>\r\n * <button slot=\"button\">Menu</button>\r\n * <sky-icon icon=\"ion:search\"></sky-icon>\r\n * </sky-appbar>\r\n * );\r\n * }\r\n * ```\r\n */\r\n@customElement(\"sky-appbar\")\r\nexport class SkyAppbar extends LitElement {\r\n\r\n static dependencies: Record<string, CustomElementConstructor> = {\r\n \"sky-icon\": SkyIcon,\r\n };\r\n\r\n /** Title text displayed in the app bar. @default \"App Bar\" */\r\n @property({ type: String }) title = \"App Bar\";\r\n\r\n /**\r\n * Bar background token or CSS color; when set, foreground uses on-color\r\n * fallback enhanced by `contrast-color()` against the fill.\r\n * @default \"default\"\r\n */\r\n @property({ type: String }) color = \"default\";\r\n\r\n /** Background image URL. @default \"\" */\r\n @property({ type: String }) url = \"\";\r\n\r\n /** When true, the bar has role=\"banner\" (main app header). Set false for secondary bars. @default true */\r\n @property({ type: Boolean }) banner = true;\r\n\r\n /** When true, reduces vertical padding for a compact bar. @default false */\r\n @property({ type: Boolean }) dense = false;\r\n\r\n /** When true, applies stronger shadow (e.g. for sticky bar after scroll). @default false */\r\n @property({ type: Boolean }) elevated = false;\r\n\r\n /** Accessible label for the default leading button when no slot content is provided. @default \"Open menu\" */\r\n @property({ type: String }) leadingLabel = \"Open menu\";\r\n\r\n\r\n /** Named prop preset from nearest `sky-config-provider`. */\r\n @property({ type: String, reflect: true }) preset = \"\";\r\n\r\n private _presets = new PresetController(this);\r\n\r\n static override styles = css`\r\n :host {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n position: relative;\r\n font-family: var(--sky-font);\r\n overflow: hidden;\r\n color: var(--appbar-text-color, var(--sky-text-primary));\r\n transition: var(--sky-transition-default);\r\n }\r\n\r\n :host(:not([data-surface=\"solid\"])) {\r\n background: var(--sky-glass-secondary);\r\n background-image: var(--sky-glass-surface);\r\n backdrop-filter:\r\n var(--sky-blur-secondary)\r\n var(--sky-saturation-secondary)\r\n var(--sky-brightness-secondary);\r\n -webkit-backdrop-filter:\r\n var(--sky-blur-secondary)\r\n var(--sky-saturation-secondary)\r\n var(--sky-brightness-secondary);\r\n border-bottom: var(--sky-border-secondary);\r\n box-shadow:\r\n var(--sky-box-shadow-inset),\r\n var(--sky-box-shadow-primary);\r\n }\r\n\r\n :host([data-surface=\"solid\"]) {\r\n background-color: var(--appbar-bg-color);\r\n color: var(--appbar-text-color);\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n border-bottom: var(--sky-border-primary);\r\n box-shadow: var(--sky-box-shadow-primary);\r\n }\r\n\r\n :host([elevated]:not([data-surface=\"solid\"])) {\r\n box-shadow:\r\n var(--sky-box-shadow-inset),\r\n var(--sky-box-shadow-secondary);\r\n }\r\n\r\n :host([elevated][data-surface=\"solid\"]) {\r\n box-shadow: var(--sky-box-shadow-secondary);\r\n }\r\n\r\n .background {\r\n position: absolute;\r\n inset: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-image: var(--appbar-bg-image, none);\r\n background-size: cover;\r\n background-position: center;\r\n z-index: -2;\r\n pointer-events: none;\r\n }\r\n\r\n .background-overlay {\r\n position: absolute;\r\n inset: 0;\r\n background: var(--appbar-bg-overlay, transparent);\r\n z-index: -1;\r\n pointer-events: none;\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n }\r\n\r\n .content {\r\n display: flex;\r\n padding: var(--sky-space-2, 8px) var(--sky-space-4, 16px);\r\n align-items: center;\r\n justify-content: space-between;\r\n width: 100%;\r\n position: relative;\r\n gap: var(--sky-space-2, 8px);\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n }\r\n\r\n :host([dense]) .content {\r\n padding-block: var(--sky-space-1, 4px);\r\n }\r\n\r\n .title-area {\r\n flex: 1 1 auto;\r\n min-width: 0;\r\n padding-inline-start: var(--sky-space-2\\\\.5, 10px);\r\n }\r\n\r\n .title-text {\r\n font: var(--sky-text-title);\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n }\r\n\r\n .leading {\r\n display: flex;\r\n align-items: center;\r\n flex-shrink: 0;\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n }\r\n\r\n .leading ::slotted(*) {\r\n cursor: pointer;\r\n }\r\n\r\n .leading-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin: 0;\r\n padding: 0;\r\n border: none;\r\n background: none;\r\n cursor: pointer;\r\n font: inherit;\r\n color: inherit;\r\n -webkit-tap-highlight-color: transparent;\r\n min-width: var(--sky-touch-target, 44px);\r\n min-height: var(--sky-touch-target, 44px);\r\n box-sizing: border-box;\r\n border-radius: var(--sky-radius-primary);\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n transition: var(--sky-transition-fast);\r\n }\r\n\r\n .leading-button:hover {\r\n background: var(--sky-hover-primary);\r\n }\r\n\r\n .leading-button:focus-visible,\r\n .leading ::slotted(*:focus-visible),\r\n .actions ::slotted(*:focus-visible) {\r\n outline: none;\r\n box-shadow: var(--sky-focus-ring);\r\n }\r\n\r\n .icon {\r\n cursor: pointer;\r\n font-size: var(--sky-font-size-xl, 1.25rem);\r\n display: flex;\r\n align-items: center;\r\n }\r\n\r\n .actions {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--sky-space-2, 8px);\r\n padding-inline-start: var(--sky-space-2\\\\.5, 10px);\r\n flex-shrink: 0;\r\n backdrop-filter: none;\r\n -webkit-backdrop-filter: none;\r\n }\r\n\r\n .actions ::slotted(button),\r\n .actions ::slotted([role=\"button\"]) {\r\n min-width: var(--sky-touch-target, 44px);\r\n min-height: var(--sky-touch-target, 44px);\r\n box-sizing: border-box;\r\n }\r\n\r\n :host-context([dir=\"rtl\"]) .leading-button .icon {\r\n transform: scaleX(-1);\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n :host,\r\n .content,\r\n .leading-button,\r\n .leading ::slotted(*),\r\n .actions ::slotted(*) {\r\n transition: none;\r\n }\r\n\r\n :host-context([dir=\"rtl\"]) .leading-button .icon {\r\n transform: none;\r\n }\r\n }\r\n\r\n ${unsafeCSS(\r\n cssOnFillEnhance([\r\n {\r\n selector: ':host([data-surface=\"solid\"])',\r\n fillVar: \"--appbar-bg-color\",\r\n },\r\n ]),\r\n )}\r\n `;\r\n\r\n /** Applies glass vs solid surface tokens from `color`. */\r\n private _applyColorSurface(): void {\r\n if (!isDefaultColorToken(this.color)) {\r\n this.setAttribute(\"data-surface\", \"solid\");\r\n this.style.setProperty(\"--appbar-bg-color\", resolveColor(this.color));\r\n this.style.setProperty(\"--appbar-text-color\", ON_COLOR_FALLBACK_LIGHT);\r\n return;\r\n }\r\n\r\n this.removeAttribute(\"data-surface\");\r\n this.style.removeProperty(\"--appbar-bg-color\");\r\n this.style.removeProperty(\"--appbar-text-color\");\r\n }\r\n\r\n override connectedCallback(): void {\r\n super.connectedCallback();\r\n this._applyColorSurface();\r\n this._applyBackgroundImage();\r\n }\r\n\r\n /** Sets background image CSS variable from `url`. */\r\n private _applyBackgroundImage(): void {\r\n const image = this.url ? `url(${this.url})` : \"none\";\r\n this.style.setProperty(\"--appbar-bg-image\", image);\r\n }\r\n\r\n /** Updates host style variables when visual input properties change. */\r\n protected override updated(changedProperties: PropertyValues): void {\r\n if (changedProperties.has(\"color\")) {\r\n this._applyColorSurface();\r\n }\r\n\r\n if (changedProperties.has(\"url\")) {\r\n this._applyBackgroundImage();\r\n }\r\n }\r\n\r\n override render() {\r\n return html`\r\n ${this.url\r\n ? html`\r\n <div class=\"background\" aria-hidden=\"true\"></div>\r\n <div class=\"background-overlay\" aria-hidden=\"true\"></div>\r\n `\r\n : nothing}\r\n <div\r\n class=\"content\"\r\n part=\"content\"\r\n role=\"${this.banner ? \"banner\" : \"group\"}\"\r\n >\r\n <div class=\"leading\" part=\"leading\">\r\n <slot name=\"button\">\r\n <button\r\n type=\"button\"\r\n class=\"leading-button\"\r\n aria-label=\"${this.leadingLabel}\"\r\n >\r\n <sky-icon class=\"icon\" icon=\"mdi:menu\"></sky-icon>\r\n </button>\r\n </slot>\r\n </div>\r\n <div class=\"title-area\" part=\"title\">\r\n <span class=\"title-text\">${this.title}</span>\r\n </div>\r\n <div class=\"actions\" part=\"actions\">\r\n <slot></slot>\r\n </div>\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"names":["SkyAppbar","LitElement","constructor","super","arguments","this","title","color","url","banner","dense","elevated","leadingLabel","preset","_presets","PresetController","_applyColorSurface","isDefaultColorToken","setAttribute","style","setProperty","resolveColor","ON_COLOR_FALLBACK_LIGHT","removeAttribute","removeProperty","connectedCallback","_applyBackgroundImage","image","updated","changedProperties","has","render","html","nothing","dependencies","SkyIcon","styles","css","unsafeCSS","cssOnFillEnhance","selector","fillVar","__decorateClass","property","type","String","prototype","Boolean","reflect","customElement"],"mappings":"4oBAwEO,IAAMA,EAAN,cAAwBC,EAAxB,WAAAC,GAAAC,SAAAC,WAOuBC,KAAAC,MAAQ,UAORD,KAAAE,MAAQ,UAGRF,KAAAG,IAAM,GAGLH,KAAAI,QAAS,EAGTJ,KAAAK,OAAQ,EAGRL,KAAAM,UAAW,EAGZN,KAAAO,aAAe,YAIAP,KAAAQ,OAAS,GAEpDR,KAAQS,SAAW,IAAIC,EAAiBV,KAAI,CAsMpC,kBAAAW,GACN,IAAKC,EAAoBZ,KAAKE,OAI5B,OAHAF,KAAKa,aAAa,eAAgB,SAClCb,KAAKc,MAAMC,YAAY,oBAAqBC,EAAahB,KAAKE,aAC9DF,KAAKc,MAAMC,YAAY,sBAAuBE,GAIhDjB,KAAKkB,gBAAgB,gBACrBlB,KAAKc,MAAMK,eAAe,qBAC1BnB,KAAKc,MAAMK,eAAe,sBAC5B,CAES,iBAAAC,GACPtB,MAAMsB,oBACNpB,KAAKW,qBACLX,KAAKqB,uBACP,CAGQ,qBAAAA,GACN,MAAMC,EAAQtB,KAAKG,IAAM,OAAOH,KAAKG,OAAS,OAC9CH,KAAKc,MAAMC,YAAY,oBAAqBO,EAC9C,CAGmB,OAAAC,CAAQC,GACrBA,EAAkBC,IAAI,UACxBzB,KAAKW,qBAGHa,EAAkBC,IAAI,QACxBzB,KAAKqB,uBAET,CAES,MAAAK,GACP,OAAOC,CAAA;QACH3B,KAAKG,IACHwB,CAAA;;;YAIAC;;;;gBAIM5B,KAAKI,OAAS,SAAW;;;;;;;4BAObJ,KAAKO;;;;;;;qCAOIP,KAAKC;;;;;;KAOxC,GA7SWN,EAEJkC,aAAyD,CAC9D,WAAYC,GAHHnC,EAqCKoC,OAASC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAyLrBC,EACAC,EAAiB,CACf,CACEC,SAAU,gCACVC,QAAS;IA3NWC,EAAA,CAA3BC,EAAS,CAAEC,KAAMC,UAPP7C,EAOiB8C,UAAA,QAAA,GAOAJ,EAAA,CAA3BC,EAAS,CAAEC,KAAMC,UAdP7C,EAciB8C,UAAA,QAAA,GAGAJ,EAAA,CAA3BC,EAAS,CAAEC,KAAMC,UAjBP7C,EAiBiB8C,UAAA,MAAA,GAGCJ,EAAA,CAA5BC,EAAS,CAAEC,KAAMG,WApBP/C,EAoBkB8C,UAAA,SAAA,GAGAJ,EAAA,CAA5BC,EAAS,CAAEC,KAAMG,WAvBP/C,EAuBkB8C,UAAA,QAAA,GAGAJ,EAAA,CAA5BC,EAAS,CAAEC,KAAMG,WA1BP/C,EA0BkB8C,UAAA,WAAA,GAGDJ,EAAA,CAA3BC,EAAS,CAAEC,KAAMC,UA7BP7C,EA6BiB8C,UAAA,eAAA,GAIeJ,EAAA,CAA1CC,EAAS,CAAEC,KAAMC,OAAQG,SAAS,KAjCxBhD,EAiCgC8C,UAAA,SAAA,GAjChC9C,EAAN0C,EAAA,CADNO,EAAc,eACFjD"}
@@ -8,7 +8,7 @@ export type SkyAvatarFit = "cover" | "contain";
8
8
  * @status stable
9
9
  * @since 1.0.0
10
10
  *
11
- * @documentation https://library.sky-ui.com/components/avatar
11
+ * @documentation https://sky-ui.com/components/avatar
12
12
  *
13
13
  * @slot - Fallback content (e.g., initials or an icon) rendered when `image` is empty.
14
14
  *
@@ -24,6 +24,7 @@ export type SkyAvatarFit = "cover" | "contain";
24
24
  * @property {boolean} disabled - Dims and disables pointer interactions.
25
25
  * @property {boolean} interactive - Enables interactive behavior with keyboard/click activation.
26
26
  * @property {boolean} shadow - When true, applies solid surface, border ring, and elevation; no backdrop blur.
27
+ * @property {string} preset - Named prop preset from nearest `sky-config-provider`. Default: `""`.
27
28
  *
28
29
  * @csspart avatar - The avatar container element.
29
30
  * @csspart loading-overlay - The loading overlay container (shown when `loading` is true).
@@ -88,6 +89,9 @@ export declare class SkyAvatar extends LitElement {
88
89
  shadow: boolean;
89
90
  /** True when image failed to load; show slot instead. */
90
91
  private _imageError;
92
+ /** Named prop preset from nearest `sky-config-provider`. */
93
+ preset: string;
94
+ private _presets;
91
95
  static styles: import("lit").CSSResult;
92
96
  updated(changed: PropertyValues): void;
93
97
  /** Marks image load success and keeps image rendering active. */