@lifecorner/angular-ui-kit 3.25.1 → 3.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/fesm2022/lifecorner-angular-ui-kit-button.mjs +18 -2
  2. package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -1
  3. package/fesm2022/lifecorner-angular-ui-kit-callout.mjs +2 -2
  4. package/fesm2022/lifecorner-angular-ui-kit-callout.mjs.map +1 -1
  5. package/fesm2022/lifecorner-angular-ui-kit-chat.mjs +2 -2
  6. package/fesm2022/lifecorner-angular-ui-kit-chat.mjs.map +1 -1
  7. package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs +1 -0
  8. package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs.map +1 -1
  9. package/fesm2022/lifecorner-angular-ui-kit-color-picker.mjs +2 -2
  10. package/fesm2022/lifecorner-angular-ui-kit-color-picker.mjs.map +1 -1
  11. package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs +1 -0
  12. package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs.map +1 -1
  13. package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs +1 -0
  14. package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs.map +1 -1
  15. package/fesm2022/lifecorner-angular-ui-kit-date-range-picker.mjs +2 -2
  16. package/fesm2022/lifecorner-angular-ui-kit-date-range-picker.mjs.map +1 -1
  17. package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs +2 -2
  18. package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs.map +1 -1
  19. package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs +47 -9
  20. package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs.map +1 -1
  21. package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs +2 -2
  22. package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs.map +1 -1
  23. package/fesm2022/lifecorner-angular-ui-kit-document-viewer.mjs +2 -2
  24. package/fesm2022/lifecorner-angular-ui-kit-document-viewer.mjs.map +1 -1
  25. package/fesm2022/lifecorner-angular-ui-kit-file-upload.mjs +8 -4
  26. package/fesm2022/lifecorner-angular-ui-kit-file-upload.mjs.map +1 -1
  27. package/fesm2022/lifecorner-angular-ui-kit-filter-bar.mjs +2 -2
  28. package/fesm2022/lifecorner-angular-ui-kit-filter-bar.mjs.map +1 -1
  29. package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs +2 -2
  30. package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs.map +1 -1
  31. package/fesm2022/lifecorner-angular-ui-kit-gantt-chart.mjs +2 -2
  32. package/fesm2022/lifecorner-angular-ui-kit-gantt-chart.mjs.map +1 -1
  33. package/fesm2022/lifecorner-angular-ui-kit-header.mjs +3 -2
  34. package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
  35. package/fesm2022/lifecorner-angular-ui-kit-input.mjs +2 -2
  36. package/fesm2022/lifecorner-angular-ui-kit-input.mjs.map +1 -1
  37. package/fesm2022/lifecorner-angular-ui-kit-kanban-board.mjs +2 -2
  38. package/fesm2022/lifecorner-angular-ui-kit-kanban-board.mjs.map +1 -1
  39. package/fesm2022/lifecorner-angular-ui-kit-list.mjs +1 -0
  40. package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
  41. package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs +2 -2
  42. package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs.map +1 -1
  43. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +1 -0
  44. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -1
  45. package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs +2 -2
  46. package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs.map +1 -1
  47. package/fesm2022/lifecorner-angular-ui-kit-number-input.mjs +2 -2
  48. package/fesm2022/lifecorner-angular-ui-kit-number-input.mjs.map +1 -1
  49. package/fesm2022/lifecorner-angular-ui-kit-rich-text-editor.mjs +2 -2
  50. package/fesm2022/lifecorner-angular-ui-kit-rich-text-editor.mjs.map +1 -1
  51. package/fesm2022/lifecorner-angular-ui-kit-scatter-plot.mjs +2 -2
  52. package/fesm2022/lifecorner-angular-ui-kit-scatter-plot.mjs.map +1 -1
  53. package/fesm2022/lifecorner-angular-ui-kit-search-input.mjs +2 -2
  54. package/fesm2022/lifecorner-angular-ui-kit-search-input.mjs.map +1 -1
  55. package/fesm2022/lifecorner-angular-ui-kit-select.mjs +2 -2
  56. package/fesm2022/lifecorner-angular-ui-kit-select.mjs.map +1 -1
  57. package/fesm2022/lifecorner-angular-ui-kit-split-pane.mjs +2 -2
  58. package/fesm2022/lifecorner-angular-ui-kit-split-pane.mjs.map +1 -1
  59. package/fesm2022/lifecorner-angular-ui-kit-table.mjs +3 -2
  60. package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
  61. package/fesm2022/lifecorner-angular-ui-kit-tabs.mjs +2 -2
  62. package/fesm2022/lifecorner-angular-ui-kit-tabs.mjs.map +1 -1
  63. package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs +2 -2
  64. package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs.map +1 -1
  65. package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs +2 -2
  66. package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs.map +1 -1
  67. package/fesm2022/lifecorner-angular-ui-kit-toggle-group.mjs +2 -2
  68. package/fesm2022/lifecorner-angular-ui-kit-toggle-group.mjs.map +1 -1
  69. package/package.json +1 -1
  70. package/src/styles/_reset.scss +4 -2
  71. package/src/styles/focus-indicators.spec.ts +199 -0
  72. package/types/lifecorner-angular-ui-kit-button.d.ts +20 -0
  73. package/types/lifecorner-angular-ui-kit-dependency-viewer.d.ts +33 -4
  74. package/types/lifecorner-angular-ui-kit-description-list.d.ts +4 -0
  75. package/types/lifecorner-angular-ui-kit-file-upload.d.ts +11 -1
@@ -1 +1 @@
1
- {"version":3,"file":"lifecorner-angular-ui-kit-scatter-plot.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/scatter-plot/scatter-plot.component.ts","../../../../libs/angular-ui-kit/src/lib/scatter-plot/scatter-plot.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n input,\n computed,\n signal,\n output,\n} from '@angular/core';\nimport { chartColor } from '@lifecorner/angular-ui-kit/internal/chart';\nimport {\n ChartValueFormatter,\n formatChartValue,\n niceScale,\n toFinite,\n} from '@lifecorner/angular-ui-kit/internal/chart';\n\nexport interface ScatterPoint {\n x: number;\n y: number;\n label?: string;\n size?: number;\n}\n\nexport interface ScatterSeries {\n label: string;\n data: ScatterPoint[];\n color?: string;\n}\n\n/** Approximate glyph width of the 10px tooltip font, used to size its backplate. */\nconst TOOLTIP_CHAR_W = 6;\nconst TOOLTIP_PAD_X = 8;\nconst TOOLTIP_H = 18;\n\n@Component({\n selector: 'lc-scatter-plot',\n standalone: true,\n templateUrl: './scatter-plot.component.html',\n styleUrls: ['./scatter-plot.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Scatter plot for visualizing correlations between two variables.\n *\n * Features:\n * - Multiple data series with automatic color assignment\n * - Variable dot sizes for bubble-chart style (`size` on data points)\n * - Configurable axis labels (X / Y) and grid on a nice tick scale\n * - Interactive dots: hover/focus tooltip, click and Enter/Space emit `pointClick`\n * - Optional legend for multi-series data\n *\n * @example\n * ```html\n * <lc-scatter-plot [series]=\"data\" xAxisLabel=\"Weight\" yAxisLabel=\"Height\" (pointClick)=\"select($event)\" />\n * ```\n */\nexport class ScatterPlotComponent {\n readonly series = input.required<ScatterSeries[]>();\n /** Chart width in pixels (fixed; the SVG is not fluid). */\n readonly width = input(400);\n /** Chart height in pixels. */\n readonly height = input(300);\n readonly showGrid = input(true);\n readonly showXLabels = input(true);\n readonly showYLabels = input(true);\n readonly showLegend = input(false);\n readonly showTooltip = input(true);\n readonly dotRadius = input(4);\n readonly xAxisLabel = input('');\n readonly yAxisLabel = input('');\n /**\n * Whether the dots are interactive: keyboard-focusable buttons that show\n * the tooltip on focus and emit `pointClick` on click / Enter / Space. When\n * false the chart is a static image (`role=\"img\"`).\n */\n readonly interactive = input(true);\n /** Formats axis ticks and the default point label. Defaults to a float-safe `String(value)`. */\n readonly formatValue = input<ChartValueFormatter>(formatChartValue);\n /**\n * Accessible name of the chart. Defaults to a generated summary naming the\n * axes and each series with its point count.\n */\n readonly ariaLabel = input<string>('');\n\n readonly pointClick = output<{ series: string; point: ScatterPoint }>();\n\n /** Tooltip: label, backplate centre x / top y and width (SVG units). */\n protected hoveredPoint = signal<{ label: string; sx: number; ty: number; w: number } | null>(null);\n\n private readonly PL = 48;\n private readonly PR = 16;\n private readonly PT = 16;\n private readonly PB = 36;\n\n protected readonly viewBox = computed(() => `0 0 ${this.width()} ${this.height()}`);\n\n private readonly cleanSeries = computed(() =>\n (this.series() ?? []).map((ser) => ({\n ...ser,\n data: (ser.data ?? []).map((p) => ({ ...p, x: toFinite(p.x), y: toFinite(p.y) })),\n }))\n );\n\n private readonly allPoints = computed(() => this.cleanSeries().flatMap(s => s.data));\n\n /** Nice tick scale over the data extent, padded 5% so edge points don't sit on the axis. */\n private extent(values: number[]) {\n if (!values.length) return niceScale(0, 1, 5);\n const min = Math.min(...values);\n const max = Math.max(...values);\n const pad = (max - min) * 0.05 || 0.5;\n return niceScale(min - pad, max + pad, 5);\n }\n\n private readonly xScale = computed(() => this.extent(this.allPoints().map(p => p.x)));\n private readonly yScale = computed(() => this.extent(this.allPoints().map(p => p.y)));\n\n protected readonly plotArea = computed(() => ({\n x: this.PL,\n y: this.PT,\n w: this.width() - this.PL - this.PR,\n h: this.height() - this.PT - this.PB,\n }));\n\n private toSx(x: number): number {\n const { min, max } = this.xScale();\n const pa = this.plotArea();\n return pa.x + ((x - min) / (max - min || 1)) * pa.w;\n }\n\n private toSy(y: number): number {\n const { min, max } = this.yScale();\n const pa = this.plotArea();\n return pa.y + pa.h - ((y - min) / (max - min || 1)) * pa.h;\n }\n\n protected readonly gridLinesX = computed(() => {\n if (!this.showGrid()) return [];\n const fmt = this.formatValue();\n return this.xScale().ticks.map((tick) => ({ x: this.toSx(tick), label: fmt(tick) }));\n });\n\n protected readonly gridLinesY = computed(() => {\n if (!this.showGrid()) return [];\n const fmt = this.formatValue();\n return this.yScale().ticks.map((tick) => ({ y: this.toSy(tick), label: fmt(tick) }));\n });\n\n protected readonly renderedSeries = computed(() => {\n const dr = this.dotRadius();\n const fmt = this.formatValue();\n\n return this.cleanSeries().map((ser, si) => {\n const color = ser.color || chartColor(si);\n const points = ser.data.map(p => {\n const coords = `(${fmt(p.x)}, ${fmt(p.y)})`;\n const label = p.label || coords;\n return {\n cx: this.toSx(p.x),\n cy: this.toSy(p.y),\n r: Math.max(0, toFinite(p.size, dr)),\n label,\n ariaLabel: `${ser.label}: ${p.label ? `${p.label} ${coords}` : coords}`,\n orig: p,\n };\n });\n return { label: ser.label, color, points };\n });\n });\n\n protected readonly legendItems = computed(() => {\n if (!this.showLegend()) return [];\n return this.renderedSeries().map(s => ({ label: s.label, color: s.color }));\n });\n\n protected readonly axisLine = computed(() => {\n const pa = this.plotArea();\n return {\n vx1: pa.x, vy1: pa.y, vx2: pa.x, vy2: pa.y + pa.h,\n hx1: pa.x, hy1: pa.y + pa.h, hx2: pa.x + pa.w, hy2: pa.y + pa.h,\n };\n });\n\n protected readonly effectiveAriaLabel = computed(() => {\n const explicit = this.ariaLabel();\n if (explicit) return explicit;\n const series = this.cleanSeries();\n const xl = this.xAxisLabel();\n const yl = this.yAxisLabel();\n const axes = xl || yl ? ` (${xl || 'x'} vs ${yl || 'y'})` : '';\n if (!series.length) return `Scatter plot${axes}: no data`;\n const parts = series.map((s, i) => {\n const n = s.data.length;\n return `${s.label || `Series ${i + 1}`} ${n} ${n === 1 ? 'point' : 'points'}`;\n });\n return `Scatter plot${axes}: ${parts.join(', ')}`;\n });\n\n protected onDotEnter(cx: number, cy: number, label: string): void {\n if (!this.showTooltip()) return;\n // Size the backplate from the label and keep it inside the SVG: clamped\n // horizontally, flipped below the dot when there is no room above it.\n const w = label.length * TOOLTIP_CHAR_W + TOOLTIP_PAD_X * 2;\n const half = w / 2;\n const sx = Math.min(Math.max(cx, half), this.width() - half);\n const above = cy - 12 - TOOLTIP_H;\n this.hoveredPoint.set({ label, sx, ty: above < 0 ? cy + 12 : above, w });\n }\n\n protected onDotLeave(): void {\n this.hoveredPoint.set(null);\n }\n\n protected onDotClick(seriesLabel: string, point: ScatterPoint): void {\n this.pointClick.emit({ series: seriesLabel, point });\n }\n\n protected readonly tooltipH = TOOLTIP_H;\n}\n","<div class=\"lc-scatter-plot\">\n <svg\n [attr.width]=\"width()\"\n [attr.height]=\"height()\"\n [attr.viewBox]=\"viewBox()\"\n [attr.role]=\"interactive() ? 'group' : 'img'\"\n [attr.aria-label]=\"effectiveAriaLabel()\"\n class=\"lc-scatter-plot__svg\"\n >\n <title>{{ effectiveAriaLabel() }}</title>\n\n <!-- Grid, axes and tick labels are decoration for AT; the summary carries the meaning. -->\n <g aria-hidden=\"true\">\n <!-- Grid lines Y -->\n @for (line of gridLinesY(); track line.y) {\n <line\n [attr.x1]=\"axisLine().hx1\"\n [attr.y1]=\"line.y\"\n [attr.x2]=\"axisLine().hx2\"\n [attr.y2]=\"line.y\"\n class=\"lc-scatter-plot__grid-line\"\n />\n @if (showYLabels()) {\n <text\n [attr.x]=\"axisLine().vx1 - 6\"\n [attr.y]=\"line.y\"\n text-anchor=\"end\"\n dominant-baseline=\"central\"\n class=\"lc-scatter-plot__label\"\n >{{ line.label }}</text>\n }\n }\n\n <!-- Grid lines X -->\n @for (line of gridLinesX(); track line.x) {\n <line\n [attr.x1]=\"line.x\"\n [attr.y1]=\"axisLine().vy1\"\n [attr.x2]=\"line.x\"\n [attr.y2]=\"axisLine().vy2\"\n class=\"lc-scatter-plot__grid-line\"\n />\n @if (showXLabels()) {\n <!-- Tick labels sit just under the plot; the axis title takes the last line of\n the bottom padding, so the two never overlap. -->\n <text\n [attr.x]=\"line.x\"\n [attr.y]=\"plotArea().y + plotArea().h + 14\"\n text-anchor=\"middle\"\n class=\"lc-scatter-plot__label\"\n >{{ line.label }}</text>\n }\n }\n\n <!-- Axes -->\n <line [attr.x1]=\"axisLine().vx1\" [attr.y1]=\"axisLine().vy1\" [attr.x2]=\"axisLine().vx2\" [attr.y2]=\"axisLine().vy2\" class=\"lc-scatter-plot__axis\" />\n <line [attr.x1]=\"axisLine().hx1\" [attr.y1]=\"axisLine().hy1\" [attr.x2]=\"axisLine().hx2\" [attr.y2]=\"axisLine().hy2\" class=\"lc-scatter-plot__axis\" />\n\n <!-- Axis labels -->\n @if (xAxisLabel()) {\n <text [attr.x]=\"plotArea().x + plotArea().w / 2\" [attr.y]=\"height() - 3\" text-anchor=\"middle\" class=\"lc-scatter-plot__axis-label\">{{ xAxisLabel() }}</text>\n }\n @if (yAxisLabel()) {\n <text [attr.x]=\"12\" [attr.y]=\"plotArea().y + plotArea().h / 2\" text-anchor=\"middle\" [attr.transform]=\"'rotate(-90, 12, ' + (plotArea().y + plotArea().h / 2) + ')'\" class=\"lc-scatter-plot__axis-label\">{{ yAxisLabel() }}</text>\n }\n </g>\n\n <!-- Series dots -->\n @for (ser of renderedSeries(); track $index) {\n @for (pt of ser.points; track $index) {\n <circle\n [attr.cx]=\"pt.cx\"\n [attr.cy]=\"pt.cy\"\n [attr.r]=\"pt.r\"\n [attr.fill]=\"ser.color\"\n class=\"lc-scatter-plot__dot\"\n [class.lc-scatter-plot__dot--interactive]=\"interactive()\"\n [attr.tabindex]=\"interactive() ? 0 : null\"\n [attr.role]=\"interactive() ? 'button' : null\"\n [attr.aria-label]=\"interactive() ? pt.ariaLabel : null\"\n (mouseenter)=\"onDotEnter(pt.cx, pt.cy, pt.label)\"\n (mouseleave)=\"onDotLeave()\"\n (focus)=\"onDotEnter(pt.cx, pt.cy, pt.label)\"\n (blur)=\"onDotLeave()\"\n (click)=\"onDotClick(ser.label, pt.orig)\"\n (keydown.enter)=\"onDotClick(ser.label, pt.orig)\"\n (keydown.space)=\"$event.preventDefault(); onDotClick(ser.label, pt.orig)\"\n />\n }\n }\n\n <!-- Tooltip -->\n @if (hoveredPoint(); as hp) {\n <g class=\"lc-scatter-plot__tooltip\" aria-hidden=\"true\">\n <rect\n [attr.x]=\"hp.sx - hp.w / 2\"\n [attr.y]=\"hp.ty\"\n [attr.width]=\"hp.w\"\n [attr.height]=\"tooltipH\"\n rx=\"4\"\n class=\"lc-scatter-plot__tooltip-bg\"\n />\n <text\n [attr.x]=\"hp.sx\"\n [attr.y]=\"hp.ty + tooltipH / 2\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"lc-scatter-plot__tooltip-text\"\n >{{ hp.label }}</text>\n </g>\n }\n </svg>\n\n @if (legendItems().length) {\n <div class=\"lc-scatter-plot__legend\">\n @for (item of legendItems(); track $index) {\n <div class=\"lc-scatter-plot__legend-item\">\n <span class=\"lc-scatter-plot__legend-dot\" [style.background-color]=\"item.color\"></span>\n <span class=\"lc-scatter-plot__legend-label\">{{ item.label }}</span>\n </div>\n }\n </div>\n }\n</div>\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-scatter-plot.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/scatter-plot/scatter-plot.component.ts","../../../../libs/angular-ui-kit/src/lib/scatter-plot/scatter-plot.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n input,\n computed,\n signal,\n output,\n} from '@angular/core';\nimport { chartColor } from '@lifecorner/angular-ui-kit/internal/chart';\nimport {\n ChartValueFormatter,\n formatChartValue,\n niceScale,\n toFinite,\n} from '@lifecorner/angular-ui-kit/internal/chart';\n\nexport interface ScatterPoint {\n x: number;\n y: number;\n label?: string;\n size?: number;\n}\n\nexport interface ScatterSeries {\n label: string;\n data: ScatterPoint[];\n color?: string;\n}\n\n/** Approximate glyph width of the 10px tooltip font, used to size its backplate. */\nconst TOOLTIP_CHAR_W = 6;\nconst TOOLTIP_PAD_X = 8;\nconst TOOLTIP_H = 18;\n\n@Component({\n selector: 'lc-scatter-plot',\n standalone: true,\n templateUrl: './scatter-plot.component.html',\n styleUrls: ['./scatter-plot.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Scatter plot for visualizing correlations between two variables.\n *\n * Features:\n * - Multiple data series with automatic color assignment\n * - Variable dot sizes for bubble-chart style (`size` on data points)\n * - Configurable axis labels (X / Y) and grid on a nice tick scale\n * - Interactive dots: hover/focus tooltip, click and Enter/Space emit `pointClick`\n * - Optional legend for multi-series data\n *\n * @example\n * ```html\n * <lc-scatter-plot [series]=\"data\" xAxisLabel=\"Weight\" yAxisLabel=\"Height\" (pointClick)=\"select($event)\" />\n * ```\n */\nexport class ScatterPlotComponent {\n readonly series = input.required<ScatterSeries[]>();\n /** Chart width in pixels (fixed; the SVG is not fluid). */\n readonly width = input(400);\n /** Chart height in pixels. */\n readonly height = input(300);\n readonly showGrid = input(true);\n readonly showXLabels = input(true);\n readonly showYLabels = input(true);\n readonly showLegend = input(false);\n readonly showTooltip = input(true);\n readonly dotRadius = input(4);\n readonly xAxisLabel = input('');\n readonly yAxisLabel = input('');\n /**\n * Whether the dots are interactive: keyboard-focusable buttons that show\n * the tooltip on focus and emit `pointClick` on click / Enter / Space. When\n * false the chart is a static image (`role=\"img\"`).\n */\n readonly interactive = input(true);\n /** Formats axis ticks and the default point label. Defaults to a float-safe `String(value)`. */\n readonly formatValue = input<ChartValueFormatter>(formatChartValue);\n /**\n * Accessible name of the chart. Defaults to a generated summary naming the\n * axes and each series with its point count.\n */\n readonly ariaLabel = input<string>('');\n\n readonly pointClick = output<{ series: string; point: ScatterPoint }>();\n\n /** Tooltip: label, backplate centre x / top y and width (SVG units). */\n protected hoveredPoint = signal<{ label: string; sx: number; ty: number; w: number } | null>(null);\n\n private readonly PL = 48;\n private readonly PR = 16;\n private readonly PT = 16;\n private readonly PB = 36;\n\n protected readonly viewBox = computed(() => `0 0 ${this.width()} ${this.height()}`);\n\n private readonly cleanSeries = computed(() =>\n (this.series() ?? []).map((ser) => ({\n ...ser,\n data: (ser.data ?? []).map((p) => ({ ...p, x: toFinite(p.x), y: toFinite(p.y) })),\n }))\n );\n\n private readonly allPoints = computed(() => this.cleanSeries().flatMap(s => s.data));\n\n /** Nice tick scale over the data extent, padded 5% so edge points don't sit on the axis. */\n private extent(values: number[]) {\n if (!values.length) return niceScale(0, 1, 5);\n const min = Math.min(...values);\n const max = Math.max(...values);\n const pad = (max - min) * 0.05 || 0.5;\n return niceScale(min - pad, max + pad, 5);\n }\n\n private readonly xScale = computed(() => this.extent(this.allPoints().map(p => p.x)));\n private readonly yScale = computed(() => this.extent(this.allPoints().map(p => p.y)));\n\n protected readonly plotArea = computed(() => ({\n x: this.PL,\n y: this.PT,\n w: this.width() - this.PL - this.PR,\n h: this.height() - this.PT - this.PB,\n }));\n\n private toSx(x: number): number {\n const { min, max } = this.xScale();\n const pa = this.plotArea();\n return pa.x + ((x - min) / (max - min || 1)) * pa.w;\n }\n\n private toSy(y: number): number {\n const { min, max } = this.yScale();\n const pa = this.plotArea();\n return pa.y + pa.h - ((y - min) / (max - min || 1)) * pa.h;\n }\n\n protected readonly gridLinesX = computed(() => {\n if (!this.showGrid()) return [];\n const fmt = this.formatValue();\n return this.xScale().ticks.map((tick) => ({ x: this.toSx(tick), label: fmt(tick) }));\n });\n\n protected readonly gridLinesY = computed(() => {\n if (!this.showGrid()) return [];\n const fmt = this.formatValue();\n return this.yScale().ticks.map((tick) => ({ y: this.toSy(tick), label: fmt(tick) }));\n });\n\n protected readonly renderedSeries = computed(() => {\n const dr = this.dotRadius();\n const fmt = this.formatValue();\n\n return this.cleanSeries().map((ser, si) => {\n const color = ser.color || chartColor(si);\n const points = ser.data.map(p => {\n const coords = `(${fmt(p.x)}, ${fmt(p.y)})`;\n const label = p.label || coords;\n return {\n cx: this.toSx(p.x),\n cy: this.toSy(p.y),\n r: Math.max(0, toFinite(p.size, dr)),\n label,\n ariaLabel: `${ser.label}: ${p.label ? `${p.label} ${coords}` : coords}`,\n orig: p,\n };\n });\n return { label: ser.label, color, points };\n });\n });\n\n protected readonly legendItems = computed(() => {\n if (!this.showLegend()) return [];\n return this.renderedSeries().map(s => ({ label: s.label, color: s.color }));\n });\n\n protected readonly axisLine = computed(() => {\n const pa = this.plotArea();\n return {\n vx1: pa.x, vy1: pa.y, vx2: pa.x, vy2: pa.y + pa.h,\n hx1: pa.x, hy1: pa.y + pa.h, hx2: pa.x + pa.w, hy2: pa.y + pa.h,\n };\n });\n\n protected readonly effectiveAriaLabel = computed(() => {\n const explicit = this.ariaLabel();\n if (explicit) return explicit;\n const series = this.cleanSeries();\n const xl = this.xAxisLabel();\n const yl = this.yAxisLabel();\n const axes = xl || yl ? ` (${xl || 'x'} vs ${yl || 'y'})` : '';\n if (!series.length) return `Scatter plot${axes}: no data`;\n const parts = series.map((s, i) => {\n const n = s.data.length;\n return `${s.label || `Series ${i + 1}`} ${n} ${n === 1 ? 'point' : 'points'}`;\n });\n return `Scatter plot${axes}: ${parts.join(', ')}`;\n });\n\n protected onDotEnter(cx: number, cy: number, label: string): void {\n if (!this.showTooltip()) return;\n // Size the backplate from the label and keep it inside the SVG: clamped\n // horizontally, flipped below the dot when there is no room above it.\n const w = label.length * TOOLTIP_CHAR_W + TOOLTIP_PAD_X * 2;\n const half = w / 2;\n const sx = Math.min(Math.max(cx, half), this.width() - half);\n const above = cy - 12 - TOOLTIP_H;\n this.hoveredPoint.set({ label, sx, ty: above < 0 ? cy + 12 : above, w });\n }\n\n protected onDotLeave(): void {\n this.hoveredPoint.set(null);\n }\n\n protected onDotClick(seriesLabel: string, point: ScatterPoint): void {\n this.pointClick.emit({ series: seriesLabel, point });\n }\n\n protected readonly tooltipH = TOOLTIP_H;\n}\n","<div class=\"lc-scatter-plot\">\n <svg\n [attr.width]=\"width()\"\n [attr.height]=\"height()\"\n [attr.viewBox]=\"viewBox()\"\n [attr.role]=\"interactive() ? 'group' : 'img'\"\n [attr.aria-label]=\"effectiveAriaLabel()\"\n class=\"lc-scatter-plot__svg\"\n >\n <title>{{ effectiveAriaLabel() }}</title>\n\n <!-- Grid, axes and tick labels are decoration for AT; the summary carries the meaning. -->\n <g aria-hidden=\"true\">\n <!-- Grid lines Y -->\n @for (line of gridLinesY(); track line.y) {\n <line\n [attr.x1]=\"axisLine().hx1\"\n [attr.y1]=\"line.y\"\n [attr.x2]=\"axisLine().hx2\"\n [attr.y2]=\"line.y\"\n class=\"lc-scatter-plot__grid-line\"\n />\n @if (showYLabels()) {\n <text\n [attr.x]=\"axisLine().vx1 - 6\"\n [attr.y]=\"line.y\"\n text-anchor=\"end\"\n dominant-baseline=\"central\"\n class=\"lc-scatter-plot__label\"\n >{{ line.label }}</text>\n }\n }\n\n <!-- Grid lines X -->\n @for (line of gridLinesX(); track line.x) {\n <line\n [attr.x1]=\"line.x\"\n [attr.y1]=\"axisLine().vy1\"\n [attr.x2]=\"line.x\"\n [attr.y2]=\"axisLine().vy2\"\n class=\"lc-scatter-plot__grid-line\"\n />\n @if (showXLabels()) {\n <!-- Tick labels sit just under the plot; the axis title takes the last line of\n the bottom padding, so the two never overlap. -->\n <text\n [attr.x]=\"line.x\"\n [attr.y]=\"plotArea().y + plotArea().h + 14\"\n text-anchor=\"middle\"\n class=\"lc-scatter-plot__label\"\n >{{ line.label }}</text>\n }\n }\n\n <!-- Axes -->\n <line [attr.x1]=\"axisLine().vx1\" [attr.y1]=\"axisLine().vy1\" [attr.x2]=\"axisLine().vx2\" [attr.y2]=\"axisLine().vy2\" class=\"lc-scatter-plot__axis\" />\n <line [attr.x1]=\"axisLine().hx1\" [attr.y1]=\"axisLine().hy1\" [attr.x2]=\"axisLine().hx2\" [attr.y2]=\"axisLine().hy2\" class=\"lc-scatter-plot__axis\" />\n\n <!-- Axis labels -->\n @if (xAxisLabel()) {\n <text [attr.x]=\"plotArea().x + plotArea().w / 2\" [attr.y]=\"height() - 3\" text-anchor=\"middle\" class=\"lc-scatter-plot__axis-label\">{{ xAxisLabel() }}</text>\n }\n @if (yAxisLabel()) {\n <text [attr.x]=\"12\" [attr.y]=\"plotArea().y + plotArea().h / 2\" text-anchor=\"middle\" [attr.transform]=\"'rotate(-90, 12, ' + (plotArea().y + plotArea().h / 2) + ')'\" class=\"lc-scatter-plot__axis-label\">{{ yAxisLabel() }}</text>\n }\n </g>\n\n <!-- Series dots -->\n @for (ser of renderedSeries(); track $index) {\n @for (pt of ser.points; track $index) {\n <circle\n [attr.cx]=\"pt.cx\"\n [attr.cy]=\"pt.cy\"\n [attr.r]=\"pt.r\"\n [attr.fill]=\"ser.color\"\n class=\"lc-scatter-plot__dot\"\n [class.lc-scatter-plot__dot--interactive]=\"interactive()\"\n [attr.tabindex]=\"interactive() ? 0 : null\"\n [attr.role]=\"interactive() ? 'button' : null\"\n [attr.aria-label]=\"interactive() ? pt.ariaLabel : null\"\n (mouseenter)=\"onDotEnter(pt.cx, pt.cy, pt.label)\"\n (mouseleave)=\"onDotLeave()\"\n (focus)=\"onDotEnter(pt.cx, pt.cy, pt.label)\"\n (blur)=\"onDotLeave()\"\n (click)=\"onDotClick(ser.label, pt.orig)\"\n (keydown.enter)=\"onDotClick(ser.label, pt.orig)\"\n (keydown.space)=\"$event.preventDefault(); onDotClick(ser.label, pt.orig)\"\n />\n }\n }\n\n <!-- Tooltip -->\n @if (hoveredPoint(); as hp) {\n <g class=\"lc-scatter-plot__tooltip\" aria-hidden=\"true\">\n <rect\n [attr.x]=\"hp.sx - hp.w / 2\"\n [attr.y]=\"hp.ty\"\n [attr.width]=\"hp.w\"\n [attr.height]=\"tooltipH\"\n rx=\"4\"\n class=\"lc-scatter-plot__tooltip-bg\"\n />\n <text\n [attr.x]=\"hp.sx\"\n [attr.y]=\"hp.ty + tooltipH / 2\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"lc-scatter-plot__tooltip-text\"\n >{{ hp.label }}</text>\n </g>\n }\n </svg>\n\n @if (legendItems().length) {\n <div class=\"lc-scatter-plot__legend\">\n @for (item of legendItems(); track $index) {\n <div class=\"lc-scatter-plot__legend-item\">\n <span class=\"lc-scatter-plot__legend-dot\" [style.background-color]=\"item.color\"></span>\n <span class=\"lc-scatter-plot__legend-label\">{{ item.label }}</span>\n </div>\n }\n </div>\n }\n</div>\n"],"mappings":"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"}
@@ -161,7 +161,7 @@ var SearchInputComponent = class SearchInputComponent {
161
161
  }],
162
162
  ngImport: i0,
163
163
  template: "<div [class]=\"wrapperClasses()\">\n <lc-icon name=\"magnifying-glass\" class=\"search-input__icon\" [decorative]=\"true\"></lc-icon>\n <input\n #searchInputEl\n type=\"search\"\n class=\"search-input__field\"\n [id]=\"inputId()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n autocomplete=\"off\"\n [attr.aria-label]=\"ariaLabelledBy() ? null : ariaLabel() || 'Search'\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n />\n @if (value()) {\n <button\n type=\"button\"\n class=\"search-input__clear\"\n (click)=\"clear()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n [disabled]=\"disabled()\"\n >\n <lc-icon name=\"x-mark\" class=\"search-input__clear-icon\" [decorative]=\"true\"></lc-icon>\n </button>\n }\n</div>\n",
164
- styles: [":host{display:block;width:100%}.search-input{display:flex;align-items:center;gap:.5rem;width:100%;background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:border-color .15s ease,box-shadow .15s ease}.search-input:hover:not(.search-input--disabled){border-color:var(--color-text-secondary)}.search-input:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 2px #20849733}.search-input--sm{padding:.375rem .625rem;font-size:.8125rem}.search-input--md{padding:.5rem .75rem;font-size:.875rem}.search-input--lg{padding:.625rem 1rem;font-size:1rem}.search-input--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.search-input__icon{flex-shrink:0;color:var(--color-text-tertiary);--icon-size: 1rem}.search-input__field{flex:1;border:none;outline:none;background:transparent;font:inherit;color:var(--color-text-primary);min-width:0}.search-input__field::placeholder{color:var(--color-text-tertiary)}.search-input__field::-webkit-search-cancel-button,.search-input__field::-webkit-search-decoration{-webkit-appearance:none;appearance:none}.search-input__clear{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;border:none;border-radius:50%;background:var(--color-surface-hover);cursor:pointer;padding:0;transition:background .15s ease}.search-input__clear:hover{background:var(--color-border-strong)}.search-input__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.search-input__clear-icon{--icon-size: .75rem;color:var(--color-text-secondary)}\n"],
164
+ styles: [":host{display:block;width:100%}.search-input{display:flex;align-items:center;gap:.5rem;width:100%;background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:border-color .15s ease,box-shadow .15s ease}.search-input:hover:not(.search-input--disabled):not(:focus-within){border-color:var(--color-text-secondary)}.search-input:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 2px #20849733}.search-input--sm{padding:.375rem .625rem;font-size:.8125rem}.search-input--md{padding:.5rem .75rem;font-size:.875rem}.search-input--lg{padding:.625rem 1rem;font-size:1rem}.search-input--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.search-input__icon{flex-shrink:0;color:var(--color-text-tertiary);--icon-size: 1rem}.search-input__field{flex:1;border:none;outline:none;background:transparent;font:inherit;color:var(--color-text-primary);min-width:0}.search-input__field::placeholder{color:var(--color-text-tertiary)}.search-input__field::-webkit-search-cancel-button,.search-input__field::-webkit-search-decoration{-webkit-appearance:none;appearance:none}.search-input__clear{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;border:none;border-radius:50%;background:var(--color-surface-hover);cursor:pointer;padding:0;transition:background .15s ease}.search-input__clear:hover{background:var(--color-border-strong)}.search-input__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.search-input__clear-icon{--icon-size: .75rem;color:var(--color-text-secondary)}\n"],
165
165
  dependencies: [{
166
166
  kind: "component",
167
167
  type: IconComponent,
@@ -194,7 +194,7 @@ i0.ɵɵngDeclareClassMetadata({
194
194
  viewProviders: [ɵprovideKitIcons([ICON_X_MARK, ICON_SEARCH])],
195
195
  changeDetection: ChangeDetectionStrategy.OnPush,
196
196
  template: "<div [class]=\"wrapperClasses()\">\n <lc-icon name=\"magnifying-glass\" class=\"search-input__icon\" [decorative]=\"true\"></lc-icon>\n <input\n #searchInputEl\n type=\"search\"\n class=\"search-input__field\"\n [id]=\"inputId()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n autocomplete=\"off\"\n [attr.aria-label]=\"ariaLabelledBy() ? null : ariaLabel() || 'Search'\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n />\n @if (value()) {\n <button\n type=\"button\"\n class=\"search-input__clear\"\n (click)=\"clear()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n [disabled]=\"disabled()\"\n >\n <lc-icon name=\"x-mark\" class=\"search-input__clear-icon\" [decorative]=\"true\"></lc-icon>\n </button>\n }\n</div>\n",
197
- styles: [":host{display:block;width:100%}.search-input{display:flex;align-items:center;gap:.5rem;width:100%;background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:border-color .15s ease,box-shadow .15s ease}.search-input:hover:not(.search-input--disabled){border-color:var(--color-text-secondary)}.search-input:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 2px #20849733}.search-input--sm{padding:.375rem .625rem;font-size:.8125rem}.search-input--md{padding:.5rem .75rem;font-size:.875rem}.search-input--lg{padding:.625rem 1rem;font-size:1rem}.search-input--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.search-input__icon{flex-shrink:0;color:var(--color-text-tertiary);--icon-size: 1rem}.search-input__field{flex:1;border:none;outline:none;background:transparent;font:inherit;color:var(--color-text-primary);min-width:0}.search-input__field::placeholder{color:var(--color-text-tertiary)}.search-input__field::-webkit-search-cancel-button,.search-input__field::-webkit-search-decoration{-webkit-appearance:none;appearance:none}.search-input__clear{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;border:none;border-radius:50%;background:var(--color-surface-hover);cursor:pointer;padding:0;transition:background .15s ease}.search-input__clear:hover{background:var(--color-border-strong)}.search-input__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.search-input__clear-icon{--icon-size: .75rem;color:var(--color-text-secondary)}\n"]
197
+ styles: [":host{display:block;width:100%}.search-input{display:flex;align-items:center;gap:.5rem;width:100%;background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:border-color .15s ease,box-shadow .15s ease}.search-input:hover:not(.search-input--disabled):not(:focus-within){border-color:var(--color-text-secondary)}.search-input:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 2px #20849733}.search-input--sm{padding:.375rem .625rem;font-size:.8125rem}.search-input--md{padding:.5rem .75rem;font-size:.875rem}.search-input--lg{padding:.625rem 1rem;font-size:1rem}.search-input--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.search-input__icon{flex-shrink:0;color:var(--color-text-tertiary);--icon-size: 1rem}.search-input__field{flex:1;border:none;outline:none;background:transparent;font:inherit;color:var(--color-text-primary);min-width:0}.search-input__field::placeholder{color:var(--color-text-tertiary)}.search-input__field::-webkit-search-cancel-button,.search-input__field::-webkit-search-decoration{-webkit-appearance:none;appearance:none}.search-input__clear{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;border:none;border-radius:50%;background:var(--color-surface-hover);cursor:pointer;padding:0;transition:background .15s ease}.search-input__clear:hover{background:var(--color-border-strong)}.search-input__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.search-input__clear-icon{--icon-size: .75rem;color:var(--color-text-secondary)}\n"]
198
198
  }]
199
199
  }],
200
200
  ctorParameters: () => [],
@@ -1 +1 @@
1
- {"version":3,"file":"lifecorner-angular-ui-kit-search-input.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/search-input/search-input.component.ts","../../../../libs/angular-ui-kit/src/lib/search-input/search-input.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n effect,\n input,\n model,\n output,\n computed,\n ElementRef,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_SEARCH, ICON_X_MARK } from '@lifecorner/angular-ui-kit/icons';\nimport { Subject, debounce, distinctUntilChanged, filter, of, timer } from 'rxjs';\n\nexport type SearchInputSize = 'sm' | 'md' | 'lg';\n\n/** A value travelling through the debounce pipe. */\ninterface SearchEmission {\n readonly value: string;\n /** Bypass the debounce (clear button, external writes). */\n readonly immediate: boolean;\n /** Only update the dedupe baseline, never reach `searchChange` (external writes). */\n readonly silent: boolean;\n}\n\nlet nextUniqueId = 0;\n\n/**\n * Search input component with integrated search functionality.\n *\n * Features:\n * - Built-in search icon\n * - Clear button for resetting input\n * - RxJS-based configurable debounce\n * - Multiple size variants (sm, md, lg)\n * - Disabled state support\n * - Submit event on Enter key\n * - Two-way bindable `value` so a parent can preset or reset the query\n *\n * @example\n * ```html\n * <lc-search-input\n * placeholder=\"Search...\"\n * [debounceMs]=\"300\"\n * [(value)]=\"query\"\n * (searchChange)=\"onSearch($event)\"\n * ></lc-search-input>\n * ```\n */\n@Component({\n selector: 'lc-search-input',\n standalone: true,\n imports: [IconComponent],\n viewProviders: [ɵprovideKitIcons([ICON_X_MARK, ICON_SEARCH])],\n templateUrl: './search-input.component.html',\n styleUrls: ['./search-input.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SearchInputComponent {\n /**\n * id of the native input (lets a parent `<label for>` point at it).\n * @default generated\n */\n readonly inputId = input<string>(`lc-search-input-${++nextUniqueId}`);\n\n /**\n * Placeholder text.\n * @default 'Search…'\n */\n placeholder = input<string>('Search…');\n\n /**\n * Size variant.\n * @default 'md'\n */\n size = input<SearchInputSize>('md');\n\n /**\n * Debounce delay in milliseconds. 0 means no debounce.\n * @default 300\n */\n debounceMs = input<number>(300);\n\n /**\n * Whether the search input is disabled.\n * @default false\n */\n disabled = input<boolean>(false);\n\n /**\n * Accessible name of the input.\n * @default 'Search'\n */\n readonly ariaLabel = input<string>();\n\n /** id(s) of external element(s) labelling the input (wins over `ariaLabel`). */\n readonly ariaLabelledBy = input<string>();\n\n /** Accessible name of the clear button. */\n readonly clearAriaLabel = input('Clear search');\n\n /**\n * Current query (two-way bindable). Writing it from outside updates the\n * field without emitting `searchChange`; `valueChange` emits on every\n * keystroke (undebounced) and on clear.\n */\n readonly value = model<string>('');\n\n /**\n * Emitted when the search value changes (debounced).\n */\n readonly searchChange = output<string>();\n\n /**\n * Emitted when the user presses Enter.\n */\n readonly searchSubmit = output<string>();\n\n protected readonly inputRef = viewChild<ElementRef<HTMLInputElement>>('searchInputEl');\n\n protected wrapperClasses = computed(() => {\n return [\n 'search-input',\n `search-input--${this.size()}`,\n this.disabled() ? 'search-input--disabled' : '',\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n private readonly input$ = new Subject<SearchEmission>();\n /** Last value pushed into the pipe (by typing, clear or an external write). */\n private lastPushed = '';\n\n constructor() {\n this.input$\n .pipe(\n // debounceMs is read per emission, so changing it takes effect immediately.\n // 0 means \"no debounce\" — emit synchronously rather than on a 0ms timer.\n debounce(({ immediate }) => {\n const ms = this.debounceMs();\n return immediate || ms <= 0 ? of(null) : timer(ms);\n }),\n distinctUntilChanged((a, b) => a.value === b.value),\n filter(({ silent }) => !silent),\n takeUntilDestroyed(),\n )\n .subscribe(({ value }) => this.searchChange.emit(value));\n\n // A value written from outside is already known to the parent: run it through\n // the pipe silently so it becomes the dedupe baseline (and cancels a pending\n // debounce) without echoing a searchChange back.\n effect(() => {\n const value = this.value();\n untracked(() => {\n if (value !== this.lastPushed) {\n this.push(value, { immediate: true, silent: true });\n }\n });\n });\n }\n\n protected onInput(event: Event): void {\n const val = (event.target as HTMLInputElement).value;\n this.value.set(val);\n this.push(val, { immediate: false, silent: false });\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n this.searchSubmit.emit(this.value());\n }\n }\n\n protected clear(): void {\n this.value.set('');\n // immediate: emits '' synchronously through the pipe, exactly once\n this.push('', { immediate: true, silent: false });\n this.inputRef()?.nativeElement.focus();\n }\n\n private push(value: string, opts: Omit<SearchEmission, 'value'>): void {\n this.lastPushed = value;\n this.input$.next({ value, ...opts });\n }\n}\n","<div [class]=\"wrapperClasses()\">\n <lc-icon name=\"magnifying-glass\" class=\"search-input__icon\" [decorative]=\"true\"></lc-icon>\n <input\n #searchInputEl\n type=\"search\"\n class=\"search-input__field\"\n [id]=\"inputId()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n autocomplete=\"off\"\n [attr.aria-label]=\"ariaLabelledBy() ? null : ariaLabel() || 'Search'\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n />\n @if (value()) {\n <button\n type=\"button\"\n class=\"search-input__clear\"\n (click)=\"clear()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n [disabled]=\"disabled()\"\n >\n <lc-icon name=\"x-mark\" class=\"search-input__clear-icon\" [decorative]=\"true\"></lc-icon>\n </button>\n }\n</div>\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-search-input.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/search-input/search-input.component.ts","../../../../libs/angular-ui-kit/src/lib/search-input/search-input.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n effect,\n input,\n model,\n output,\n computed,\n ElementRef,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_SEARCH, ICON_X_MARK } from '@lifecorner/angular-ui-kit/icons';\nimport { Subject, debounce, distinctUntilChanged, filter, of, timer } from 'rxjs';\n\nexport type SearchInputSize = 'sm' | 'md' | 'lg';\n\n/** A value travelling through the debounce pipe. */\ninterface SearchEmission {\n readonly value: string;\n /** Bypass the debounce (clear button, external writes). */\n readonly immediate: boolean;\n /** Only update the dedupe baseline, never reach `searchChange` (external writes). */\n readonly silent: boolean;\n}\n\nlet nextUniqueId = 0;\n\n/**\n * Search input component with integrated search functionality.\n *\n * Features:\n * - Built-in search icon\n * - Clear button for resetting input\n * - RxJS-based configurable debounce\n * - Multiple size variants (sm, md, lg)\n * - Disabled state support\n * - Submit event on Enter key\n * - Two-way bindable `value` so a parent can preset or reset the query\n *\n * @example\n * ```html\n * <lc-search-input\n * placeholder=\"Search...\"\n * [debounceMs]=\"300\"\n * [(value)]=\"query\"\n * (searchChange)=\"onSearch($event)\"\n * ></lc-search-input>\n * ```\n */\n@Component({\n selector: 'lc-search-input',\n standalone: true,\n imports: [IconComponent],\n viewProviders: [ɵprovideKitIcons([ICON_X_MARK, ICON_SEARCH])],\n templateUrl: './search-input.component.html',\n styleUrls: ['./search-input.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SearchInputComponent {\n /**\n * id of the native input (lets a parent `<label for>` point at it).\n * @default generated\n */\n readonly inputId = input<string>(`lc-search-input-${++nextUniqueId}`);\n\n /**\n * Placeholder text.\n * @default 'Search…'\n */\n placeholder = input<string>('Search…');\n\n /**\n * Size variant.\n * @default 'md'\n */\n size = input<SearchInputSize>('md');\n\n /**\n * Debounce delay in milliseconds. 0 means no debounce.\n * @default 300\n */\n debounceMs = input<number>(300);\n\n /**\n * Whether the search input is disabled.\n * @default false\n */\n disabled = input<boolean>(false);\n\n /**\n * Accessible name of the input.\n * @default 'Search'\n */\n readonly ariaLabel = input<string>();\n\n /** id(s) of external element(s) labelling the input (wins over `ariaLabel`). */\n readonly ariaLabelledBy = input<string>();\n\n /** Accessible name of the clear button. */\n readonly clearAriaLabel = input('Clear search');\n\n /**\n * Current query (two-way bindable). Writing it from outside updates the\n * field without emitting `searchChange`; `valueChange` emits on every\n * keystroke (undebounced) and on clear.\n */\n readonly value = model<string>('');\n\n /**\n * Emitted when the search value changes (debounced).\n */\n readonly searchChange = output<string>();\n\n /**\n * Emitted when the user presses Enter.\n */\n readonly searchSubmit = output<string>();\n\n protected readonly inputRef = viewChild<ElementRef<HTMLInputElement>>('searchInputEl');\n\n protected wrapperClasses = computed(() => {\n return [\n 'search-input',\n `search-input--${this.size()}`,\n this.disabled() ? 'search-input--disabled' : '',\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n private readonly input$ = new Subject<SearchEmission>();\n /** Last value pushed into the pipe (by typing, clear or an external write). */\n private lastPushed = '';\n\n constructor() {\n this.input$\n .pipe(\n // debounceMs is read per emission, so changing it takes effect immediately.\n // 0 means \"no debounce\" — emit synchronously rather than on a 0ms timer.\n debounce(({ immediate }) => {\n const ms = this.debounceMs();\n return immediate || ms <= 0 ? of(null) : timer(ms);\n }),\n distinctUntilChanged((a, b) => a.value === b.value),\n filter(({ silent }) => !silent),\n takeUntilDestroyed(),\n )\n .subscribe(({ value }) => this.searchChange.emit(value));\n\n // A value written from outside is already known to the parent: run it through\n // the pipe silently so it becomes the dedupe baseline (and cancels a pending\n // debounce) without echoing a searchChange back.\n effect(() => {\n const value = this.value();\n untracked(() => {\n if (value !== this.lastPushed) {\n this.push(value, { immediate: true, silent: true });\n }\n });\n });\n }\n\n protected onInput(event: Event): void {\n const val = (event.target as HTMLInputElement).value;\n this.value.set(val);\n this.push(val, { immediate: false, silent: false });\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n this.searchSubmit.emit(this.value());\n }\n }\n\n protected clear(): void {\n this.value.set('');\n // immediate: emits '' synchronously through the pipe, exactly once\n this.push('', { immediate: true, silent: false });\n this.inputRef()?.nativeElement.focus();\n }\n\n private push(value: string, opts: Omit<SearchEmission, 'value'>): void {\n this.lastPushed = value;\n this.input$.next({ value, ...opts });\n }\n}\n","<div [class]=\"wrapperClasses()\">\n <lc-icon name=\"magnifying-glass\" class=\"search-input__icon\" [decorative]=\"true\"></lc-icon>\n <input\n #searchInputEl\n type=\"search\"\n class=\"search-input__field\"\n [id]=\"inputId()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n autocomplete=\"off\"\n [attr.aria-label]=\"ariaLabelledBy() ? null : ariaLabel() || 'Search'\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n />\n @if (value()) {\n <button\n type=\"button\"\n class=\"search-input__clear\"\n (click)=\"clear()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n [disabled]=\"disabled()\"\n >\n <lc-icon name=\"x-mark\" class=\"search-input__clear-icon\" [decorative]=\"true\"></lc-icon>\n </button>\n }\n</div>\n"],"mappings":"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"}
@@ -387,7 +387,7 @@ var SelectComponent = class SelectComponent {
387
387
  }],
388
388
  ngImport: i0,
389
389
  template: "<div class=\"lc-select-wrapper\">\n <div\n #selectTrigger\n [class]=\"selectClasses()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n >\n <div class=\"lc-select__value\">\n <span [class.lc-select__placeholder]=\"!selectedLabel()\">\n {{ displayValue() }}\n </span>\n </div>\n\n <div class=\"lc-select__icons\">\n @if (loading()) {\n <svg\n class=\"lc-select__spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n } @else if (value() && !isDisabled() && !multiple()) {\n <button\n type=\"button\"\n class=\"lc-select__clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n\n <svg\n class=\"lc-select__chevron\"\n [class.lc-select__chevron--open]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Dropdown Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"selectTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div #dropdownPanel class=\"lc-select__dropdown\" [class.lc-select__dropdown--open]=\"isOpen()\">\n @if (searchable()) {\n <div class=\"lc-select__search\">\n <input\n type=\"text\"\n class=\"lc-select__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"searchAriaLabel() || (ariaLabel() ? 'Search ' + ariaLabel() : 'Search options')\"\n [(ngModel)]=\"searchQuery\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div\n class=\"lc-select__options\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n >\n @if (filteredOptions().length === 0) {\n <div\n class=\"lc-select__option lc-select__option--no-results\"\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n >\n {{ noOptionsLabel() }}\n </div>\n } @else {\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays on the trigger/search, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-select__option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"isSelected(option) ? 'true' : 'false'\"\n [attr.aria-disabled]=\"option.disabled ? 'true' : null\"\n [class.lc-select__option--selected]=\"isSelected(option)\"\n [class.lc-select__option--highlighted]=\"highlightedIndex() === i\"\n [class.lc-select__option--disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(i)\"\n >\n @if (multiple()) {\n <!-- Purely visual: the option itself carries the selected state (role=option\n + aria-selected); the checkbox is inert so clicks land on the option. -->\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(option)\"\n [disabled]=\"option.disabled\"\n class=\"lc-select__checkbox\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"lc-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option) && !multiple()) {\n <svg\n class=\"lc-select__check\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-select__error\" [id]=\"selectId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-select__helper\" [id]=\"selectId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n",
390
- styles: [".lc-select-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-select{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:pointer;-webkit-user-select:none;user-select:none}.lc-select:hover:not(.lc-select--disabled){border-color:var(--color-text-secondary)}.lc-select:focus,.lc-select:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-select.lc-select--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-8);font-size:var(--size-interactive-xs-font-size)}.lc-select.lc-select--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-9);font-size:var(--size-interactive-sm-font-size)}.lc-select.lc-select--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-md-font-size)}.lc-select.lc-select--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-lg-font-size)}.lc-select.lc-select--filled{background-color:var(--color-surface-sunken);border-color:transparent}.lc-select.lc-select--filled:hover:not(.lc-select--disabled){background-color:var(--color-surface-hover);border-color:var(--color-border)}.lc-select.lc-select--filled:focus,.lc-select.lc-select--filled:focus-visible{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-select.lc-select--error{border-color:var(--color-error-600)}.lc-select.lc-select--error:focus,.lc-select.lc-select--error:focus-visible{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-select.lc-select--disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-select__placeholder{color:var(--color-text-secondary)}.lc-select__icons{position:absolute;right:var(--spacing-3);display:flex;align-items:center;gap:var(--spacing-1);flex-shrink:0;pointer-events:none}.lc-select__icons button{pointer-events:auto}.lc-select__spinner{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.lc-select__clear{display:var(--lc-select-clear-display, flex);align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:none;border:none;border-radius:var(--border-radius-sm);color:var(--lc-select-clear-fg, var(--color-text-secondary));cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__clear:hover{color:var(--lc-select-clear-hover-fg, var(--color-text-primary));background-color:var(--lc-select-clear-hover-bg, var(--color-surface-hover))}.lc-select__clear svg{width:1rem;height:1rem}.lc-select__chevron{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);transition:transform var(--animation-duration-base) var(--animation-timing-ease)}.lc-select__chevron.lc-select__chevron--open{transform:rotate(180deg)}.lc-select__dropdown{position:absolute;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-xs, var(--spacing-2));background-color:var(--color-surface);background-image:var(--gradient-surface);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-4);min-width:200px;max-height:320px;overflow-y:auto;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-select__dropdown.lc-select__dropdown--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-select__dropdown::-webkit-scrollbar{width:8px}.lc-select__dropdown::-webkit-scrollbar-track{background:var(--color-surface-sunken);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb:hover{background:var(--color-border-strong)}.lc-select__search{padding:var(--lc-density-padding-xs, var(--spacing-2));border-bottom:1px solid var(--color-border);margin-bottom:var(--spacing-2)}.lc-select__search-input{width:100%;padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-md);outline:none;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__search-input:focus{border-color:var(--color-primary-500)}.lc-select__search-input::placeholder{color:var(--color-text-secondary)}.lc-select__options{list-style:none;padding:0;margin:0}.lc-select__option{display:flex;align-items:center;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--font-size-sm);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease);text-align:left;width:100%}.lc-select__option:hover:not(.lc-select__option--disabled){background-color:var(--color-surface-hover)}.lc-select__option.lc-select__option--selected{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-select__option.lc-select__option--highlighted{background-color:var(--color-surface-hover);outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-select__option.lc-select__option--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-select__option-label{flex:1}.lc-select__check{width:1rem;height:1rem;margin-left:var(--spacing-2);flex-shrink:0;color:var(--color-primary-600)}.lc-select__checkbox{margin-right:var(--spacing-2);width:1rem;height:1rem;pointer-events:none}.lc-select__empty{padding:var(--lc-density-padding-md, var(--spacing-4));text-align:center;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.lc-select__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-select__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}@media(forced-colors:active){.lc-select__option.lc-select__option--highlighted{outline-color:Highlight}}\n"],
390
+ styles: [".lc-select-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-select{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:pointer;-webkit-user-select:none;user-select:none}.lc-select:hover:not(.lc-select--disabled):not(:focus){border-color:var(--color-text-secondary)}.lc-select:focus,.lc-select:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-select.lc-select--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-8);font-size:var(--size-interactive-xs-font-size)}.lc-select.lc-select--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-9);font-size:var(--size-interactive-sm-font-size)}.lc-select.lc-select--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-md-font-size)}.lc-select.lc-select--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-lg-font-size)}.lc-select.lc-select--filled{background-color:var(--color-surface-sunken);border-color:transparent}.lc-select.lc-select--filled:hover:not(.lc-select--disabled):not(:focus){background-color:var(--color-surface-hover);border-color:var(--color-border)}.lc-select.lc-select--filled:focus,.lc-select.lc-select--filled:focus-visible{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-select.lc-select--error{border-color:var(--color-error-600)}.lc-select.lc-select--error:focus,.lc-select.lc-select--error:focus-visible{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-select.lc-select--disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-select__placeholder{color:var(--color-text-secondary)}.lc-select__icons{position:absolute;right:var(--spacing-3);display:flex;align-items:center;gap:var(--spacing-1);flex-shrink:0;pointer-events:none}.lc-select__icons button{pointer-events:auto}.lc-select__spinner{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.lc-select__clear{display:var(--lc-select-clear-display, flex);align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:none;border:none;border-radius:var(--border-radius-sm);color:var(--lc-select-clear-fg, var(--color-text-secondary));cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__clear:hover{color:var(--lc-select-clear-hover-fg, var(--color-text-primary));background-color:var(--lc-select-clear-hover-bg, var(--color-surface-hover))}.lc-select__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-select__clear svg{width:1rem;height:1rem}.lc-select__chevron{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);transition:transform var(--animation-duration-base) var(--animation-timing-ease)}.lc-select__chevron.lc-select__chevron--open{transform:rotate(180deg)}.lc-select__dropdown{position:absolute;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-xs, var(--spacing-2));background-color:var(--color-surface);background-image:var(--gradient-surface);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-4);min-width:200px;max-height:320px;overflow-y:auto;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-select__dropdown.lc-select__dropdown--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-select__dropdown::-webkit-scrollbar{width:8px}.lc-select__dropdown::-webkit-scrollbar-track{background:var(--color-surface-sunken);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb:hover{background:var(--color-border-strong)}.lc-select__search{padding:var(--lc-density-padding-xs, var(--spacing-2));border-bottom:1px solid var(--color-border);margin-bottom:var(--spacing-2)}.lc-select__search-input{width:100%;padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-md);outline:none;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__search-input:focus{border-color:var(--color-primary-500)}.lc-select__search-input::placeholder{color:var(--color-text-secondary)}.lc-select__options{list-style:none;padding:0;margin:0}.lc-select__option{display:flex;align-items:center;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--font-size-sm);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease);text-align:left;width:100%}.lc-select__option:hover:not(.lc-select__option--disabled){background-color:var(--color-surface-hover)}.lc-select__option.lc-select__option--selected{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-select__option.lc-select__option--highlighted{background-color:var(--color-surface-hover);outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-select__option.lc-select__option--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-select__option-label{flex:1}.lc-select__check{width:1rem;height:1rem;margin-left:var(--spacing-2);flex-shrink:0;color:var(--color-primary-600)}.lc-select__checkbox{margin-right:var(--spacing-2);width:1rem;height:1rem;pointer-events:none}.lc-select__empty{padding:var(--lc-density-padding-md, var(--spacing-4));text-align:center;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.lc-select__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-select__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}@media(forced-colors:active){.lc-select__option.lc-select__option--highlighted{outline-color:Highlight}.lc-select__clear:focus-visible{outline-color:Highlight}}\n"],
391
391
  dependencies: [
392
392
  {
393
393
  kind: "ngmodule",
@@ -483,7 +483,7 @@ i0.ɵɵngDeclareClassMetadata({
483
483
  multi: true
484
484
  }],
485
485
  template: "<div class=\"lc-select-wrapper\">\n <div\n #selectTrigger\n [class]=\"selectClasses()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n >\n <div class=\"lc-select__value\">\n <span [class.lc-select__placeholder]=\"!selectedLabel()\">\n {{ displayValue() }}\n </span>\n </div>\n\n <div class=\"lc-select__icons\">\n @if (loading()) {\n <svg\n class=\"lc-select__spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n } @else if (value() && !isDisabled() && !multiple()) {\n <button\n type=\"button\"\n class=\"lc-select__clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n\n <svg\n class=\"lc-select__chevron\"\n [class.lc-select__chevron--open]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Dropdown Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"selectTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div #dropdownPanel class=\"lc-select__dropdown\" [class.lc-select__dropdown--open]=\"isOpen()\">\n @if (searchable()) {\n <div class=\"lc-select__search\">\n <input\n type=\"text\"\n class=\"lc-select__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"searchAriaLabel() || (ariaLabel() ? 'Search ' + ariaLabel() : 'Search options')\"\n [(ngModel)]=\"searchQuery\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div\n class=\"lc-select__options\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n >\n @if (filteredOptions().length === 0) {\n <div\n class=\"lc-select__option lc-select__option--no-results\"\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n >\n {{ noOptionsLabel() }}\n </div>\n } @else {\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays on the trigger/search, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-select__option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"isSelected(option) ? 'true' : 'false'\"\n [attr.aria-disabled]=\"option.disabled ? 'true' : null\"\n [class.lc-select__option--selected]=\"isSelected(option)\"\n [class.lc-select__option--highlighted]=\"highlightedIndex() === i\"\n [class.lc-select__option--disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(i)\"\n >\n @if (multiple()) {\n <!-- Purely visual: the option itself carries the selected state (role=option\n + aria-selected); the checkbox is inert so clicks land on the option. -->\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(option)\"\n [disabled]=\"option.disabled\"\n class=\"lc-select__checkbox\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"lc-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option) && !multiple()) {\n <svg\n class=\"lc-select__check\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-select__error\" [id]=\"selectId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-select__helper\" [id]=\"selectId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n",
486
- styles: [".lc-select-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-select{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:pointer;-webkit-user-select:none;user-select:none}.lc-select:hover:not(.lc-select--disabled){border-color:var(--color-text-secondary)}.lc-select:focus,.lc-select:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-select.lc-select--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-8);font-size:var(--size-interactive-xs-font-size)}.lc-select.lc-select--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-9);font-size:var(--size-interactive-sm-font-size)}.lc-select.lc-select--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-md-font-size)}.lc-select.lc-select--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-lg-font-size)}.lc-select.lc-select--filled{background-color:var(--color-surface-sunken);border-color:transparent}.lc-select.lc-select--filled:hover:not(.lc-select--disabled){background-color:var(--color-surface-hover);border-color:var(--color-border)}.lc-select.lc-select--filled:focus,.lc-select.lc-select--filled:focus-visible{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-select.lc-select--error{border-color:var(--color-error-600)}.lc-select.lc-select--error:focus,.lc-select.lc-select--error:focus-visible{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-select.lc-select--disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-select__placeholder{color:var(--color-text-secondary)}.lc-select__icons{position:absolute;right:var(--spacing-3);display:flex;align-items:center;gap:var(--spacing-1);flex-shrink:0;pointer-events:none}.lc-select__icons button{pointer-events:auto}.lc-select__spinner{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.lc-select__clear{display:var(--lc-select-clear-display, flex);align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:none;border:none;border-radius:var(--border-radius-sm);color:var(--lc-select-clear-fg, var(--color-text-secondary));cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__clear:hover{color:var(--lc-select-clear-hover-fg, var(--color-text-primary));background-color:var(--lc-select-clear-hover-bg, var(--color-surface-hover))}.lc-select__clear svg{width:1rem;height:1rem}.lc-select__chevron{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);transition:transform var(--animation-duration-base) var(--animation-timing-ease)}.lc-select__chevron.lc-select__chevron--open{transform:rotate(180deg)}.lc-select__dropdown{position:absolute;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-xs, var(--spacing-2));background-color:var(--color-surface);background-image:var(--gradient-surface);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-4);min-width:200px;max-height:320px;overflow-y:auto;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-select__dropdown.lc-select__dropdown--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-select__dropdown::-webkit-scrollbar{width:8px}.lc-select__dropdown::-webkit-scrollbar-track{background:var(--color-surface-sunken);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb:hover{background:var(--color-border-strong)}.lc-select__search{padding:var(--lc-density-padding-xs, var(--spacing-2));border-bottom:1px solid var(--color-border);margin-bottom:var(--spacing-2)}.lc-select__search-input{width:100%;padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-md);outline:none;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__search-input:focus{border-color:var(--color-primary-500)}.lc-select__search-input::placeholder{color:var(--color-text-secondary)}.lc-select__options{list-style:none;padding:0;margin:0}.lc-select__option{display:flex;align-items:center;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--font-size-sm);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease);text-align:left;width:100%}.lc-select__option:hover:not(.lc-select__option--disabled){background-color:var(--color-surface-hover)}.lc-select__option.lc-select__option--selected{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-select__option.lc-select__option--highlighted{background-color:var(--color-surface-hover);outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-select__option.lc-select__option--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-select__option-label{flex:1}.lc-select__check{width:1rem;height:1rem;margin-left:var(--spacing-2);flex-shrink:0;color:var(--color-primary-600)}.lc-select__checkbox{margin-right:var(--spacing-2);width:1rem;height:1rem;pointer-events:none}.lc-select__empty{padding:var(--lc-density-padding-md, var(--spacing-4));text-align:center;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.lc-select__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-select__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}@media(forced-colors:active){.lc-select__option.lc-select__option--highlighted{outline-color:Highlight}}\n"]
486
+ styles: [".lc-select-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-select{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:pointer;-webkit-user-select:none;user-select:none}.lc-select:hover:not(.lc-select--disabled):not(:focus){border-color:var(--color-text-secondary)}.lc-select:focus,.lc-select:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-select.lc-select--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-8);font-size:var(--size-interactive-xs-font-size)}.lc-select.lc-select--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-9);font-size:var(--size-interactive-sm-font-size)}.lc-select.lc-select--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-md-font-size)}.lc-select.lc-select--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-lg-font-size)}.lc-select.lc-select--filled{background-color:var(--color-surface-sunken);border-color:transparent}.lc-select.lc-select--filled:hover:not(.lc-select--disabled):not(:focus){background-color:var(--color-surface-hover);border-color:var(--color-border)}.lc-select.lc-select--filled:focus,.lc-select.lc-select--filled:focus-visible{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-select.lc-select--error{border-color:var(--color-error-600)}.lc-select.lc-select--error:focus,.lc-select.lc-select--error:focus-visible{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-select.lc-select--disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-select__placeholder{color:var(--color-text-secondary)}.lc-select__icons{position:absolute;right:var(--spacing-3);display:flex;align-items:center;gap:var(--spacing-1);flex-shrink:0;pointer-events:none}.lc-select__icons button{pointer-events:auto}.lc-select__spinner{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.lc-select__clear{display:var(--lc-select-clear-display, flex);align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:none;border:none;border-radius:var(--border-radius-sm);color:var(--lc-select-clear-fg, var(--color-text-secondary));cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__clear:hover{color:var(--lc-select-clear-hover-fg, var(--color-text-primary));background-color:var(--lc-select-clear-hover-bg, var(--color-surface-hover))}.lc-select__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-select__clear svg{width:1rem;height:1rem}.lc-select__chevron{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);transition:transform var(--animation-duration-base) var(--animation-timing-ease)}.lc-select__chevron.lc-select__chevron--open{transform:rotate(180deg)}.lc-select__dropdown{position:absolute;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-xs, var(--spacing-2));background-color:var(--color-surface);background-image:var(--gradient-surface);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-4);min-width:200px;max-height:320px;overflow-y:auto;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-select__dropdown.lc-select__dropdown--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-select__dropdown::-webkit-scrollbar{width:8px}.lc-select__dropdown::-webkit-scrollbar-track{background:var(--color-surface-sunken);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb:hover{background:var(--color-border-strong)}.lc-select__search{padding:var(--lc-density-padding-xs, var(--spacing-2));border-bottom:1px solid var(--color-border);margin-bottom:var(--spacing-2)}.lc-select__search-input{width:100%;padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-md);outline:none;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__search-input:focus{border-color:var(--color-primary-500)}.lc-select__search-input::placeholder{color:var(--color-text-secondary)}.lc-select__options{list-style:none;padding:0;margin:0}.lc-select__option{display:flex;align-items:center;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--font-size-sm);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease);text-align:left;width:100%}.lc-select__option:hover:not(.lc-select__option--disabled){background-color:var(--color-surface-hover)}.lc-select__option.lc-select__option--selected{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-select__option.lc-select__option--highlighted{background-color:var(--color-surface-hover);outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-select__option.lc-select__option--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-select__option-label{flex:1}.lc-select__check{width:1rem;height:1rem;margin-left:var(--spacing-2);flex-shrink:0;color:var(--color-primary-600)}.lc-select__checkbox{margin-right:var(--spacing-2);width:1rem;height:1rem;pointer-events:none}.lc-select__empty{padding:var(--lc-density-padding-md, var(--spacing-4));text-align:center;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.lc-select__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-select__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}@media(forced-colors:active){.lc-select__option.lc-select__option--highlighted{outline-color:Highlight}.lc-select__clear:focus-visible{outline-color:Highlight}}\n"]
487
487
  }]
488
488
  }],
489
489
  propDecorators: {
@@ -1 +1 @@
1
- {"version":3,"file":"lifecorner-angular-ui-kit-select.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/select/select.component.ts","../../../../libs/angular-ui-kit/src/lib/select/select.component.html"],"sourcesContent":["import {\n Component,\n input,\n output,\n signal,\n computed,\n linkedSignal,\n ChangeDetectionStrategy,\n forwardRef,\n ElementRef,\n viewChild,\n inject,\n DOCUMENT,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';\nimport { OverlayModule } from '@angular/cdk/overlay';\n\nexport interface SelectOption {\n value: string | number;\n label: string;\n disabled?: boolean;\n}\n\nexport interface SelectOptionGroup {\n label: string;\n options: SelectOption[];\n}\n\nexport type SelectValue = string | number | string[] | number[] | null;\n\n/**\n * Select component for dropdown option selection.\n *\n * Features:\n * - Single and multiple selection modes\n * - Searchable/filterable option list\n * - Option groups with headers\n * - Loading state indicator\n * - Variant styles (outline, filled)\n * - Size presets (xs, sm, md, lg)\n * - Keyboard navigation support\n * - CDK overlay positioning\n * - ControlValueAccessor integration for reactive forms\n *\n * @example\n * ```html\n * <lc-select [options]=\"options\" placeholder=\"Choose\" [(ngModel)]=\"selected\" />\n * ```\n */\n@Component({\n selector: 'lc-select',\n standalone: true,\n imports: [FormsModule, OverlayModule],\n templateUrl: './select.component.html',\n styleUrl: './select.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => SelectComponent),\n multi: true,\n },\n ],\n})\nexport class SelectComponent implements ControlValueAccessor {\n private static nextId = 0;\n\n /** Per-instance id base; the listbox and its options derive their ids from it. */\n readonly selectId = `lc-select-${++SelectComponent.nextId}`;\n readonly listboxId = `${this.selectId}-listbox`;\n\n private readonly selectTrigger = viewChild<ElementRef<HTMLElement>>('selectTrigger');\n private readonly dropdownPanel = viewChild<ElementRef<HTMLElement>>('dropdownPanel');\n\n /**\n * Visual variant of the select\n */\n readonly variant = input<'outline' | 'filled'>('outline');\n\n /**\n * Size of the select\n */\n readonly size = input<'xs' | 'sm' | 'md' | 'lg'>('md');\n\n /**\n * Whether the select is disabled\n */\n readonly disabled = input<boolean>(false);\n\n /**\n * Whether the select is in error state\n */\n readonly error = input<boolean>(false);\n\n /**\n * Whether the select is required\n */\n readonly required = input<boolean>(false);\n\n /**\n * Whether the select is in loading state\n */\n readonly loading = input<boolean>(false);\n\n /**\n * Whether the select allows searching\n */\n readonly searchable = input<boolean>(false);\n\n /**\n * Whether multiple options can be selected\n */\n readonly multiple = input<boolean>(false);\n\n /**\n * Placeholder text when no option is selected\n */\n readonly placeholder = input<string>('Select an option');\n\n /**\n * Helper text displayed below the select\n */\n readonly helperText = input<string>('');\n\n /**\n * Error message displayed when error is true\n */\n readonly errorMessage = input<string>('');\n\n /**\n * ARIA label for accessibility\n */\n readonly ariaLabel = input<string | undefined>(undefined);\n\n /**\n * Select options (flat list or groups)\n */\n readonly options = input<SelectOption[] | SelectOptionGroup[]>([]);\n\n /** Accessible name of the clear button. */\n readonly clearAriaLabel = input('Clear selection');\n\n /** Placeholder of the search field (`searchable`). */\n readonly searchPlaceholder = input('Search...');\n\n /** Accessible name of the search field. Empty: \"Search \" + `ariaLabel`, or \"Search options\". */\n readonly searchAriaLabel = input('');\n\n /** Shown when the search matches no option. */\n readonly noOptionsLabel = input('No options found');\n\n /**\n * Emitted when selection changes\n */\n readonly selectionChange = output<SelectValue>();\n\n /**\n * Emitted when dropdown opens\n */\n readonly opened = output<void>();\n\n /**\n * Emitted when dropdown closes\n */\n readonly closed = output<void>();\n\n // Internal state\n readonly value = signal<SelectValue>(null);\n readonly isOpen = signal<boolean>(false);\n readonly searchQuery = signal<string>('');\n\n /** Disabled state pushed in by the forms API (setDisabledState). */\n private readonly formDisabled = signal<boolean>(false);\n\n /** Effective disabled state: the `disabled` input OR the form control's disabled state. */\n readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n\n // Computed values\n readonly filteredOptions = computed(() => {\n const query = this.searchQuery().toLowerCase();\n const opts = this.options();\n\n if (!query || !this.searchable()) {\n return this.flattenOptions(opts);\n }\n\n return this.flattenOptions(opts).filter((opt) => opt.label.toLowerCase().includes(query));\n });\n\n /** Keyboard highlight; resets whenever the visible option list changes so it never points at a stale row. */\n readonly highlightedIndex = linkedSignal<SelectOption[], number>({\n source: this.filteredOptions,\n computation: () => -1,\n });\n\n readonly activeDescendantId = computed(() => {\n const index = this.highlightedIndex();\n return this.isOpen() && index >= 0 ? this.optionId(index) : null;\n });\n\n readonly selectedLabel = computed(() => {\n const currentValue = this.value();\n const opts = this.options();\n\n if (currentValue === null) {\n return '';\n }\n\n if (this.multiple()) {\n const values = Array.isArray(currentValue) ? currentValue : [currentValue];\n return values\n .map((val) => this.findOptionByValue(val, opts)?.label)\n .filter(Boolean)\n .join(', ');\n }\n\n const val = Array.isArray(currentValue) ? currentValue[0] : currentValue;\n return this.findOptionByValue(val ?? '', opts)?.label || '';\n });\n\n readonly displayValue = computed(() => {\n const label = this.selectedLabel();\n if (label) {\n const currentValue = this.value();\n if (this.multiple() && Array.isArray(currentValue)) {\n const count = currentValue.length;\n return count > 1 ? `${count} selected` : label;\n }\n return label;\n }\n return this.placeholder();\n });\n\n /** id of the helper/error text the trigger is described by (aria-describedby) */\n readonly describedBy = computed(() => {\n if (this.error() && this.errorMessage()) {\n return `${this.selectId}-error`;\n }\n return this.helperText() ? `${this.selectId}-helper` : null;\n });\n\n /**\n * Computed classes for the select trigger element\n */\n readonly selectClasses = computed(() => {\n const classes = ['lc-select', `lc-select--${this.variant()}`, `lc-select--${this.size()}`];\n\n if (this.isDisabled()) {\n classes.push('lc-select--disabled');\n }\n\n if (this.error()) {\n classes.push('lc-select--error');\n }\n\n if (this.loading()) {\n classes.push('lc-select--loading');\n }\n\n if (this.isOpen()) {\n classes.push('lc-select--open');\n }\n\n return classes.join(' ');\n });\n\n // Private properties\n private readonly document = inject(DOCUMENT);\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onChange: (value: SelectValue) => void = () => {};\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onTouched: () => void = () => {};\n\n // Public methods\n /**\n * Id of the option at `index` in the filtered list (used for aria-activedescendant)\n */\n optionId(index: number): string {\n return `${this.selectId}-option-${index}`;\n }\n\n /**\n * Toggle dropdown open/closed\n */\n toggle(): void {\n if (this.isDisabled() || this.loading()) {\n return;\n }\n if (this.isOpen()) {\n this.close();\n } else {\n this.open();\n }\n }\n\n /**\n * Open dropdown\n */\n open(): void {\n if (this.isDisabled() || this.loading() || this.isOpen()) {\n return;\n }\n this.isOpen.set(true);\n this.opened.emit();\n }\n\n /**\n * Close dropdown. Idempotent: the overlay's `detach` re-enters here after\n * `isOpen` flips, and that second call must not emit `closed` again.\n */\n close(): void {\n if (!this.isOpen()) {\n return;\n }\n // If focus is inside the panel (search input) it would fall to <body> when the\n // overlay is torn down; hand it back to the trigger first.\n this.restoreFocusFromPanel();\n this.isOpen.set(false);\n this.searchQuery.set('');\n this.highlightedIndex.set(-1);\n this.closed.emit();\n }\n\n /**\n * Select an option\n */\n selectOption(option: SelectOption): void {\n if (option.disabled) {\n return;\n }\n\n if (this.multiple()) {\n const currentValue = this.value() || [];\n const currentArray = (Array.isArray(currentValue) ? currentValue : []) as (string | number)[];\n const index = currentArray.indexOf(option.value);\n\n const newValue = (\n index > -1\n ? currentArray.filter((v) => v !== option.value) // Deselect\n : [...currentArray, option.value] // Select\n ) as SelectValue;\n this.value.set(newValue);\n this.onChange(newValue);\n this.selectionChange.emit(newValue);\n } else {\n this.value.set(option.value);\n this.onChange(option.value);\n this.selectionChange.emit(option.value);\n this.close();\n }\n }\n\n /**\n * Check if an option is selected\n */\n isSelected(option: SelectOption): boolean {\n const currentValue = this.value();\n if (this.multiple()) {\n const values = Array.isArray(currentValue) ? currentValue : [];\n return values.some((v) => v === option.value);\n }\n return currentValue === option.value;\n }\n\n /**\n * Clear selection\n */\n clear(): void {\n if (this.multiple()) {\n this.value.set([]);\n this.onChange([]);\n } else {\n this.value.set(null);\n this.onChange(null);\n }\n this.selectionChange.emit(this.value());\n }\n\n /**\n * Handle keyboard navigation (trigger and search input share this handler)\n */\n onKeyDown(event: KeyboardEvent): void {\n if (this.isDisabled() || this.loading()) {\n return;\n }\n\n switch (event.key) {\n case ' ':\n case 'Enter':\n // Space must keep typing into the search box.\n if (event.key === ' ' && this.isSearchInput(event.target)) {\n return;\n }\n if (!this.isOpen()) {\n this.open();\n } else {\n const option = this.filteredOptions()[this.highlightedIndex()];\n if (option) {\n this.selectOption(option);\n }\n }\n event.preventDefault();\n break;\n\n case 'Escape':\n if (this.isOpen()) {\n this.close();\n event.preventDefault();\n // Only this select should react; keep the key from reaching enclosing overlays.\n event.stopPropagation();\n }\n break;\n\n case 'ArrowDown':\n if (!this.isOpen()) {\n this.open();\n } else {\n const count = this.filteredOptions().length;\n if (count > 0) {\n this.highlightedIndex.set((this.highlightedIndex() + 1) % count);\n }\n }\n event.preventDefault();\n break;\n\n case 'ArrowUp':\n if (!this.isOpen()) {\n this.open();\n } else {\n const count = this.filteredOptions().length;\n if (count > 0) {\n const current = this.highlightedIndex();\n this.highlightedIndex.set(current <= 0 ? count - 1 : current - 1);\n }\n }\n event.preventDefault();\n break;\n\n case 'Home':\n if (this.isOpen() && this.filteredOptions().length > 0) {\n this.highlightedIndex.set(0);\n event.preventDefault();\n }\n break;\n\n case 'End':\n if (this.isOpen() && this.filteredOptions().length > 0) {\n this.highlightedIndex.set(this.filteredOptions().length - 1);\n event.preventDefault();\n }\n break;\n }\n }\n\n /**\n * Handle blur event\n */\n onBlur(): void {\n this.onTouched();\n }\n\n /**\n * Handle click outside\n */\n onClickOutside(): void {\n this.close();\n }\n\n // ControlValueAccessor implementation\n writeValue(value: SelectValue): void {\n this.value.set(value);\n }\n\n registerOnChange(fn: (value: SelectValue) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n // Private helper methods\n private isSearchInput(target: EventTarget | null): boolean {\n return target instanceof HTMLInputElement;\n }\n\n private restoreFocusFromPanel(): void {\n const panel = this.dropdownPanel()?.nativeElement;\n const active = this.document.activeElement;\n if (panel && active && panel.contains(active)) {\n this.selectTrigger()?.nativeElement.focus();\n }\n }\n\n private findOptionByValue(\n value: string | number,\n options: SelectOption[] | SelectOptionGroup[],\n ): SelectOption | undefined {\n const flatOptions = this.flattenOptions(options);\n return flatOptions.find((opt) => opt.value === value);\n }\n\n private flattenOptions(options: SelectOption[] | SelectOptionGroup[]): SelectOption[] {\n if (!options || options.length === 0) {\n return [];\n }\n\n // Check if first item is a group\n const firstItem = options[0];\n if (firstItem && 'options' in firstItem) {\n return (options as SelectOptionGroup[]).flatMap((group) => group.options);\n }\n\n return options as SelectOption[];\n }\n}\n","<div class=\"lc-select-wrapper\">\n <div\n #selectTrigger\n [class]=\"selectClasses()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n >\n <div class=\"lc-select__value\">\n <span [class.lc-select__placeholder]=\"!selectedLabel()\">\n {{ displayValue() }}\n </span>\n </div>\n\n <div class=\"lc-select__icons\">\n @if (loading()) {\n <svg\n class=\"lc-select__spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n } @else if (value() && !isDisabled() && !multiple()) {\n <button\n type=\"button\"\n class=\"lc-select__clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n\n <svg\n class=\"lc-select__chevron\"\n [class.lc-select__chevron--open]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Dropdown Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"selectTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div #dropdownPanel class=\"lc-select__dropdown\" [class.lc-select__dropdown--open]=\"isOpen()\">\n @if (searchable()) {\n <div class=\"lc-select__search\">\n <input\n type=\"text\"\n class=\"lc-select__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"searchAriaLabel() || (ariaLabel() ? 'Search ' + ariaLabel() : 'Search options')\"\n [(ngModel)]=\"searchQuery\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div\n class=\"lc-select__options\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n >\n @if (filteredOptions().length === 0) {\n <div\n class=\"lc-select__option lc-select__option--no-results\"\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n >\n {{ noOptionsLabel() }}\n </div>\n } @else {\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays on the trigger/search, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-select__option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"isSelected(option) ? 'true' : 'false'\"\n [attr.aria-disabled]=\"option.disabled ? 'true' : null\"\n [class.lc-select__option--selected]=\"isSelected(option)\"\n [class.lc-select__option--highlighted]=\"highlightedIndex() === i\"\n [class.lc-select__option--disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(i)\"\n >\n @if (multiple()) {\n <!-- Purely visual: the option itself carries the selected state (role=option\n + aria-selected); the checkbox is inert so clicks land on the option. -->\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(option)\"\n [disabled]=\"option.disabled\"\n class=\"lc-select__checkbox\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"lc-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option) && !multiple()) {\n <svg\n class=\"lc-select__check\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-select__error\" [id]=\"selectId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-select__helper\" [id]=\"selectId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-select.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/select/select.component.ts","../../../../libs/angular-ui-kit/src/lib/select/select.component.html"],"sourcesContent":["import {\n Component,\n input,\n output,\n signal,\n computed,\n linkedSignal,\n ChangeDetectionStrategy,\n forwardRef,\n ElementRef,\n viewChild,\n inject,\n DOCUMENT,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';\nimport { OverlayModule } from '@angular/cdk/overlay';\n\nexport interface SelectOption {\n value: string | number;\n label: string;\n disabled?: boolean;\n}\n\nexport interface SelectOptionGroup {\n label: string;\n options: SelectOption[];\n}\n\nexport type SelectValue = string | number | string[] | number[] | null;\n\n/**\n * Select component for dropdown option selection.\n *\n * Features:\n * - Single and multiple selection modes\n * - Searchable/filterable option list\n * - Option groups with headers\n * - Loading state indicator\n * - Variant styles (outline, filled)\n * - Size presets (xs, sm, md, lg)\n * - Keyboard navigation support\n * - CDK overlay positioning\n * - ControlValueAccessor integration for reactive forms\n *\n * @example\n * ```html\n * <lc-select [options]=\"options\" placeholder=\"Choose\" [(ngModel)]=\"selected\" />\n * ```\n */\n@Component({\n selector: 'lc-select',\n standalone: true,\n imports: [FormsModule, OverlayModule],\n templateUrl: './select.component.html',\n styleUrl: './select.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => SelectComponent),\n multi: true,\n },\n ],\n})\nexport class SelectComponent implements ControlValueAccessor {\n private static nextId = 0;\n\n /** Per-instance id base; the listbox and its options derive their ids from it. */\n readonly selectId = `lc-select-${++SelectComponent.nextId}`;\n readonly listboxId = `${this.selectId}-listbox`;\n\n private readonly selectTrigger = viewChild<ElementRef<HTMLElement>>('selectTrigger');\n private readonly dropdownPanel = viewChild<ElementRef<HTMLElement>>('dropdownPanel');\n\n /**\n * Visual variant of the select\n */\n readonly variant = input<'outline' | 'filled'>('outline');\n\n /**\n * Size of the select\n */\n readonly size = input<'xs' | 'sm' | 'md' | 'lg'>('md');\n\n /**\n * Whether the select is disabled\n */\n readonly disabled = input<boolean>(false);\n\n /**\n * Whether the select is in error state\n */\n readonly error = input<boolean>(false);\n\n /**\n * Whether the select is required\n */\n readonly required = input<boolean>(false);\n\n /**\n * Whether the select is in loading state\n */\n readonly loading = input<boolean>(false);\n\n /**\n * Whether the select allows searching\n */\n readonly searchable = input<boolean>(false);\n\n /**\n * Whether multiple options can be selected\n */\n readonly multiple = input<boolean>(false);\n\n /**\n * Placeholder text when no option is selected\n */\n readonly placeholder = input<string>('Select an option');\n\n /**\n * Helper text displayed below the select\n */\n readonly helperText = input<string>('');\n\n /**\n * Error message displayed when error is true\n */\n readonly errorMessage = input<string>('');\n\n /**\n * ARIA label for accessibility\n */\n readonly ariaLabel = input<string | undefined>(undefined);\n\n /**\n * Select options (flat list or groups)\n */\n readonly options = input<SelectOption[] | SelectOptionGroup[]>([]);\n\n /** Accessible name of the clear button. */\n readonly clearAriaLabel = input('Clear selection');\n\n /** Placeholder of the search field (`searchable`). */\n readonly searchPlaceholder = input('Search...');\n\n /** Accessible name of the search field. Empty: \"Search \" + `ariaLabel`, or \"Search options\". */\n readonly searchAriaLabel = input('');\n\n /** Shown when the search matches no option. */\n readonly noOptionsLabel = input('No options found');\n\n /**\n * Emitted when selection changes\n */\n readonly selectionChange = output<SelectValue>();\n\n /**\n * Emitted when dropdown opens\n */\n readonly opened = output<void>();\n\n /**\n * Emitted when dropdown closes\n */\n readonly closed = output<void>();\n\n // Internal state\n readonly value = signal<SelectValue>(null);\n readonly isOpen = signal<boolean>(false);\n readonly searchQuery = signal<string>('');\n\n /** Disabled state pushed in by the forms API (setDisabledState). */\n private readonly formDisabled = signal<boolean>(false);\n\n /** Effective disabled state: the `disabled` input OR the form control's disabled state. */\n readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n\n // Computed values\n readonly filteredOptions = computed(() => {\n const query = this.searchQuery().toLowerCase();\n const opts = this.options();\n\n if (!query || !this.searchable()) {\n return this.flattenOptions(opts);\n }\n\n return this.flattenOptions(opts).filter((opt) => opt.label.toLowerCase().includes(query));\n });\n\n /** Keyboard highlight; resets whenever the visible option list changes so it never points at a stale row. */\n readonly highlightedIndex = linkedSignal<SelectOption[], number>({\n source: this.filteredOptions,\n computation: () => -1,\n });\n\n readonly activeDescendantId = computed(() => {\n const index = this.highlightedIndex();\n return this.isOpen() && index >= 0 ? this.optionId(index) : null;\n });\n\n readonly selectedLabel = computed(() => {\n const currentValue = this.value();\n const opts = this.options();\n\n if (currentValue === null) {\n return '';\n }\n\n if (this.multiple()) {\n const values = Array.isArray(currentValue) ? currentValue : [currentValue];\n return values\n .map((val) => this.findOptionByValue(val, opts)?.label)\n .filter(Boolean)\n .join(', ');\n }\n\n const val = Array.isArray(currentValue) ? currentValue[0] : currentValue;\n return this.findOptionByValue(val ?? '', opts)?.label || '';\n });\n\n readonly displayValue = computed(() => {\n const label = this.selectedLabel();\n if (label) {\n const currentValue = this.value();\n if (this.multiple() && Array.isArray(currentValue)) {\n const count = currentValue.length;\n return count > 1 ? `${count} selected` : label;\n }\n return label;\n }\n return this.placeholder();\n });\n\n /** id of the helper/error text the trigger is described by (aria-describedby) */\n readonly describedBy = computed(() => {\n if (this.error() && this.errorMessage()) {\n return `${this.selectId}-error`;\n }\n return this.helperText() ? `${this.selectId}-helper` : null;\n });\n\n /**\n * Computed classes for the select trigger element\n */\n readonly selectClasses = computed(() => {\n const classes = ['lc-select', `lc-select--${this.variant()}`, `lc-select--${this.size()}`];\n\n if (this.isDisabled()) {\n classes.push('lc-select--disabled');\n }\n\n if (this.error()) {\n classes.push('lc-select--error');\n }\n\n if (this.loading()) {\n classes.push('lc-select--loading');\n }\n\n if (this.isOpen()) {\n classes.push('lc-select--open');\n }\n\n return classes.join(' ');\n });\n\n // Private properties\n private readonly document = inject(DOCUMENT);\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onChange: (value: SelectValue) => void = () => {};\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onTouched: () => void = () => {};\n\n // Public methods\n /**\n * Id of the option at `index` in the filtered list (used for aria-activedescendant)\n */\n optionId(index: number): string {\n return `${this.selectId}-option-${index}`;\n }\n\n /**\n * Toggle dropdown open/closed\n */\n toggle(): void {\n if (this.isDisabled() || this.loading()) {\n return;\n }\n if (this.isOpen()) {\n this.close();\n } else {\n this.open();\n }\n }\n\n /**\n * Open dropdown\n */\n open(): void {\n if (this.isDisabled() || this.loading() || this.isOpen()) {\n return;\n }\n this.isOpen.set(true);\n this.opened.emit();\n }\n\n /**\n * Close dropdown. Idempotent: the overlay's `detach` re-enters here after\n * `isOpen` flips, and that second call must not emit `closed` again.\n */\n close(): void {\n if (!this.isOpen()) {\n return;\n }\n // If focus is inside the panel (search input) it would fall to <body> when the\n // overlay is torn down; hand it back to the trigger first.\n this.restoreFocusFromPanel();\n this.isOpen.set(false);\n this.searchQuery.set('');\n this.highlightedIndex.set(-1);\n this.closed.emit();\n }\n\n /**\n * Select an option\n */\n selectOption(option: SelectOption): void {\n if (option.disabled) {\n return;\n }\n\n if (this.multiple()) {\n const currentValue = this.value() || [];\n const currentArray = (Array.isArray(currentValue) ? currentValue : []) as (string | number)[];\n const index = currentArray.indexOf(option.value);\n\n const newValue = (\n index > -1\n ? currentArray.filter((v) => v !== option.value) // Deselect\n : [...currentArray, option.value] // Select\n ) as SelectValue;\n this.value.set(newValue);\n this.onChange(newValue);\n this.selectionChange.emit(newValue);\n } else {\n this.value.set(option.value);\n this.onChange(option.value);\n this.selectionChange.emit(option.value);\n this.close();\n }\n }\n\n /**\n * Check if an option is selected\n */\n isSelected(option: SelectOption): boolean {\n const currentValue = this.value();\n if (this.multiple()) {\n const values = Array.isArray(currentValue) ? currentValue : [];\n return values.some((v) => v === option.value);\n }\n return currentValue === option.value;\n }\n\n /**\n * Clear selection\n */\n clear(): void {\n if (this.multiple()) {\n this.value.set([]);\n this.onChange([]);\n } else {\n this.value.set(null);\n this.onChange(null);\n }\n this.selectionChange.emit(this.value());\n }\n\n /**\n * Handle keyboard navigation (trigger and search input share this handler)\n */\n onKeyDown(event: KeyboardEvent): void {\n if (this.isDisabled() || this.loading()) {\n return;\n }\n\n switch (event.key) {\n case ' ':\n case 'Enter':\n // Space must keep typing into the search box.\n if (event.key === ' ' && this.isSearchInput(event.target)) {\n return;\n }\n if (!this.isOpen()) {\n this.open();\n } else {\n const option = this.filteredOptions()[this.highlightedIndex()];\n if (option) {\n this.selectOption(option);\n }\n }\n event.preventDefault();\n break;\n\n case 'Escape':\n if (this.isOpen()) {\n this.close();\n event.preventDefault();\n // Only this select should react; keep the key from reaching enclosing overlays.\n event.stopPropagation();\n }\n break;\n\n case 'ArrowDown':\n if (!this.isOpen()) {\n this.open();\n } else {\n const count = this.filteredOptions().length;\n if (count > 0) {\n this.highlightedIndex.set((this.highlightedIndex() + 1) % count);\n }\n }\n event.preventDefault();\n break;\n\n case 'ArrowUp':\n if (!this.isOpen()) {\n this.open();\n } else {\n const count = this.filteredOptions().length;\n if (count > 0) {\n const current = this.highlightedIndex();\n this.highlightedIndex.set(current <= 0 ? count - 1 : current - 1);\n }\n }\n event.preventDefault();\n break;\n\n case 'Home':\n if (this.isOpen() && this.filteredOptions().length > 0) {\n this.highlightedIndex.set(0);\n event.preventDefault();\n }\n break;\n\n case 'End':\n if (this.isOpen() && this.filteredOptions().length > 0) {\n this.highlightedIndex.set(this.filteredOptions().length - 1);\n event.preventDefault();\n }\n break;\n }\n }\n\n /**\n * Handle blur event\n */\n onBlur(): void {\n this.onTouched();\n }\n\n /**\n * Handle click outside\n */\n onClickOutside(): void {\n this.close();\n }\n\n // ControlValueAccessor implementation\n writeValue(value: SelectValue): void {\n this.value.set(value);\n }\n\n registerOnChange(fn: (value: SelectValue) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n // Private helper methods\n private isSearchInput(target: EventTarget | null): boolean {\n return target instanceof HTMLInputElement;\n }\n\n private restoreFocusFromPanel(): void {\n const panel = this.dropdownPanel()?.nativeElement;\n const active = this.document.activeElement;\n if (panel && active && panel.contains(active)) {\n this.selectTrigger()?.nativeElement.focus();\n }\n }\n\n private findOptionByValue(\n value: string | number,\n options: SelectOption[] | SelectOptionGroup[],\n ): SelectOption | undefined {\n const flatOptions = this.flattenOptions(options);\n return flatOptions.find((opt) => opt.value === value);\n }\n\n private flattenOptions(options: SelectOption[] | SelectOptionGroup[]): SelectOption[] {\n if (!options || options.length === 0) {\n return [];\n }\n\n // Check if first item is a group\n const firstItem = options[0];\n if (firstItem && 'options' in firstItem) {\n return (options as SelectOptionGroup[]).flatMap((group) => group.options);\n }\n\n return options as SelectOption[];\n }\n}\n","<div class=\"lc-select-wrapper\">\n <div\n #selectTrigger\n [class]=\"selectClasses()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n >\n <div class=\"lc-select__value\">\n <span [class.lc-select__placeholder]=\"!selectedLabel()\">\n {{ displayValue() }}\n </span>\n </div>\n\n <div class=\"lc-select__icons\">\n @if (loading()) {\n <svg\n class=\"lc-select__spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n } @else if (value() && !isDisabled() && !multiple()) {\n <button\n type=\"button\"\n class=\"lc-select__clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n\n <svg\n class=\"lc-select__chevron\"\n [class.lc-select__chevron--open]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Dropdown Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"selectTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div #dropdownPanel class=\"lc-select__dropdown\" [class.lc-select__dropdown--open]=\"isOpen()\">\n @if (searchable()) {\n <div class=\"lc-select__search\">\n <input\n type=\"text\"\n class=\"lc-select__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"searchAriaLabel() || (ariaLabel() ? 'Search ' + ariaLabel() : 'Search options')\"\n [(ngModel)]=\"searchQuery\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div\n class=\"lc-select__options\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n >\n @if (filteredOptions().length === 0) {\n <div\n class=\"lc-select__option lc-select__option--no-results\"\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n >\n {{ noOptionsLabel() }}\n </div>\n } @else {\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays on the trigger/search, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-select__option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"isSelected(option) ? 'true' : 'false'\"\n [attr.aria-disabled]=\"option.disabled ? 'true' : null\"\n [class.lc-select__option--selected]=\"isSelected(option)\"\n [class.lc-select__option--highlighted]=\"highlightedIndex() === i\"\n [class.lc-select__option--disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(i)\"\n >\n @if (multiple()) {\n <!-- Purely visual: the option itself carries the selected state (role=option\n + aria-selected); the checkbox is inert so clicks land on the option. -->\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(option)\"\n [disabled]=\"option.disabled\"\n class=\"lc-select__checkbox\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"lc-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option) && !multiple()) {\n <svg\n class=\"lc-select__check\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-select__error\" [id]=\"selectId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-select__helper\" [id]=\"selectId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n"],"mappings":"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"}
@@ -210,7 +210,7 @@ var SplitPaneComponent = class SplitPaneComponent {
210
210
  outputs: { sizeChange: "sizeChange" },
211
211
  ngImport: i0,
212
212
  template: "<div class=\"lc-split-pane\" [class.lc-split-pane--stacked]=\"stacked()\">\n <div\n class=\"lc-split-pane__pane lc-split-pane__pane--start\"\n [style.flex-basis.px]=\"stacked() ? null : effectiveSize()\"\n >\n <ng-content select=\"[slot=start]\" />\n </div>\n\n @if (!stacked()) {\n <div\n class=\"lc-split-pane__separator\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"separatorLabel()\"\n [attr.aria-valuenow]=\"effectiveSize()\"\n [attr.aria-valuemin]=\"minSize()\"\n [attr.aria-valuemax]=\"ariaMax()\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n (dblclick)=\"reset()\"\n (keydown)=\"onKeydown($event)\"\n ></div>\n }\n\n <div class=\"lc-split-pane__pane lc-split-pane__pane--end\">\n <ng-content select=\"[slot=end]\" />\n </div>\n</div>\n",
213
- styles: [":host{display:block;height:100%;min-height:0}.lc-split-pane{display:flex;align-items:stretch;width:100%;height:100%;min-height:0}.lc-split-pane__pane{min-width:0;min-height:0;overflow:hidden}.lc-split-pane__pane--start{flex:0 0 auto}.lc-split-pane__pane--end{flex:1 1 auto}.lc-split-pane__separator{flex:0 0 auto;width:8px;cursor:col-resize;touch-action:none;position:relative;background:transparent;outline:none}.lc-split-pane__separator:before{content:\"\";position:absolute;inset-block:0;left:50%;width:1px;transform:translate(-50%);background:var(--color-border);transition:background-color .15s ease,width .15s ease}.lc-split-pane__separator:hover:before,.lc-split-pane__separator:active:before{width:3px;background:var(--color-primary-500)}.lc-split-pane__separator:focus-visible:before{width:3px;background:var(--color-primary-500)}.lc-split-pane--stacked{flex-direction:column}.lc-split-pane--stacked .lc-split-pane__pane--start{flex:0 0 auto}\n"],
213
+ styles: [":host{display:block;height:100%;min-height:0}.lc-split-pane{display:flex;align-items:stretch;width:100%;height:100%;min-height:0}.lc-split-pane__pane{min-width:0;min-height:0;overflow:hidden}.lc-split-pane__pane--start{flex:0 0 auto}.lc-split-pane__pane--end{flex:1 1 auto}.lc-split-pane__separator{flex:0 0 auto;width:8px;cursor:col-resize;touch-action:none;position:relative;background:transparent;outline:none}.lc-split-pane__separator:before{content:\"\";position:absolute;inset-block:0;left:50%;width:1px;transform:translate(-50%);background:var(--color-border);transition:background-color .15s ease,width .15s ease}.lc-split-pane__separator:hover:before,.lc-split-pane__separator:active:before{width:3px;background:var(--color-primary-500)}.lc-split-pane__separator:focus-visible:before{width:3px;background:var(--color-primary-500)}.lc-split-pane--stacked{flex-direction:column}.lc-split-pane--stacked .lc-split-pane__pane--start{flex:0 0 auto}@media(forced-colors:active){.lc-split-pane__separator:focus-visible{outline:2px solid Highlight;outline-offset:-2px}}\n"],
214
214
  changeDetection: i0.ChangeDetectionStrategy.OnPush
215
215
  });
216
216
  };
@@ -226,7 +226,7 @@ i0.ɵɵngDeclareClassMetadata({
226
226
  standalone: true,
227
227
  changeDetection: ChangeDetectionStrategy.OnPush,
228
228
  template: "<div class=\"lc-split-pane\" [class.lc-split-pane--stacked]=\"stacked()\">\n <div\n class=\"lc-split-pane__pane lc-split-pane__pane--start\"\n [style.flex-basis.px]=\"stacked() ? null : effectiveSize()\"\n >\n <ng-content select=\"[slot=start]\" />\n </div>\n\n @if (!stacked()) {\n <div\n class=\"lc-split-pane__separator\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"separatorLabel()\"\n [attr.aria-valuenow]=\"effectiveSize()\"\n [attr.aria-valuemin]=\"minSize()\"\n [attr.aria-valuemax]=\"ariaMax()\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n (dblclick)=\"reset()\"\n (keydown)=\"onKeydown($event)\"\n ></div>\n }\n\n <div class=\"lc-split-pane__pane lc-split-pane__pane--end\">\n <ng-content select=\"[slot=end]\" />\n </div>\n</div>\n",
229
- styles: [":host{display:block;height:100%;min-height:0}.lc-split-pane{display:flex;align-items:stretch;width:100%;height:100%;min-height:0}.lc-split-pane__pane{min-width:0;min-height:0;overflow:hidden}.lc-split-pane__pane--start{flex:0 0 auto}.lc-split-pane__pane--end{flex:1 1 auto}.lc-split-pane__separator{flex:0 0 auto;width:8px;cursor:col-resize;touch-action:none;position:relative;background:transparent;outline:none}.lc-split-pane__separator:before{content:\"\";position:absolute;inset-block:0;left:50%;width:1px;transform:translate(-50%);background:var(--color-border);transition:background-color .15s ease,width .15s ease}.lc-split-pane__separator:hover:before,.lc-split-pane__separator:active:before{width:3px;background:var(--color-primary-500)}.lc-split-pane__separator:focus-visible:before{width:3px;background:var(--color-primary-500)}.lc-split-pane--stacked{flex-direction:column}.lc-split-pane--stacked .lc-split-pane__pane--start{flex:0 0 auto}\n"]
229
+ styles: [":host{display:block;height:100%;min-height:0}.lc-split-pane{display:flex;align-items:stretch;width:100%;height:100%;min-height:0}.lc-split-pane__pane{min-width:0;min-height:0;overflow:hidden}.lc-split-pane__pane--start{flex:0 0 auto}.lc-split-pane__pane--end{flex:1 1 auto}.lc-split-pane__separator{flex:0 0 auto;width:8px;cursor:col-resize;touch-action:none;position:relative;background:transparent;outline:none}.lc-split-pane__separator:before{content:\"\";position:absolute;inset-block:0;left:50%;width:1px;transform:translate(-50%);background:var(--color-border);transition:background-color .15s ease,width .15s ease}.lc-split-pane__separator:hover:before,.lc-split-pane__separator:active:before{width:3px;background:var(--color-primary-500)}.lc-split-pane__separator:focus-visible:before{width:3px;background:var(--color-primary-500)}.lc-split-pane--stacked{flex-direction:column}.lc-split-pane--stacked .lc-split-pane__pane--start{flex:0 0 auto}@media(forced-colors:active){.lc-split-pane__separator:focus-visible{outline:2px solid Highlight;outline-offset:-2px}}\n"]
230
230
  }]
231
231
  }],
232
232
  ctorParameters: () => [],