{"version":3,"file":"forty-cdk-meter.mjs","sources":["../../../projects/forty-cdk/meter/src/meter-context.ts","../../../projects/forty-cdk/meter/src/meter.ts","../../../projects/forty-cdk/meter/src/meter-indicator.ts","../../../projects/forty-cdk/meter/src/forty-cdk-meter.ts"],"sourcesContent":["import { inject, InjectionToken, type Signal } from '@angular/core';\n\nimport { orphanContextError } from 'forty-cdk/core';\n\n/**\n * Quality bucket reflected on `data-quality`. Mirrors the HTML5 `<meter>`\n * algorithm:\n * - `optimum`: the value sits in the optimal region.\n * - `sub-optimum`: less than ideal but still acceptable.\n * - `even-less-good`: opposite side of optimum, the worst region.\n */\nexport type ForMeterQuality = 'optimum' | 'sub-optimum' | 'even-less-good';\n\n/** Read surface `[forMeter]` publishes through {@link FOR_METER_CONTEXT}. */\nexport interface ForMeterContext {\n  /** Clamped to `[min, max]`. Use this for any visual / ARIA reflection. */\n  readonly clampedValue: Signal<number>;\n  /**\n   * Sanitized lower bound (`min <= max`). Use this for any ARIA / visual\n   * reflection instead of the raw `min` input.\n   */\n  readonly sanitizedMin: Signal<number>;\n  /**\n   * Sanitized upper bound (`min <= max`). Use this for any ARIA / visual\n   * reflection instead of the raw `max` input.\n   */\n  readonly sanitizedMax: Signal<number>;\n  /** `0..100`. */\n  readonly percentage: Signal<number>;\n  /**\n   * {@link percentage} rounded to two decimals for the `data-percentage`\n   * reflection. Owned by the root so the indicator mirrors it instead of\n   * re-implementing the rounding.\n   */\n  readonly percentageAttr: Signal<number>;\n  readonly quality: Signal<ForMeterQuality>;\n}\n\nexport const FOR_METER_CONTEXT = new InjectionToken<ForMeterContext>('FOR_METER_CONTEXT');\n\n/**\n * Injects the nearest {@link ForMeterContext}, throwing a descriptive error\n * when used outside a `[forMeter]` element.\n *\n * @param piece Name of the calling directive, used in the error message.\n */\nexport function injectMeterContext(piece: string): ForMeterContext {\n  const ctx = inject(FOR_METER_CONTEXT, { optional: true });\n  if (!ctx) {\n    throw orphanContextError({\n      code: 'FORCDK-METER-001',\n      piece,\n      root: '[forMeter]',\n      token: 'FOR_METER_CONTEXT',\n    });\n  }\n  return ctx;\n}\n","import { computed, Directive, input } from '@angular/core';\n\nimport { clamp, hostAriaLabel } from 'forty-cdk/core';\nimport { FOR_METER_CONTEXT, type ForMeterContext, type ForMeterQuality } from './meter-context';\n\n/**\n * Headless implementation of the\n * [WAI-ARIA Meter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/meter/),\n * mirroring the HTML5 `<meter>` element semantics.\n *\n * A meter represents a known scalar measurement within a range — disk usage,\n * battery level, score, queue depth — **not** a task in progress. Use\n * `[forProgress]` for the latter.\n *\n * The optional `low`, `high`, and `optimum` inputs let you shape the \"quality\n * bucket\" reflected on `data-quality` (`optimum` / `sub-optimum` /\n * `even-less-good`) for CSS styling.\n *\n * @example\n * ```html\n * <div forMeter [value]=\"diskUsed()\" min=\"0\" max=\"100\" [low]=\"20\" [high]=\"80\" [optimum]=\"40\">\n *   <div forMeterIndicator></div>\n * </div>\n * ```\n */\n@Directive({\n  selector: '[forMeter]',\n  exportAs: 'forMeter',\n  host: {\n    role: 'meter',\n    '[attr.aria-valuemin]': 'sanitizedMin()',\n    '[attr.aria-valuemax]': 'sanitizedMax()',\n    '[attr.aria-valuenow]': 'clampedValue()',\n    '[attr.aria-valuetext]': 'ariaValueText()',\n    '[attr.aria-label]': 'resolvedAriaLabel()',\n    '[attr.data-quality]': 'quality()',\n    '[attr.data-value]': 'clampedValue()',\n    '[attr.data-min]': 'sanitizedMin()',\n    '[attr.data-max]': 'sanitizedMax()',\n    '[attr.data-percentage]': 'percentageAttr()',\n  },\n  providers: [{ provide: FOR_METER_CONTEXT, useExisting: ForMeter }],\n})\nexport class ForMeter implements ForMeterContext {\n  /**\n   * Current measurement. One-way `[value]` input: a meter is a display-only\n   * readout with no interactive value, so it exposes no two-way binding.\n   * Clamped to `[min, max]` for everything reflected on the host; the input\n   * retains the raw value so a consumer reading it back is not surprised.\n   */\n  readonly value = input<number>(0);\n\n  /** Lower bound. Defaults to `0`. */\n  readonly min = input<number>(0);\n\n  /** Upper bound. Defaults to `100`. */\n  readonly max = input<number>(100);\n\n  /**\n   * Optional lower boundary of the \"OK\" range. Values below `low` are\n   * treated as below the comfortable region. `null` means no lower band.\n   */\n  readonly low = input<number | null>(null);\n\n  /**\n   * Optional upper boundary of the \"OK\" range. Values above `high` are\n   * treated as above the comfortable region. `null` means no upper band.\n   */\n  readonly high = input<number | null>(null);\n\n  /**\n   * Optional point at which the value is considered ideal. Falls back to\n   * the midpoint of `[min, max]`. Determines which region is `optimum`,\n   * which is `sub-optimum`, and which is `even-less-good` (see HTML5 spec).\n   */\n  readonly optimum = input<number | null>(null);\n\n  /**\n   * Optional override for `aria-valuetext`. Receives the clamped value,\n   * `min`, and `max`.\n   */\n  readonly getValueLabel = input<((value: number, min: number, max: number) => string) | null>(\n    null,\n  );\n\n  /**\n   * Accessible name for the meter. Defaults to `null`, emitting no\n   * `aria-label`; prefer a visible label referenced via `aria-labelledby` when\n   * one exists.\n   */\n  readonly ariaLabel = input<string | null>(null);\n\n  protected readonly resolvedAriaLabel = hostAriaLabel(() => this.ariaLabel() || null);\n\n  readonly #range = computed(() => {\n    const min = this.min();\n    const max = Math.max(this.max(), min);\n    return { min, max };\n  });\n\n  /** Sanitized lower bound (`min <= max`), reflected to ARIA / data-\\*. */\n  readonly sanitizedMin = computed<number>(() => this.#range().min);\n\n  /** Sanitized upper bound (`min <= max`), reflected to ARIA / data-\\*. */\n  readonly sanitizedMax = computed<number>(() => this.#range().max);\n\n  readonly clampedValue = computed<number>(() => {\n    const { min, max } = this.#range();\n    return clamp(this.value(), min, max);\n  });\n\n  readonly percentage = computed<number>(() => {\n    const { min, max } = this.#range();\n    if (max === min) return 0;\n    return ((this.clampedValue() - min) / (max - min)) * 100;\n  });\n\n  readonly quality = computed<ForMeterQuality>(() => {\n    const { min, max } = this.#range();\n    let low = this.low() ?? min;\n    let high = this.high() ?? max;\n    if (low < min) low = min;\n    if (high > max) high = max;\n    if (low > high) low = high;\n    let optimum = this.optimum() ?? (min + max) / 2;\n    if (optimum < min) optimum = min;\n    if (optimum > max) optimum = max;\n    const v = this.clampedValue();\n\n    if (optimum < low) {\n      if (v < low) return 'optimum';\n      if (v <= high) return 'sub-optimum';\n      return 'even-less-good';\n    }\n    if (optimum > high) {\n      if (v > high) return 'optimum';\n      if (v >= low) return 'sub-optimum';\n      return 'even-less-good';\n    }\n    return v >= low && v <= high ? 'optimum' : 'sub-optimum';\n  });\n\n  readonly ariaValueText = computed<string | null>(() => {\n    const label = this.getValueLabel();\n    if (!label) return null;\n    const { min, max } = this.#range();\n    return label(this.clampedValue(), min, max);\n  });\n\n  readonly percentageAttr = computed<number>(() => Math.round(this.percentage() * 100) / 100);\n}\n","import { Directive } from '@angular/core';\n\nimport { injectMeterContext } from './meter-context';\n\n/**\n * Visual fill paired with `[forMeter]`. Reflects `data-quality`,\n * `data-percentage`, and the CSS custom property `--for-meter-percentage`\n * so the consumer can drive width / transform from CSS.\n */\n@Directive({\n  selector: '[forMeterIndicator]',\n  exportAs: 'forMeterIndicator',\n  host: {\n    '[attr.data-quality]': 'context.quality()',\n    '[attr.data-value]': 'context.clampedValue()',\n    '[attr.data-min]': 'context.sanitizedMin()',\n    '[attr.data-max]': 'context.sanitizedMax()',\n    '[attr.data-percentage]': 'context.percentageAttr()',\n    '[style.--for-meter-percentage]': 'percentageStyle()',\n  },\n})\nexport class ForMeterIndicator {\n  protected readonly context = injectMeterContext('ForMeterIndicator');\n\n  protected percentageStyle(): string {\n    return `${this.context.percentageAttr()}%`;\n  }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}