@oicl/openbridge-webcomponents 0.0.20260407101310 → 0.0.20260407112816

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 (67) hide show
  1. package/dist/building-blocks/instrument-radial/instrument-radial.d.ts +3 -0
  2. package/dist/building-blocks/instrument-radial/instrument-radial.d.ts.map +1 -1
  3. package/dist/building-blocks/instrument-radial/instrument-radial.js +50 -22
  4. package/dist/building-blocks/instrument-radial/instrument-radial.js.map +1 -1
  5. package/dist/navigation-instruments/compass/arrow.d.ts +1 -1
  6. package/dist/navigation-instruments/compass/arrow.d.ts.map +1 -1
  7. package/dist/navigation-instruments/compass/arrow.js +3 -3
  8. package/dist/navigation-instruments/compass/arrow.js.map +1 -1
  9. package/dist/navigation-instruments/compass/compass.d.ts +12 -6
  10. package/dist/navigation-instruments/compass/compass.d.ts.map +1 -1
  11. package/dist/navigation-instruments/compass/compass.js +29 -24
  12. package/dist/navigation-instruments/compass/compass.js.map +1 -1
  13. package/dist/navigation-instruments/compass-flat/compass-flat.d.ts +37 -1
  14. package/dist/navigation-instruments/compass-flat/compass-flat.d.ts.map +1 -1
  15. package/dist/navigation-instruments/compass-flat/compass-flat.js +34 -3
  16. package/dist/navigation-instruments/compass-flat/compass-flat.js.map +1 -1
  17. package/dist/navigation-instruments/compass-sector/compass-sector.css.js +34 -0
  18. package/dist/navigation-instruments/compass-sector/compass-sector.css.js.map +1 -0
  19. package/dist/navigation-instruments/compass-sector/compass-sector.d.ts +101 -0
  20. package/dist/navigation-instruments/compass-sector/compass-sector.d.ts.map +1 -0
  21. package/dist/navigation-instruments/compass-sector/compass-sector.js +404 -0
  22. package/dist/navigation-instruments/compass-sector/compass-sector.js.map +1 -0
  23. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.controller.d.ts +15 -2
  24. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.controller.d.ts.map +1 -1
  25. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.controller.js +50 -18
  26. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.controller.js.map +1 -1
  27. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.d.ts +40 -6
  28. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.d.ts.map +1 -1
  29. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.js +40 -47
  30. package/dist/navigation-instruments/rate-of-turn/rate-of-turn.js.map +1 -1
  31. package/dist/navigation-instruments/rate-of-turn/rot-renderer.d.ts +63 -0
  32. package/dist/navigation-instruments/rate-of-turn/rot-renderer.d.ts.map +1 -0
  33. package/dist/navigation-instruments/rate-of-turn/rot-renderer.js +211 -0
  34. package/dist/navigation-instruments/rate-of-turn/rot-renderer.js.map +1 -0
  35. package/dist/navigation-instruments/rot-sector/rot-sector.d.ts +10 -4
  36. package/dist/navigation-instruments/rot-sector/rot-sector.d.ts.map +1 -1
  37. package/dist/navigation-instruments/rot-sector/rot-sector.js +13 -3
  38. package/dist/navigation-instruments/rot-sector/rot-sector.js.map +1 -1
  39. package/dist/navigation-instruments/rudder/rudder.d.ts +4 -0
  40. package/dist/navigation-instruments/rudder/rudder.d.ts.map +1 -1
  41. package/dist/navigation-instruments/rudder/rudder.js +55 -19
  42. package/dist/navigation-instruments/rudder/rudder.js.map +1 -1
  43. package/dist/navigation-instruments/watch/advice.d.ts +3 -3
  44. package/dist/navigation-instruments/watch/advice.d.ts.map +1 -1
  45. package/dist/navigation-instruments/watch/advice.js +68 -16
  46. package/dist/navigation-instruments/watch/advice.js.map +1 -1
  47. package/dist/navigation-instruments/watch/tickmark.d.ts +2 -1
  48. package/dist/navigation-instruments/watch/tickmark.d.ts.map +1 -1
  49. package/dist/navigation-instruments/watch/tickmark.js +15 -13
  50. package/dist/navigation-instruments/watch/tickmark.js.map +1 -1
  51. package/dist/navigation-instruments/watch/watch.d.ts +29 -0
  52. package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
  53. package/dist/navigation-instruments/watch/watch.js +256 -44
  54. package/dist/navigation-instruments/watch/watch.js.map +1 -1
  55. package/dist/navigation-instruments/watch-flat/watch-flat.d.ts +29 -1
  56. package/dist/navigation-instruments/watch-flat/watch-flat.d.ts.map +1 -1
  57. package/dist/navigation-instruments/watch-flat/watch-flat.js +162 -17
  58. package/dist/navigation-instruments/watch-flat/watch-flat.js.map +1 -1
  59. package/dist/svghelpers/arc-frame.d.ts +42 -0
  60. package/dist/svghelpers/arc-frame.d.ts.map +1 -0
  61. package/dist/svghelpers/arc-frame.js +123 -0
  62. package/dist/svghelpers/arc-frame.js.map +1 -0
  63. package/package.json +1 -1
  64. package/dist/navigation-instruments/compass/rot.d.ts +0 -4
  65. package/dist/navigation-instruments/compass/rot.d.ts.map +0 -1
  66. package/dist/navigation-instruments/compass/rot.js +0 -11
  67. package/dist/navigation-instruments/compass/rot.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"rot-sector.js","sources":["../../../src/navigation-instruments/rot-sector/rot-sector.ts"],"sourcesContent":["import {LitElement, html} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport {property} from 'lit/decorators.js';\nimport {AdviceType} from '../watch/advice.js';\nimport {Priority} from '../types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport '../../building-blocks/instrument-radial/instrument-radial.js';\nimport {TickmarkStyle} from '../watch/tickmark.js';\n\nexport enum ObcGaugeRadialType {\n filled = 'filled',\n bar = 'bar',\n needle = 'needle',\n}\n\nexport interface GaugeRadialAdvice {\n minValue: number;\n maxValue: number;\n type: AdviceType;\n hinted: boolean;\n}\n\n/**\n * `<obc-rot-sector>` — Rate-of-turn sector gauge for rotational velocity.\n *\n * `ObcRotSector` is a thin wrapper around `<obc-instrument-radial>` that\n * displays a bipolar ±60° sector gauge showing rate of turn. The bottom\n * 50% of the circle is clipped, producing a compact sector arc. It inherits\n * a full setpoint property bundle from {@link SetpointMixin}, including\n * auto at-setpoint detection, dual-marker adjustment preview, and deadband\n * tuning.\n *\n * ## Features\n *\n * - **Bipolar sector**: Value range is symmetric around zero (−maxValue to\n * +maxValue), mapped to a ±60° arc.\n * - **Port/starboard coloring**: When `portStarboard` is true, positive\n * values render in starboard (green) and negative in port (red).\n * - **Bar display**: Always renders as a `bar` type — no needle or filled\n * variants.\n * - **Setpoint via mixin**: `setpoint`, `newSetpoint`, `touching`,\n * `autoAtSetpointDeadband`, `setpointOverride`, and all other setpoint\n * properties are provided by `SetpointMixin` and forwarded to the inner\n * `<obc-instrument-radial>`.\n * - **Advice zones**: Pass an array of {@link GaugeRadialAdvice} objects to\n * render caution/alert arcs on the gauge.\n *\n * ## Usage Guidelines\n *\n * - Set `maxValue` to define the symmetric ± range.\n * - Use `priority` to switch between regular and enhanced color palettes.\n * - Enable `portStarboard` to show directional coloring.\n * - Provide `primaryTickmarkInterval` and `secondaryTickmarkInterval` to\n * control tickmark density.\n * - Enable `showLabels` to show numeric labels at primary tickmarks.\n *\n * ## Best Practices\n *\n * - Prefer `SetpointMixin` properties (`setpoint`, `touching`, etc.) over\n * any legacy aliases — the mixin is the single source of truth.\n * - The sector is always bottom-clipped at 50%; do not change `clipBottom`\n * externally.\n *\n * ## Example\n *\n * ```html\n * <obc-rot-sector\n * value=\"15\"\n * maxValue=\"60\"\n * enhanced\n * portStarboard\n * showLabels\n * primaryTickmarkInterval=\"20\"\n * secondaryTickmarkInterval=\"10\"\n * setpoint=\"30\"\n * ></obc-rot-sector>\n * ```\n *\n * @element obc-rot-sector\n * @typedef {import('./rot-sector.js').GaugeRadialAdvice} GaugeRadialAdvice\n */\n@customElement('obc-rot-sector')\nexport class ObcRotSector extends SetpointMixin(LitElement) {\n @property({type: Number}) value = 0;\n @property({type: Number}) maxValue = 100;\n @property({type: Boolean}) showLabels: boolean = false;\n /** Whether to render tickmarks inside the ring. */\n @property({type: Boolean}) tickmarksInside: boolean = false;\n /**\n * Interval for primary tickmarks in value units.\n * When undefined or <= 0, no primary tickmarks are shown.\n */\n @property({type: Number}) primaryTickmarkInterval: number | undefined = 50;\n /**\n * Interval for secondary tickmarks in value units.\n * When undefined or <= 0, no secondary tickmarks are shown.\n */\n @property({type: Number}) secondaryTickmarkInterval: number | undefined = 10;\n /**\n * Interval for tertiary tickmarks in value units.\n * When undefined or <= 0, no tertiary tickmarks are shown.\n */\n @property({type: Number}) tertiaryTickmarkInterval: number | undefined =\n undefined;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Boolean}) portStarboard: boolean = false;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n @property({type: Array, attribute: false}) advices: GaugeRadialAdvice[] = [];\n\n getAngle(v: number): number {\n return (v / this.maxValue) * 60;\n }\n\n get _type(): ObcGaugeRadialType {\n return ObcGaugeRadialType.bar;\n }\n\n private get _barColor(): string {\n if (this.priority !== Priority.enhanced) {\n return 'var(--instrument-regular-tertiary-color)';\n }\n\n if (this.portStarboard) {\n if (this.value > 0) {\n return 'var(--instrument-starboard-secondary-color)';\n }\n return 'var(--instrument-port-secondary-color)';\n }\n\n return 'var(--instrument-enhanced-tertiary-color)';\n }\n\n override render() {\n const barColor = this._barColor;\n\n return html`\n <obc-instrument-radial\n .value=${this.value}\n .setpoint=${this.setpoint}\n .newSetpoint=${this.newSetpoint}\n .setpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .touching=${this.touching}\n .autoAtSetpoint=${this.autoAtSetpoint}\n .autoAtSetpointDeadband=${this.autoAtSetpointDeadband}\n .maxValue=${this.maxValue}\n .minValue=${-this.maxValue}\n .getAngle=${this.getAngle}\n .needleColor=${this._needleColor}\n .barColor=${barColor}\n .showLabels=${this.showLabels}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .primaryTickmarkInterval=${this.primaryTickmarkInterval}\n .secondaryTickmarkInterval=${this.secondaryTickmarkInterval}\n .tertiaryTickmarkInterval=${this.tertiaryTickmarkInterval}\n .type=${this._type}\n .needleType=${this._type}\n .advices=${this.advices}\n .clipBottom=${50}\n >\n </obc-instrument-radial>\n `;\n }\n\n private get _needleColor(): string {\n if (this.priority !== Priority.enhanced) {\n return 'var(--instrument-regular-secondary-color)';\n }\n\n if (this.portStarboard) {\n if (this.value > 0) {\n return 'var(--instrument-starboard-primary-color)';\n }\n if (this.value < 0) {\n return 'var(--instrument-port-primary-color)';\n }\n return 'var(--instrument-regular-secondary-color)';\n }\n\n return 'var(--instrument-enhanced-secondary-color)';\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rot-sector': ObcRotSector;\n }\n}\n"],"names":["ObcGaugeRadialType"],"mappings":";;;;;;;;;;;;;;;;;AASO,IAAK,uCAAAA,wBAAL;AACLA,sBAAA,QAAA,IAAS;AACTA,sBAAA,KAAA,IAAM;AACNA,sBAAA,QAAA,IAAS;AAHC,SAAAA;AAAA,GAAA,sBAAA,CAAA,CAAA;AAyEL,IAAM,eAAN,cAA2B,cAAc,UAAU,EAAE;AAAA,EAArD,cAAA;AAAA,UAAA,GAAA,SAAA;AACqB,SAAA,QAAQ;AACR,SAAA,WAAW;AACV,SAAA,aAAsB;AAEtB,SAAA,kBAA2B;AAK5B,SAAA,0BAA8C;AAK9C,SAAA,4BAAgD;AAKhD,SAAA,2BACxB;AACwB,SAAA,WAAqB,SAAS;AAC7B,SAAA,gBAAyB;AAC1B,SAAA,gBACxB,cAAc;AAC2B,SAAA,UAA+B,CAAA;AAAA,EAAC;AAAA,EAE3E,SAAS,GAAmB;AAC1B,WAAQ,IAAI,KAAK,WAAY;AAAA,EAC/B;AAAA,EAEA,IAAI,QAA4B;AAC9B,WAAO;AAAA,EACT;AAAA,EAEA,IAAY,YAAoB;AAC9B,QAAI,KAAK,aAAa,SAAS,UAAU;AACvC,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,eAAe;AACtB,UAAI,KAAK,QAAQ,GAAG;AAClB,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAES,SAAS;AAChB,UAAM,WAAW,KAAK;AAEtB,WAAO;AAAA;AAAA,iBAEM,KAAK,KAAK;AAAA,oBACP,KAAK,QAAQ;AAAA,uBACV,KAAK,WAAW;AAAA,kCACL,KAAK,sBAAsB;AAAA,4BACjC,KAAK,gBAAgB;AAAA,oBAC7B,KAAK,QAAQ;AAAA,0BACP,KAAK,cAAc;AAAA,kCACX,KAAK,sBAAsB;AAAA,oBACzC,KAAK,QAAQ;AAAA,oBACb,CAAC,KAAK,QAAQ;AAAA,oBACd,KAAK,QAAQ;AAAA,uBACV,KAAK,YAAY;AAAA,oBACpB,QAAQ;AAAA,sBACN,KAAK,UAAU;AAAA,2BACV,KAAK,eAAe;AAAA,yBACtB,KAAK,aAAa;AAAA,mCACR,KAAK,uBAAuB;AAAA,qCAC1B,KAAK,yBAAyB;AAAA,oCAC/B,KAAK,wBAAwB;AAAA,gBACjD,KAAK,KAAK;AAAA,sBACJ,KAAK,KAAK;AAAA,mBACb,KAAK,OAAO;AAAA,sBACT,EAAE;AAAA;AAAA;AAAA;AAAA,EAItB;AAAA,EAEA,IAAY,eAAuB;AACjC,QAAI,KAAK,aAAa,SAAS,UAAU;AACvC,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,eAAe;AACtB,UAAI,KAAK,QAAQ,GAAG;AAClB,eAAO;AAAA,MACT;AACA,UAAI,KAAK,QAAQ,GAAG;AAClB,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AACF;AApG4B,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GADb,aACe,WAAA,SAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAFb,aAEe,WAAA,YAAA,CAAA;AACC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAHd,aAGgB,WAAA,cAAA,CAAA;AAEA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GALd,aAKgB,WAAA,mBAAA,CAAA;AAKD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAVb,aAUe,WAAA,2BAAA,CAAA;AAKA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAfb,aAee,WAAA,6BAAA,CAAA;AAKA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GApBb,aAoBe,WAAA,4BAAA,CAAA;AAEA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAtBb,aAsBe,WAAA,YAAA,CAAA;AACC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAvBd,aAuBgB,WAAA,iBAAA,CAAA;AACD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAxBb,aAwBe,WAAA,iBAAA,CAAA;AAEiB,gBAAA;AAAA,EAA1C,SAAS,EAAC,MAAM,OAAO,WAAW,OAAM;AAAA,GA1B9B,aA0BgC,WAAA,WAAA,CAAA;AA1BhC,eAAN,gBAAA;AAAA,EADN,cAAc,gBAAgB;AAAA,GAClB,YAAA;"}
1
+ {"version":3,"file":"rot-sector.js","sources":["../../../src/navigation-instruments/rot-sector/rot-sector.ts"],"sourcesContent":["import {LitElement, html} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport {property} from 'lit/decorators.js';\nimport {AdviceType} from '../watch/advice.js';\nimport {Priority} from '../types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport '../../building-blocks/instrument-radial/instrument-radial.js';\nimport {TickmarkStyle} from '../watch/tickmark.js';\n\nexport enum ObcGaugeRadialType {\n filled = 'filled',\n bar = 'bar',\n needle = 'needle',\n}\n\nexport interface GaugeRadialAdvice {\n minValue: number;\n maxValue: number;\n type: AdviceType;\n hinted: boolean;\n}\n\n/**\n * `<obc-rot-sector>` — Rate-of-turn sector gauge for rotational velocity.\n *\n * `ObcRotSector` is a thin wrapper around `<obc-instrument-radial>` that\n * displays a bipolar sector gauge showing rate of turn. The arc extent is\n * configurable via `rotArcExtent` (default 60°), mapping the value range\n * (−maxValue to +maxValue) to ±rotArcExtent degrees. The bottom 50% of the\n * circle is clipped, producing a compact sector arc. When `zoomToFitArc`\n * is enabled, clipping is bypassed and the arc is enlarged to fill the\n * available space. It inherits\n * a full setpoint property bundle from {@link SetpointMixin}, including\n * auto at-setpoint detection, dual-marker adjustment preview, and deadband\n * tuning.\n *\n * ## Features\n *\n * - **Bipolar sector**: Value range is symmetric around zero (−maxValue to\n * +maxValue), mapped to a ±`rotArcExtent`° arc (default 60°).\n * - **Port/starboard coloring**: When `portStarboard` is true, positive\n * values render in starboard (green) and negative in port (red).\n * - **Bar display**: Always renders as a `bar` type — no needle or filled\n * variants.\n * - **Setpoint via mixin**: `setpoint`, `newSetpoint`, `touching`,\n * `autoAtSetpointDeadband`, `setpointOverride`, and all other setpoint\n * properties are provided by `SetpointMixin` and forwarded to the inner\n * `<obc-instrument-radial>`.\n * - **Advice zones**: Pass an array of {@link GaugeRadialAdvice} objects to\n * render caution/alert arcs on the gauge.\n *\n * ## Usage Guidelines\n *\n * - Set `maxValue` to define the symmetric ± range.\n * - Use `priority` to switch between regular and enhanced color palettes.\n * - Enable `portStarboard` to show directional coloring.\n * - Provide `primaryTickmarkInterval` and `secondaryTickmarkInterval` to\n * control tickmark density.\n * - Enable `showLabels` to show numeric labels at primary tickmarks.\n *\n * ## Best Practices\n *\n * - Prefer `SetpointMixin` properties (`setpoint`, `touching`, etc.) over\n * any legacy aliases — the mixin is the single source of truth.\n * - The sector is always bottom-clipped at 50%; do not change `clipBottom`\n * externally.\n *\n * ## Example\n *\n * ```html\n * <obc-rot-sector\n * value=\"15\"\n * maxValue=\"60\"\n * enhanced\n * portStarboard\n * showLabels\n * primaryTickmarkInterval=\"20\"\n * secondaryTickmarkInterval=\"10\"\n * setpoint=\"30\"\n * ></obc-rot-sector>\n * ```\n *\n * @element obc-rot-sector\n * @typedef {import('./rot-sector.js').GaugeRadialAdvice} GaugeRadialAdvice\n */\n@customElement('obc-rot-sector')\nexport class ObcRotSector extends SetpointMixin(LitElement) {\n @property({type: Number}) value = 0;\n @property({type: Number}) maxValue = 100;\n @property({type: Boolean}) showLabels: boolean = false;\n /** Whether to render tickmarks inside the ring. */\n @property({type: Boolean}) tickmarksInside: boolean = false;\n /**\n * Interval for primary tickmarks in value units.\n * When undefined or <= 0, no primary tickmarks are shown.\n */\n @property({type: Number}) primaryTickmarkInterval: number | undefined = 50;\n /**\n * Interval for secondary tickmarks in value units.\n * When undefined or <= 0, no secondary tickmarks are shown.\n */\n @property({type: Number}) secondaryTickmarkInterval: number | undefined = 10;\n /**\n * Interval for tertiary tickmarks in value units.\n * When undefined or <= 0, no tertiary tickmarks are shown.\n */\n @property({type: Number}) tertiaryTickmarkInterval: number | undefined =\n undefined;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Boolean}) portStarboard: boolean = false;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n @property({type: Array, attribute: false}) advices: GaugeRadialAdvice[] = [];\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n @property({type: Number}) rotArcExtent: number = 60;\n\n getAngle = (v: number): number => {\n if (!this.maxValue) return 0;\n return (v / this.maxValue) * this.rotArcExtent;\n };\n\n get _type(): ObcGaugeRadialType {\n return ObcGaugeRadialType.bar;\n }\n\n private get _barColor(): string {\n if (this.priority !== Priority.enhanced) {\n return 'var(--instrument-regular-tertiary-color)';\n }\n\n if (this.portStarboard) {\n if (this.value > 0) {\n return 'var(--instrument-starboard-secondary-color)';\n }\n return 'var(--instrument-port-secondary-color)';\n }\n\n return 'var(--instrument-enhanced-tertiary-color)';\n }\n\n override render() {\n const barColor = this._barColor;\n\n return html`\n <obc-instrument-radial\n .value=${this.value}\n .setpoint=${this.setpoint}\n .newSetpoint=${this.newSetpoint}\n .setpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .touching=${this.touching}\n .autoAtSetpoint=${this.autoAtSetpoint}\n .autoAtSetpointDeadband=${this.autoAtSetpointDeadband}\n .maxValue=${this.maxValue}\n .minValue=${-this.maxValue}\n .getAngle=${this.getAngle}\n .needleColor=${this._needleColor}\n .barColor=${barColor}\n .showLabels=${this.showLabels}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .primaryTickmarkInterval=${this.primaryTickmarkInterval}\n .secondaryTickmarkInterval=${this.secondaryTickmarkInterval}\n .tertiaryTickmarkInterval=${this.tertiaryTickmarkInterval}\n .type=${this._type}\n .needleType=${this._type}\n .advices=${this.advices}\n .clipBottom=${50}\n .zoomToFitArc=${this.zoomToFitArc}\n >\n </obc-instrument-radial>\n `;\n }\n\n private get _needleColor(): string {\n if (this.priority !== Priority.enhanced) {\n return 'var(--instrument-regular-secondary-color)';\n }\n\n if (this.portStarboard) {\n if (this.value > 0) {\n return 'var(--instrument-starboard-primary-color)';\n }\n if (this.value < 0) {\n return 'var(--instrument-port-primary-color)';\n }\n return 'var(--instrument-regular-secondary-color)';\n }\n\n return 'var(--instrument-enhanced-secondary-color)';\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rot-sector': ObcRotSector;\n }\n}\n"],"names":["ObcGaugeRadialType"],"mappings":"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"}
@@ -78,6 +78,10 @@ export declare class ObcRudder extends ObcRudder_base {
78
78
  priority: Priority;
79
79
  tickmarkStyle: TickmarkStyle;
80
80
  advices: AngleAdvice[];
81
+ zoomToFitArc: boolean;
82
+ private _radiusOffset;
83
+ private _arcFrame;
84
+ private get _needleTransform();
81
85
  getAngle(value: number): number;
82
86
  get barColor(): "var(--instrument-regular-secondary-color)" | "var(--instrument-enhanced-secondary-color)" | "var(--instrument-frame-tertiary-color)" | "var(--instrument-regular-tertiary-color)" | "var(--instrument-enhanced-tertiary-color)";
83
87
  renderNeedle(): import('lit-html').TemplateResult<2> | typeof nothing;
@@ -1 +1 @@
1
- {"version":3,"file":"rudder.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAa,OAAO,EAAM,MAAM,KAAK,CAAC;AAExD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAW,aAAa,EAAe,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAc,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAG5E,oBAAY,gBAAgB;IAC1B,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,qBACa,SAAU,SAAQ,cAAyB;IAC5B,KAAK,SAAK;IACV,OAAO,EAAE,gBAAgB,CAAwB;IACjD,QAAQ,SAAM;IACb,UAAU,EAAE,OAAO,CAAS;IACvD,mDAAmD;IACxB,eAAe,EAAE,OAAO,CAAS;IAClC,KAAK,EAAE,eAAe,CAA0B;IAChD,QAAQ,EAAE,QAAQ,CAAoB;IACtC,aAAa,EAAE,aAAa,CAC9B;IACmB,OAAO,EAAE,WAAW,EAAE,CAAM;IAEvE,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,IAAI,QAAQ,qOAsBX;IAED,YAAY;IA0BH,MAAM;IA4Gf,OAAgB,MAAM,0BAkBpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
1
+ {"version":3,"file":"rudder.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAa,OAAO,EAAM,MAAM,KAAK,CAAC;AAExD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAW,aAAa,EAAe,MAAM,sBAAsB,CAAC;AAM3E,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAc,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAO5E,oBAAY,gBAAgB;IAC1B,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,qBACa,SAAU,SAAQ,cAAyB;IAC5B,KAAK,SAAK;IACV,OAAO,EAAE,gBAAgB,CAAwB;IACjD,QAAQ,SAAM;IACb,UAAU,EAAE,OAAO,CAAS;IACvD,mDAAmD;IACxB,eAAe,EAAE,OAAO,CAAS;IAClC,KAAK,EAAE,eAAe,CAA0B;IAChD,QAAQ,EAAE,QAAQ,CAAoB;IACtC,aAAa,EAAE,aAAa,CAC9B;IACmB,OAAO,EAAE,WAAW,EAAE,CAAM;IAC5C,YAAY,EAAE,OAAO,CAAS;IAEzD,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,SAAS,CAAgC;IAEjD,OAAO,KAAK,gBAAgB,GAM3B;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,IAAI,QAAQ,qOAsBX;IAED,YAAY;IA0BH,MAAM;IAqIf,OAAgB,MAAM,0BAkBpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
@@ -1,11 +1,12 @@
1
1
  import { LitElement, nothing, svg, html, css } from "lit";
2
2
  import { property } from "lit/decorators.js";
3
- import { WatchCircleType } from "../watch/watch.js";
3
+ import { innerRingRadiusFor, WatchCircleType, OUTER_RING_RADIUS } from "../watch/watch.js";
4
4
  import { TickmarkStyle, TickmarkType } from "../watch/tickmark.js";
5
5
  import { InstrumentState, Priority } from "../types.js";
6
6
  import { SetpointMixin } from "../../svghelpers/setpoint-mixin.js";
7
7
  import { AdviceState } from "../watch/advice.js";
8
8
  import { customElement } from "../../decorator.js";
9
+ import { computeZoomToFitArcFrame } from "../../svghelpers/arc-frame.js";
9
10
  var __defProp = Object.defineProperty;
10
11
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
12
  var __decorateClass = (decorators, target, key, kind) => {
@@ -33,6 +34,15 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
33
34
  this.priority = Priority.regular;
34
35
  this.tickmarkStyle = TickmarkStyle.regular;
35
36
  this.advices = [];
37
+ this.zoomToFitArc = false;
38
+ this._radiusOffset = 0;
39
+ }
40
+ get _needleTransform() {
41
+ const rOff = this._radiusOffset;
42
+ if (rOff > 0) {
43
+ return `translate(-256, -256) rotate(${-this.angle} 256 256) translate(0, ${rOff})`;
44
+ }
45
+ return `translate(-256, -256) rotate(${-this.angle} 256 256)`;
36
46
  }
37
47
  getAngle(value) {
38
48
  return 180 - value;
@@ -62,7 +72,7 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
62
72
  }
63
73
  return svg`
64
74
  <path
65
- transform="translate(-256, -256) rotate(${-this.angle} 256 256)"
75
+ transform="${this._needleTransform}"
66
76
  d="M260.462 411.447C259.81 416.73 251.933 416.645 251.514 411.191L239.826 259.24C239.618 258.192 239.508 257.109 239.508 256C239.508 255.764 239.514 255.528 239.524 255.294L239.503 255.039L239.462 254.5H239.576C240.334 246.09 247.401 239.5 256.008 239.5C264.615 239.5 271.681 246.09 272.439 254.5H272.542L272.5 255.039L272.488 255.196C272.501 255.462 272.508 255.731 272.508 256C272.508 257.144 272.391 258.261 272.169 259.339L260.487 411.191L260.462 411.447Z"
67
77
  fill="${color}"
68
78
  stroke="var(--border-silhouette-color)"
@@ -70,6 +80,15 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
70
80
  `;
71
81
  }
72
82
  render() {
83
+ const maxAngle = Math.max(2, this.maxAngle);
84
+ const areas = [
85
+ {
86
+ startAngle: 180 - maxAngle,
87
+ endAngle: 180 + maxAngle,
88
+ roundInsideCut: true,
89
+ roundOutsideCut: true
90
+ }
91
+ ];
73
92
  const barAreas = [
74
93
  {
75
94
  startAngle: this.getAngle(0),
@@ -90,22 +109,22 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
90
109
  color: this.barColor
91
110
  },
92
111
  {
93
- angle: 180 - this.maxAngle,
112
+ angle: 180 - maxAngle,
94
113
  type: TickmarkType.secondary,
95
- text: this.showLabels ? this.maxAngle.toFixed(0) : void 0
114
+ text: this.showLabels ? maxAngle.toFixed(0) : void 0
96
115
  },
97
116
  {
98
- angle: 180 + this.maxAngle,
117
+ angle: 180 + maxAngle,
99
118
  type: TickmarkType.secondary,
100
- text: this.showLabels ? (-this.maxAngle).toFixed(0) : void 0
119
+ text: this.showLabels ? (-maxAngle).toFixed(0) : void 0
101
120
  }
102
121
  ];
103
122
  let helpAngle = null;
104
- if (this.maxAngle > 70) {
123
+ if (maxAngle > 70) {
105
124
  helpAngle = 45;
106
- } else if (this.maxAngle > 50) {
125
+ } else if (maxAngle > 50) {
107
126
  helpAngle = 30;
108
- } else if (this.maxAngle > 40) {
127
+ } else if (maxAngle > 40) {
109
128
  helpAngle = 22.5;
110
129
  }
111
130
  if (helpAngle !== null) {
@@ -131,19 +150,33 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
131
150
  state
132
151
  };
133
152
  });
153
+ let overlayViewBox;
154
+ if (this.zoomToFitArc) {
155
+ const ext = 48;
156
+ const targetSize = (176 + ext) * 2;
157
+ const frame = computeZoomToFitArcFrame({
158
+ areas,
159
+ outerRadius: OUTER_RING_RADIUS,
160
+ innerRadius: innerRingRadiusFor(WatchCircleType.double),
161
+ extension: ext,
162
+ targetSize
163
+ });
164
+ overlayViewBox = frame.viewBox;
165
+ this._radiusOffset = frame.radiusOffset;
166
+ this._arcFrame = frame;
167
+ } else {
168
+ overlayViewBox = "-224 -44.8 448 268.8";
169
+ this._radiusOffset = 0;
170
+ this._arcFrame = void 0;
171
+ }
134
172
  return html`
135
173
  <div class="container">
136
174
  <obc-watch
137
175
  .touching=${this.touching}
138
- .clipTop=${40}
139
- .areas=${[
140
- {
141
- startAngle: 180 - this.maxAngle,
142
- endAngle: 180 + this.maxAngle,
143
- roundInsideCut: true,
144
- roundOutsideCut: true
145
- }
146
- ]}
176
+ .clipTop=${this.zoomToFitArc ? 0 : 40}
177
+ .zoomToFitArc=${this.zoomToFitArc}
178
+ .arcFrame=${this._arcFrame}
179
+ .areas=${areas}
147
180
  .angleSetpoint=${setpointAngle}
148
181
  .newAngleSetpoint=${this.newSetpoint !== void 0 ? 180 - this.newSetpoint : void 0}
149
182
  .atAngleSetpoint=${this.computeAtSetpoint(this.angle)}
@@ -160,7 +193,7 @@ let ObcRudder = class extends SetpointMixin(LitElement) {
160
193
  .priority=${this.priority}
161
194
  .advices=${advices}
162
195
  ></obc-watch>
163
- <svg viewBox="-224 -44.8 448 268.8">${this.renderNeedle()}</svg>
196
+ <svg viewBox="${overlayViewBox}">${this.renderNeedle()}</svg>
164
197
  </div>
165
198
  `;
166
199
  }
@@ -211,6 +244,9 @@ __decorateClass([
211
244
  __decorateClass([
212
245
  property({ type: Array, attribute: false })
213
246
  ], ObcRudder.prototype, "advices", 2);
247
+ __decorateClass([
248
+ property({ type: Boolean })
249
+ ], ObcRudder.prototype, "zoomToFitArc", 2);
214
250
  ObcRudder = __decorateClass([
215
251
  customElement("obc-rudder")
216
252
  ], ObcRudder);
@@ -1 +1 @@
1
- {"version":3,"file":"rudder.js","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {Tickmark, TickmarkStyle, TickmarkType} from '../watch/tickmark.js';\nimport {WatchCircleType} from '../watch/watch.js';\nimport {InstrumentState, Priority} from '../types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\n\nexport enum ObcRudderVariant {\n Bar = 'bar',\n Needle = 'needle',\n}\n\n/**\n * `<obc-rudder>` — Half-circle rudder angle indicator.\n *\n * `ObcRudder` renders a semicircular gauge (40% top-clipped) that displays\n * the current rudder angle with a configurable bar or needle variant. The\n * gauge maps rudder angles to the lower arc of an `<obc-watch>` and overlays\n * a domain-specific needle when the `needle` variant is selected. It inherits\n * a full setpoint property bundle from {@link SetpointMixin}, including\n * auto at-setpoint detection, dual-marker adjustment preview, and deadband\n * tuning.\n *\n * ## Features\n *\n * - **Two display variants**: `bar` (filled arc from zero, default) and\n * `needle` (rotating pointer with silhouette stroke) via the `variant`\n * property.\n * - **Symmetric range**: The gauge spans ±`maxAngle` around the 180° center\n * (zero position at bottom).\n * - **State-aware colors**: Bar and needle colors adapt to the current\n * `InstrumentState` (active, loading, off) and `Priority` (enhanced, regular).\n * - **Setpoint via mixin**: `setpoint`, `newSetpoint`, `touching`,\n * `autoAtSetpointDeadband`, `setpointOverride`, and all other setpoint\n * properties are provided by `SetpointMixin` and forwarded to `<obc-watch>`.\n * - **Advice zones**: Pass an array of `AngleAdvice` objects to render\n * caution/alert arcs; triggered state is derived from whether the setpoint\n * falls inside the advice range.\n *\n * ## Usage Guidelines\n *\n * - Set `maxAngle` to define the symmetric ± range (default: 90°).\n * - Use `priority` to switch between regular and enhanced color palettes\n * (default: `Priority.regular`).\n * - Use `state` to control the instrument color palette.\n * - Enable `showLabels` to show numeric angle labels at tickmarks.\n * - Enable `tickmarksInside` to render tickmarks inside the ring.\n * - Choose `variant` to switch between bar and needle display.\n *\n * ## Best Practices\n *\n * - Prefer `SetpointMixin` properties (`setpoint`, `touching`, etc.) over\n * any legacy aliases — the mixin is the single source of truth.\n * - The top 40% is always clipped; overlay SVGs use the matching clipped\n * viewBox (`-224 -44.8 448 268.8`) for layer alignment.\n *\n * ## Example\n *\n * ```html\n * <obc-rudder\n * angle=\"12\"\n * maxAngle=\"45\"\n * variant=\"needle\"\n * state=\"in-command\"\n * showLabels\n * setpoint=\"15\"\n * ></obc-rudder>\n * ```\n *\n * @element obc-rudder\n */\n@customElement('obc-rudder')\nexport class ObcRudder extends SetpointMixin(LitElement) {\n @property({type: Number}) angle = 0;\n @property({type: String}) variant: ObcRudderVariant = ObcRudderVariant.Bar;\n @property({type: Number}) maxAngle = 90;\n @property({type: Boolean}) showLabels: boolean = false;\n /** Whether to render tickmarks inside the ring. */\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n @property({type: Array, attribute: false}) advices: AngleAdvice[] = [];\n\n getAngle(value: number) {\n return 180 - value;\n }\n\n get barColor() {\n if (this.variant === ObcRudderVariant.Needle) {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n } else {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n }\n\n renderNeedle() {\n if (this.variant === ObcRudderVariant.Bar) {\n return nothing;\n }\n let color: string;\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n color = 'var(--instrument-frame-tertiary-color)';\n } else {\n color =\n this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n return svg`\n <path\n transform=\"translate(-256, -256) rotate(${-this.angle} 256 256)\"\n d=\"M260.462 411.447C259.81 416.73 251.933 416.645 251.514 411.191L239.826 259.24C239.618 258.192 239.508 257.109 239.508 256C239.508 255.764 239.514 255.528 239.524 255.294L239.503 255.039L239.462 254.5H239.576C240.334 246.09 247.401 239.5 256.008 239.5C264.615 239.5 271.681 246.09 272.439 254.5H272.542L272.5 255.039L272.488 255.196C272.501 255.462 272.508 255.731 272.508 256C272.508 257.144 272.391 258.261 272.169 259.339L260.487 411.191L260.462 411.447Z\"\n fill=\"${color}\"\n stroke=\"var(--border-silhouette-color)\"\n />\n `;\n }\n\n override render() {\n const barAreas = [\n {\n startAngle: this.getAngle(0),\n endAngle: this.getAngle(this.angle),\n fillColor: this.barColor,\n },\n ];\n\n const setpointAngle =\n this.setpoint !== undefined ? 180 - this.setpoint : undefined;\n\n const tickmarks: Tickmark[] = [\n {\n angle: 180,\n type: TickmarkType.primary,\n text: this.showLabels ? '0' : undefined,\n },\n {\n angle: 180,\n type: TickmarkType.zeroLineThick,\n color: this.barColor,\n },\n {\n angle: 180 - this.maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? this.maxAngle.toFixed(0) : undefined,\n },\n {\n angle: 180 + this.maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? (-this.maxAngle).toFixed(0) : undefined,\n },\n ];\n\n let helpAngle: null | number = null;\n if (this.maxAngle > 70) {\n helpAngle = 45;\n } else if (this.maxAngle > 50) {\n helpAngle = 30;\n } else if (this.maxAngle > 40) {\n helpAngle = 22.5;\n }\n\n if (helpAngle !== null) {\n tickmarks.push({angle: 180 - helpAngle, type: TickmarkType.primary});\n tickmarks.push({angle: 180 + helpAngle, type: TickmarkType.primary});\n }\n\n const advices = this.advices.map<AngleAdviceRaw>((adv): AngleAdviceRaw => {\n const startAngle = 180 - adv.maxAngle;\n const endAngle = 180 - adv.minAngle;\n const isInRange =\n this.setpoint !== undefined &&\n this.setpoint >= adv.minAngle &&\n this.setpoint <= adv.maxAngle;\n let state;\n if (isInRange) {\n state = AdviceState.triggered;\n } else if (adv.hinted) {\n state = AdviceState.hinted;\n } else {\n state = AdviceState.regular;\n }\n return {\n minAngle: startAngle,\n maxAngle: endAngle,\n type: adv.type,\n state: state,\n };\n });\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .clipTop=${40}\n .areas=${[\n {\n startAngle: 180 - this.maxAngle,\n endAngle: 180 + this.maxAngle,\n roundInsideCut: true,\n roundOutsideCut: true,\n },\n ]}\n .angleSetpoint=${setpointAngle}\n .newAngleSetpoint=${this.newSetpoint !== undefined\n ? 180 - this.newSetpoint\n : undefined}\n .atAngleSetpoint=${this.computeAtSetpoint(this.angle)}\n .angleSetpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .animateSetpoint=${this.animateSetpoint}\n .padding=${48}\n .tickmarks=${tickmarks}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .watchCircleType=${WatchCircleType.double}\n .barAreas=${barAreas}\n .state=${this.state}\n .priority=${this.priority}\n .advices=${advices}\n ></obc-watch>\n <svg viewBox=\"-224 -44.8 448 268.8\">${this.renderNeedle()}</svg>\n </div>\n `;\n }\n\n static override styles = css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rudder': ObcRudder;\n }\n}\n"],"names":["ObcRudderVariant"],"mappings":"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"}
1
+ {"version":3,"file":"rudder.js","sources":["../../../src/navigation-instruments/rudder/rudder.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {Tickmark, TickmarkStyle, TickmarkType} from '../watch/tickmark.js';\nimport {\n OUTER_RING_RADIUS,\n WatchCircleType,\n innerRingRadiusFor,\n} from '../watch/watch.js';\nimport {InstrumentState, Priority} from '../types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport {AdviceState, AngleAdvice, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {\n computeZoomToFitArcFrame,\n type ZoomToFitArcFrame,\n} from '../../svghelpers/arc-frame.js';\n\nexport enum ObcRudderVariant {\n Bar = 'bar',\n Needle = 'needle',\n}\n\n/**\n * `<obc-rudder>` — Half-circle rudder angle indicator.\n *\n * `ObcRudder` renders a semicircular gauge (40% top-clipped) that displays\n * the current rudder angle with a configurable bar or needle variant. The\n * gauge maps rudder angles to the lower arc of an `<obc-watch>` and overlays\n * a domain-specific needle when the `needle` variant is selected. It inherits\n * a full setpoint property bundle from {@link SetpointMixin}, including\n * auto at-setpoint detection, dual-marker adjustment preview, and deadband\n * tuning.\n *\n * ## Features\n *\n * - **Two display variants**: `bar` (filled arc from zero, default) and\n * `needle` (rotating pointer with silhouette stroke) via the `variant`\n * property.\n * - **Symmetric range**: The gauge spans ±`maxAngle` around the 180° center\n * (zero position at bottom).\n * - **State-aware colors**: Bar and needle colors adapt to the current\n * `InstrumentState` (active, loading, off) and `Priority` (enhanced, regular).\n * - **Setpoint via mixin**: `setpoint`, `newSetpoint`, `touching`,\n * `autoAtSetpointDeadband`, `setpointOverride`, and all other setpoint\n * properties are provided by `SetpointMixin` and forwarded to `<obc-watch>`.\n * - **Advice zones**: Pass an array of `AngleAdvice` objects to render\n * caution/alert arcs; triggered state is derived from whether the setpoint\n * falls inside the advice range.\n *\n * ## Usage Guidelines\n *\n * - Set `maxAngle` to define the symmetric ± range (default: 90°).\n * - Use `priority` to switch between regular and enhanced color palettes\n * (default: `Priority.regular`).\n * - Use `state` to control the instrument color palette.\n * - Enable `showLabels` to show numeric angle labels at tickmarks.\n * - Enable `tickmarksInside` to render tickmarks inside the ring.\n * - Choose `variant` to switch between bar and needle display.\n *\n * ## Best Practices\n *\n * - Prefer `SetpointMixin` properties (`setpoint`, `touching`, etc.) over\n * any legacy aliases — the mixin is the single source of truth.\n * - The top 40% is always clipped; overlay SVGs use the matching clipped\n * viewBox (`-224 -44.8 448 268.8`) for layer alignment.\n *\n * ## Example\n *\n * ```html\n * <obc-rudder\n * angle=\"12\"\n * maxAngle=\"45\"\n * variant=\"needle\"\n * state=\"in-command\"\n * showLabels\n * setpoint=\"15\"\n * ></obc-rudder>\n * ```\n *\n * @element obc-rudder\n */\n@customElement('obc-rudder')\nexport class ObcRudder extends SetpointMixin(LitElement) {\n @property({type: Number}) angle = 0;\n @property({type: String}) variant: ObcRudderVariant = ObcRudderVariant.Bar;\n @property({type: Number}) maxAngle = 90;\n @property({type: Boolean}) showLabels: boolean = false;\n /** Whether to render tickmarks inside the ring. */\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n @property({type: Array, attribute: false}) advices: AngleAdvice[] = [];\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n\n private _radiusOffset = 0;\n private _arcFrame: ZoomToFitArcFrame | undefined;\n\n private get _needleTransform(): string {\n const rOff = this._radiusOffset;\n if (rOff > 0) {\n return `translate(-256, -256) rotate(${-this.angle} 256 256) translate(0, ${rOff})`;\n }\n return `translate(-256, -256) rotate(${-this.angle} 256 256)`;\n }\n\n getAngle(value: number) {\n return 180 - value;\n }\n\n get barColor() {\n if (this.variant === ObcRudderVariant.Needle) {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n } else {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'var(--instrument-frame-tertiary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n }\n\n renderNeedle() {\n if (this.variant === ObcRudderVariant.Bar) {\n return nothing;\n }\n let color: string;\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n color = 'var(--instrument-frame-tertiary-color)';\n } else {\n color =\n this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n return svg`\n <path\n transform=\"${this._needleTransform}\"\n d=\"M260.462 411.447C259.81 416.73 251.933 416.645 251.514 411.191L239.826 259.24C239.618 258.192 239.508 257.109 239.508 256C239.508 255.764 239.514 255.528 239.524 255.294L239.503 255.039L239.462 254.5H239.576C240.334 246.09 247.401 239.5 256.008 239.5C264.615 239.5 271.681 246.09 272.439 254.5H272.542L272.5 255.039L272.488 255.196C272.501 255.462 272.508 255.731 272.508 256C272.508 257.144 272.391 258.261 272.169 259.339L260.487 411.191L260.462 411.447Z\"\n fill=\"${color}\"\n stroke=\"var(--border-silhouette-color)\"\n />\n `;\n }\n\n override render() {\n const maxAngle = Math.max(2, this.maxAngle);\n const areas = [\n {\n startAngle: 180 - maxAngle,\n endAngle: 180 + maxAngle,\n roundInsideCut: true,\n roundOutsideCut: true,\n },\n ];\n\n const barAreas = [\n {\n startAngle: this.getAngle(0),\n endAngle: this.getAngle(this.angle),\n fillColor: this.barColor,\n },\n ];\n\n const setpointAngle =\n this.setpoint !== undefined ? 180 - this.setpoint : undefined;\n\n const tickmarks: Tickmark[] = [\n {\n angle: 180,\n type: TickmarkType.primary,\n text: this.showLabels ? '0' : undefined,\n },\n {\n angle: 180,\n type: TickmarkType.zeroLineThick,\n color: this.barColor,\n },\n {\n angle: 180 - maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? maxAngle.toFixed(0) : undefined,\n },\n {\n angle: 180 + maxAngle,\n type: TickmarkType.secondary,\n text: this.showLabels ? (-maxAngle).toFixed(0) : undefined,\n },\n ];\n\n let helpAngle: null | number = null;\n if (maxAngle > 70) {\n helpAngle = 45;\n } else if (maxAngle > 50) {\n helpAngle = 30;\n } else if (maxAngle > 40) {\n helpAngle = 22.5;\n }\n\n if (helpAngle !== null) {\n tickmarks.push({angle: 180 - helpAngle, type: TickmarkType.primary});\n tickmarks.push({angle: 180 + helpAngle, type: TickmarkType.primary});\n }\n\n const advices = this.advices.map<AngleAdviceRaw>((adv): AngleAdviceRaw => {\n const startAngle = 180 - adv.maxAngle;\n const endAngle = 180 - adv.minAngle;\n const isInRange =\n this.setpoint !== undefined &&\n this.setpoint >= adv.minAngle &&\n this.setpoint <= adv.maxAngle;\n let state;\n if (isInRange) {\n state = AdviceState.triggered;\n } else if (adv.hinted) {\n state = AdviceState.hinted;\n } else {\n state = AdviceState.regular;\n }\n return {\n minAngle: startAngle,\n maxAngle: endAngle,\n type: adv.type,\n state: state,\n };\n });\n\n let overlayViewBox: string;\n if (this.zoomToFitArc) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n const frame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerRingRadiusFor(WatchCircleType.double),\n extension: ext,\n targetSize,\n });\n overlayViewBox = frame.viewBox;\n this._radiusOffset = frame.radiusOffset;\n this._arcFrame = frame;\n } else {\n overlayViewBox = '-224 -44.8 448 268.8';\n this._radiusOffset = 0;\n this._arcFrame = undefined;\n }\n\n return html`\n <div class=\"container\">\n <obc-watch\n .touching=${this.touching}\n .clipTop=${this.zoomToFitArc ? 0 : 40}\n .zoomToFitArc=${this.zoomToFitArc}\n .arcFrame=${this._arcFrame}\n .areas=${areas}\n .angleSetpoint=${setpointAngle}\n .newAngleSetpoint=${this.newSetpoint !== undefined\n ? 180 - this.newSetpoint\n : undefined}\n .atAngleSetpoint=${this.computeAtSetpoint(this.angle)}\n .angleSetpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .animateSetpoint=${this.animateSetpoint}\n .padding=${48}\n .tickmarks=${tickmarks}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .watchCircleType=${WatchCircleType.double}\n .barAreas=${barAreas}\n .state=${this.state}\n .priority=${this.priority}\n .advices=${advices}\n ></obc-watch>\n <svg viewBox=\"${overlayViewBox}\">${this.renderNeedle()}</svg>\n </div>\n `;\n }\n\n static override styles = css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-rudder': ObcRudder;\n }\n}\n"],"names":["ObcRudderVariant"],"mappings":";;;;;;;;;;;;;;;;;;;AAkBO,IAAK,qCAAAA,sBAAL;AACLA,oBAAA,KAAA,IAAM;AACNA,oBAAA,QAAA,IAAS;AAFC,SAAAA;AAAA,GAAA,oBAAA,CAAA,CAAA;AAiEL,IAAM,YAAN,cAAwB,cAAc,UAAU,EAAE;AAAA,EAAlD,cAAA;AAAA,UAAA,GAAA,SAAA;AACqB,SAAA,QAAQ;AACR,SAAA,UAA4B;AAC5B,SAAA,WAAW;AACV,SAAA,aAAsB;AAEtB,SAAA,kBAA2B;AAC5B,SAAA,QAAyB,gBAAgB;AACzC,SAAA,WAAqB,SAAS;AAC9B,SAAA,gBACxB,cAAc;AAC2B,SAAA,UAAyB,CAAA;AACzC,SAAA,eAAwB;AAEnD,SAAQ,gBAAgB;AAAA,EAAA;AAAA,EAGxB,IAAY,mBAA2B;AACrC,UAAM,OAAO,KAAK;AAClB,QAAI,OAAO,GAAG;AACZ,aAAO,gCAAgC,CAAC,KAAK,KAAK,0BAA0B,IAAI;AAAA,IAClF;AACA,WAAO,gCAAgC,CAAC,KAAK,KAAK;AAAA,EACpD;AAAA,EAEA,SAAS,OAAe;AACtB,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,IAAI,WAAW;AACb,QAAI,KAAK,YAAY,UAAyB;AAC5C,UACE,KAAK,UAAU,gBAAgB,WAC/B,KAAK,UAAU,gBAAgB,KAC/B;AACA,eAAO;AAAA,MACT;AACA,aAAO,KAAK,aAAa,SAAS,WAC9B,8CACA;AAAA,IACN,OAAO;AACL,UACE,KAAK,UAAU,gBAAgB,WAC/B,KAAK,UAAU,gBAAgB,KAC/B;AACA,eAAO;AAAA,MACT;AACA,aAAO,KAAK,aAAa,SAAS,WAC9B,+CACA;AAAA,IACN;AAAA,EACF;AAAA,EAEA,eAAe;AACb,QAAI,KAAK,YAAY,OAAsB;AACzC,aAAO;AAAA,IACT;AACA,QAAI;AACJ,QACE,KAAK,UAAU,gBAAgB,WAC/B,KAAK,UAAU,gBAAgB,KAC/B;AACA,cAAQ;AAAA,IACV,OAAO;AACL,cACE,KAAK,aAAa,SAAS,WACvB,+CACA;AAAA,IACR;AACA,WAAO;AAAA;AAAA,qBAEU,KAAK,gBAAgB;AAAA;AAAA,gBAE1B,KAAK;AAAA;AAAA;AAAA;AAAA,EAInB;AAAA,EAES,SAAS;AAChB,UAAM,WAAW,KAAK,IAAI,GAAG,KAAK,QAAQ;AAC1C,UAAM,QAAQ;AAAA,MACZ;AAAA,QACE,YAAY,MAAM;AAAA,QAClB,UAAU,MAAM;AAAA,QAChB,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,MAAA;AAAA,IACnB;AAGF,UAAM,WAAW;AAAA,MACf;AAAA,QACE,YAAY,KAAK,SAAS,CAAC;AAAA,QAC3B,UAAU,KAAK,SAAS,KAAK,KAAK;AAAA,QAClC,WAAW,KAAK;AAAA,MAAA;AAAA,IAClB;AAGF,UAAM,gBACJ,KAAK,aAAa,SAAY,MAAM,KAAK,WAAW;AAEtD,UAAM,YAAwB;AAAA,MAC5B;AAAA,QACE,OAAO;AAAA,QACP,MAAM,aAAa;AAAA,QACnB,MAAM,KAAK,aAAa,MAAM;AAAA,MAAA;AAAA,MAEhC;AAAA,QACE,OAAO;AAAA,QACP,MAAM,aAAa;AAAA,QACnB,OAAO,KAAK;AAAA,MAAA;AAAA,MAEd;AAAA,QACE,OAAO,MAAM;AAAA,QACb,MAAM,aAAa;AAAA,QACnB,MAAM,KAAK,aAAa,SAAS,QAAQ,CAAC,IAAI;AAAA,MAAA;AAAA,MAEhD;AAAA,QACE,OAAO,MAAM;AAAA,QACb,MAAM,aAAa;AAAA,QACnB,MAAM,KAAK,cAAc,CAAC,UAAU,QAAQ,CAAC,IAAI;AAAA,MAAA;AAAA,IACnD;AAGF,QAAI,YAA2B;AAC/B,QAAI,WAAW,IAAI;AACjB,kBAAY;AAAA,IACd,WAAW,WAAW,IAAI;AACxB,kBAAY;AAAA,IACd,WAAW,WAAW,IAAI;AACxB,kBAAY;AAAA,IACd;AAEA,QAAI,cAAc,MAAM;AACtB,gBAAU,KAAK,EAAC,OAAO,MAAM,WAAW,MAAM,aAAa,SAAQ;AACnE,gBAAU,KAAK,EAAC,OAAO,MAAM,WAAW,MAAM,aAAa,SAAQ;AAAA,IACrE;AAEA,UAAM,UAAU,KAAK,QAAQ,IAAoB,CAAC,QAAwB;AACxE,YAAM,aAAa,MAAM,IAAI;AAC7B,YAAM,WAAW,MAAM,IAAI;AAC3B,YAAM,YACJ,KAAK,aAAa,UAClB,KAAK,YAAY,IAAI,YACrB,KAAK,YAAY,IAAI;AACvB,UAAI;AACJ,UAAI,WAAW;AACb,gBAAQ,YAAY;AAAA,MACtB,WAAW,IAAI,QAAQ;AACrB,gBAAQ,YAAY;AAAA,MACtB,OAAO;AACL,gBAAQ,YAAY;AAAA,MACtB;AACA,aAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU;AAAA,QACV,MAAM,IAAI;AAAA,QACV;AAAA,MAAA;AAAA,IAEJ,CAAC;AAED,QAAI;AACJ,QAAI,KAAK,cAAc;AACrB,YAAM,MAAM;AACZ,YAAM,cAAc,MAAM,OAAO;AACjC,YAAM,QAAQ,yBAAyB;AAAA,QACrC;AAAA,QACA,aAAa;AAAA,QACb,aAAa,mBAAmB,gBAAgB,MAAM;AAAA,QACtD,WAAW;AAAA,QACX;AAAA,MAAA,CACD;AACD,uBAAiB,MAAM;AACvB,WAAK,gBAAgB,MAAM;AAC3B,WAAK,YAAY;AAAA,IACnB,OAAO;AACL,uBAAiB;AACjB,WAAK,gBAAgB;AACrB,WAAK,YAAY;AAAA,IACnB;AAEA,WAAO;AAAA;AAAA;AAAA,sBAGW,KAAK,QAAQ;AAAA,qBACd,KAAK,eAAe,IAAI,EAAE;AAAA,0BACrB,KAAK,YAAY;AAAA,sBACrB,KAAK,SAAS;AAAA,mBACjB,KAAK;AAAA,2BACG,aAAa;AAAA,8BACV,KAAK,gBAAgB,SACrC,MAAM,KAAK,cACX,MAAS;AAAA,6BACM,KAAK,kBAAkB,KAAK,KAAK,CAAC;AAAA,yCACtB,KAAK,sBAAsB;AAAA,8BACtC,KAAK,gBAAgB;AAAA,6BACtB,KAAK,eAAe;AAAA,qBAC5B,EAAE;AAAA,uBACA,SAAS;AAAA,6BACH,KAAK,eAAe;AAAA,2BACtB,KAAK,aAAa;AAAA,6BAChB,gBAAgB,MAAM;AAAA,sBAC7B,QAAQ;AAAA,mBACX,KAAK,KAAK;AAAA,sBACP,KAAK,QAAQ;AAAA,qBACd,OAAO;AAAA;AAAA,wBAEJ,cAAc,KAAK,KAAK,aAAA,CAAc;AAAA;AAAA;AAAA,EAG5D;AAqBF;AAvOa,UAoNK,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAnNC,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GADb,UACe,WAAA,SAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAFb,UAEe,WAAA,WAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAHb,UAGe,WAAA,YAAA,CAAA;AACC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAJd,UAIgB,WAAA,cAAA,CAAA;AAEA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GANd,UAMgB,WAAA,mBAAA,CAAA;AACD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAPb,UAOe,WAAA,SAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GARb,UAQe,WAAA,YAAA,CAAA;AACA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GATb,UASe,WAAA,iBAAA,CAAA;AAEiB,gBAAA;AAAA,EAA1C,SAAS,EAAC,MAAM,OAAO,WAAW,OAAM;AAAA,GAX9B,UAWgC,WAAA,WAAA,CAAA;AAChB,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAZd,UAYgB,WAAA,gBAAA,CAAA;AAZhB,YAAN,gBAAA;AAAA,EADN,cAAc,YAAY;AAAA,GACd,SAAA;"}
@@ -1,4 +1,4 @@
1
- import { SVGTemplateResult } from 'lit';
1
+ import { SVGTemplateResult, nothing } from 'lit';
2
2
  export declare enum AdviceType {
3
3
  advice = "advice",
4
4
  caution = "caution"
@@ -22,6 +22,6 @@ export interface AngleAdvice {
22
22
  type: AdviceType;
23
23
  hinted: boolean;
24
24
  }
25
- export declare function adviceMask(minAngle: number, maxAngle: number, fill: string, stroke: string): SVGTemplateResult;
26
- export declare function renderAdvice(advice: AngleAdviceRaw): SVGTemplateResult;
25
+ export declare function adviceMask(minAngle: number, maxAngle: number, fill: string, stroke: string, radiusOffset?: number): SVGTemplateResult | typeof nothing;
26
+ export declare function renderAdvice(advice: AngleAdviceRaw, radiusOffset?: number): SVGTemplateResult | typeof nothing;
27
27
  //# sourceMappingURL=advice.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"advice.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/watch/advice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAe,MAAM,KAAK,CAAC;AAGpD,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,OAAO,YAAY;CACpB;AAED,oBAAY,WAAW;IACrB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,SAAS,cAAc;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAKD,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,iBAAiB,CAuBnB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,iBAAiB,CA8FtE"}
1
+ {"version":3,"file":"advice.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/watch/advice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAE,OAAO,EAAM,MAAM,KAAK,CAAC;AAGpD,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,OAAO,YAAY;CACpB;AAED,oBAAY,WAAW;IACrB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,SAAS,cAAc;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAKD,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,YAAY,SAAI,GACf,iBAAiB,GAAG,OAAO,OAAO,CA2BpC;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,cAAc,EACtB,YAAY,SAAI,GACf,iBAAiB,GAAG,OAAO,OAAO,CAiKpC"}
@@ -13,11 +13,14 @@ var AdviceState = /* @__PURE__ */ ((AdviceState2) => {
13
13
  })(AdviceState || {});
14
14
  const margin = (344 - 328) / 2 + 8;
15
15
  const deltaAngle = Math.atan2(margin, (344 + 328) / 2);
16
- function adviceMask(minAngle, maxAngle, fill, stroke) {
16
+ function adviceMask(minAngle, maxAngle, fill, stroke, radiusOffset = 0) {
17
+ const spanDeg = ((maxAngle - minAngle) % 360 + 360) % 360;
18
+ const spanRad = spanDeg * Math.PI / 180;
19
+ if (spanRad <= deltaAngle * 2) return nothing;
17
20
  const radl = minAngle * Math.PI / 180 + deltaAngle;
18
21
  const radh = maxAngle * Math.PI / 180 - deltaAngle;
19
- const r1 = 328 / 2;
20
- const r2 = 344 / 2;
22
+ const r1 = 328 / 2 + radiusOffset;
23
+ const r2 = 344 / 2 + radiusOffset;
21
24
  const R = (r2 - r1) / 2;
22
25
  const x1l = Math.sin(radl) * r1;
23
26
  const y1l = -Math.cos(radl) * r1;
@@ -35,7 +38,7 @@ function adviceMask(minAngle, maxAngle, fill, stroke) {
35
38
  Z`;
36
39
  return svg`<path d=${path} fill=${fill} stroke=${stroke} stroke-width="1" vector-effect="non-scaling-stroke" />`;
37
40
  }
38
- function renderAdvice(advice) {
41
+ function renderAdvice(advice, radiusOffset = 0) {
39
42
  if (advice.type === "caution") {
40
43
  let mainColor;
41
44
  let fillColor = null;
@@ -48,11 +51,33 @@ function renderAdvice(advice) {
48
51
  fillColor = "var(--alert-caution-color)";
49
52
  }
50
53
  const radialPattern = [];
51
- for (let i = 0; i < 180; i += 4) {
52
- radialPattern.push(svg`<g transform="rotate(${i}) translate(-256 -256) ">
54
+ if (radiusOffset > 0) {
55
+ const r1z = 328 / 2 + radiusOffset;
56
+ const r2z = 344 / 2 + radiusOffset;
57
+ const rAvg = (r1z + r2z) / 2;
58
+ const baseSpacing = 2 * Math.PI * 168 / 90;
59
+ const nLines = Math.round(2 * Math.PI * rAvg / baseSpacing);
60
+ const slant = 0.705;
61
+ const rInner = r1z - 12;
62
+ const rOuter = r2z + 12;
63
+ const halfDelta = Math.tan(slant) * (rOuter - rInner) / (2 * rAvg);
64
+ for (let j = 0; j < nLines; j++) {
65
+ const theta = j * 2 * Math.PI / nLines;
66
+ const x1 = rInner * Math.sin(theta - halfDelta);
67
+ const y1 = -rInner * Math.cos(theta - halfDelta);
68
+ const x2 = rOuter * Math.sin(theta + halfDelta);
69
+ const y2 = -rOuter * Math.cos(theta + halfDelta);
70
+ radialPattern.push(
71
+ svg`<line x1=${x1} y1=${y1} x2=${x2} y2=${y2} stroke=${mainColor} stroke-width="4"/>`
72
+ );
73
+ }
74
+ } else {
75
+ for (let i = 0; i < 180; i += 4) {
76
+ radialPattern.push(svg`<g transform="rotate(${i}) translate(-256 -256) ">
53
77
  <path d="M369.167 64.7317L144 194.732L142 191.268L367.167 61.2676L369.167 64.7317ZM369.167 320.732L144 450.732L142 447.267L367.167 317.267L369.167 320.732Z" fill=${mainColor}/>
54
78
  </g>
55
79
  `);
80
+ }
56
81
  }
57
82
  const maskId = `adviceMask-${advice.minAngle}-${advice.maxAngle}`;
58
83
  let tickmarkStyle = TickmarkStyle.regular;
@@ -61,22 +86,46 @@ function renderAdvice(advice) {
61
86
  } else if (advice.state === "triggered") {
62
87
  tickmarkStyle = TickmarkStyle.enhanced;
63
88
  }
89
+ const maskStroke = radiusOffset > 0 ? "none" : "black";
90
+ const maskShape = adviceMask(
91
+ advice.minAngle,
92
+ advice.maxAngle,
93
+ "white",
94
+ maskStroke,
95
+ radiusOffset
96
+ );
97
+ const outlineShape = adviceMask(
98
+ advice.minAngle,
99
+ advice.maxAngle,
100
+ "none",
101
+ mainColor,
102
+ radiusOffset
103
+ );
104
+ let mask;
105
+ let fillRect;
106
+ if (radiusOffset > 0) {
107
+ const extent = 344 / 2 + radiusOffset + 32;
108
+ mask = svg`<mask id=${maskId} maskUnits="userSpaceOnUse" x="${-extent}" y="${-extent}" width="${extent * 2}" height="${extent * 2}">${maskShape}</mask>`;
109
+ fillRect = fillColor ? svg`<rect x="${-extent}" y="${-extent}" width="${extent * 2}" height="${extent * 2}" fill="${fillColor}"/>` : nothing;
110
+ } else {
111
+ mask = svg`<mask id=${maskId}>${maskShape}</mask>`;
112
+ fillRect = fillColor ? svg`<rect x="-256" y="-256" width="512" height="512" fill="${fillColor}"/>` : nothing;
113
+ }
64
114
  return svg`
65
- <mask id=${maskId}>
66
- ${adviceMask(advice.minAngle, advice.maxAngle, "white", "black")}
67
- </mask>
115
+ ${mask}
68
116
  <g mask="url(#${maskId})">
69
- ${fillColor ? svg`<rect x="-256" y="-256" width="512" height="512" fill="${fillColor}"/>` : nothing}
117
+ ${fillRect}
70
118
  ${radialPattern}
71
119
  </g>
72
- ${adviceMask(advice.minAngle, advice.maxAngle, "none", mainColor)}
120
+ ${outlineShape}
73
121
  ${advice.hideMinTickmark ? nothing : tickmark(advice.minAngle, {
74
122
  size: TickmarkType.primary,
75
123
  style: tickmarkStyle,
76
124
  scale: 1,
77
125
  inside: false,
78
126
  textRadius: 0,
79
- maxDigits: 0
127
+ maxDigits: 0,
128
+ radiusOffset
80
129
  })}
81
130
  ${advice.hideMaxTickmark ? nothing : tickmark(advice.maxAngle, {
82
131
  size: TickmarkType.primary,
@@ -84,7 +133,8 @@ function renderAdvice(advice) {
84
133
  scale: 1,
85
134
  inside: false,
86
135
  textRadius: 0,
87
- maxDigits: 0
136
+ maxDigits: 0,
137
+ radiusOffset
88
138
  })}
89
139
  `;
90
140
  } else {
@@ -101,14 +151,15 @@ function renderAdvice(advice) {
101
151
  tickmarkStyle = TickmarkStyle.regular;
102
152
  }
103
153
  return svg`
104
- ${adviceMask(advice.minAngle, advice.maxAngle, advice.state === "triggered" ? mainColor : "none", mainColor)}
154
+ ${adviceMask(advice.minAngle, advice.maxAngle, advice.state === "triggered" ? mainColor : "none", mainColor, radiusOffset)}
105
155
  ${tickmark(advice.minAngle, {
106
156
  size: TickmarkType.primary,
107
157
  style: tickmarkStyle,
108
158
  scale: 1,
109
159
  inside: false,
110
160
  textRadius: 0,
111
- maxDigits: 0
161
+ maxDigits: 0,
162
+ radiusOffset
112
163
  })}
113
164
  ${tickmark(advice.maxAngle, {
114
165
  size: TickmarkType.primary,
@@ -116,7 +167,8 @@ function renderAdvice(advice) {
116
167
  scale: 1,
117
168
  inside: false,
118
169
  textRadius: 0,
119
- maxDigits: 0
170
+ maxDigits: 0,
171
+ radiusOffset
120
172
  })}
121
173
  `;
122
174
  }
@@ -1 +1 @@
1
- {"version":3,"file":"advice.js","sources":["../../../src/navigation-instruments/watch/advice.ts"],"sourcesContent":["import {SVGTemplateResult, nothing, svg} from 'lit';\nimport {TickmarkStyle, TickmarkType, tickmark} from './tickmark.js';\n\nexport enum AdviceType {\n advice = 'advice',\n caution = 'caution',\n}\n\nexport enum AdviceState {\n regular = 'regular',\n hinted = 'hinted',\n triggered = 'triggered',\n}\n\nexport interface AngleAdviceRaw {\n minAngle: number;\n maxAngle: number;\n type: AdviceType;\n state: AdviceState;\n hideMinTickmark?: boolean;\n hideMaxTickmark?: boolean;\n}\n\nexport interface AngleAdvice {\n minAngle: number;\n maxAngle: number;\n type: AdviceType;\n hinted: boolean;\n}\n\nconst margin = (344 - 328) / 2 + 8;\nconst deltaAngle = Math.atan2(margin, (344 + 328) / 2);\n\nexport function adviceMask(\n minAngle: number,\n maxAngle: number,\n fill: string,\n stroke: string\n): SVGTemplateResult {\n const radl = (minAngle * Math.PI) / 180 + deltaAngle;\n const radh = (maxAngle * Math.PI) / 180 - deltaAngle;\n const r1 = 328 / 2;\n const r2 = 344 / 2;\n const R = (r2 - r1) / 2;\n const x1l = Math.sin(radl) * r1;\n const y1l = -Math.cos(radl) * r1;\n const x2l = Math.sin(radl) * r2;\n const y2l = -Math.cos(radl) * r2;\n\n const x1h = Math.sin(radh) * r1;\n const y1h = -Math.cos(radh) * r1;\n const x2h = Math.sin(radh) * r2;\n const y2h = -Math.cos(radh) * r2;\n\n const path = `M ${x1l} ${y1l} \n A ${r1} ${r1} 0 0 1 ${x1h} ${y1h}\n A ${R} ${R} 0 0 0 ${x2h} ${y2h}\n A ${r2} ${r2} 0 0 0 ${x2l} ${y2l}\n A ${R} ${R} 0 0 0 ${x1l} ${y1l}\n Z`;\n return svg`<path d=${path} fill=${fill} stroke=${stroke} stroke-width=\"1\" vector-effect=\"non-scaling-stroke\" />`;\n}\n\nexport function renderAdvice(advice: AngleAdviceRaw): SVGTemplateResult {\n if (advice.type === AdviceType.caution) {\n let mainColor;\n let fillColor: string | null = null;\n if (advice.state === AdviceState.hinted) {\n mainColor = 'var(--instrument-frame-tertiary-color)';\n } else if (advice.state === AdviceState.regular) {\n mainColor = 'var(--instrument-tick-mark-tertiary-color)';\n } else {\n mainColor = 'var(--on-caution-active-color)';\n fillColor = 'var(--alert-caution-color)';\n }\n const radialPattern = [];\n for (let i = 0; i < 180; i += 4) {\n radialPattern.push(svg`<g transform=\"rotate(${i}) translate(-256 -256) \">\n <path d=\"M369.167 64.7317L144 194.732L142 191.268L367.167 61.2676L369.167 64.7317ZM369.167 320.732L144 450.732L142 447.267L367.167 317.267L369.167 320.732Z\" fill=${mainColor}/>\n </g>\n `);\n }\n const maskId = `adviceMask-${advice.minAngle}-${advice.maxAngle}`;\n let tickmarkStyle = TickmarkStyle.regular;\n if (advice.state === AdviceState.regular) {\n tickmarkStyle = TickmarkStyle.regular;\n } else if (advice.state === AdviceState.triggered) {\n tickmarkStyle = TickmarkStyle.enhanced;\n }\n\n return svg`\n <mask id=${maskId}>\n ${adviceMask(advice.minAngle, advice.maxAngle, 'white', 'black')}\n </mask>\n <g mask=\"url(#${maskId})\">\n ${fillColor ? svg`<rect x=\"-256\" y=\"-256\" width=\"512\" height=\"512\" fill=\"${fillColor}\"/>` : nothing}\n ${radialPattern}\n </g>\n ${adviceMask(advice.minAngle, advice.maxAngle, 'none', mainColor)}\n ${\n advice.hideMinTickmark\n ? nothing\n : tickmark(advice.minAngle, {\n size: TickmarkType.primary,\n style: tickmarkStyle,\n scale: 1,\n inside: false,\n textRadius: 0,\n maxDigits: 0,\n })\n }\n ${\n advice.hideMaxTickmark\n ? nothing\n : tickmark(advice.maxAngle, {\n size: TickmarkType.primary,\n style: tickmarkStyle,\n scale: 1,\n inside: false,\n textRadius: 0,\n maxDigits: 0,\n })\n }\n `;\n } else {\n let mainColor;\n let tickmarkStyle;\n if (advice.state === AdviceState.hinted) {\n mainColor = 'var(--instrument-frame-tertiary-color)';\n tickmarkStyle = TickmarkStyle.regular;\n } else if (advice.state === AdviceState.regular) {\n mainColor = 'var(--instrument-regular-secondary-color)';\n tickmarkStyle = TickmarkStyle.regular;\n } else {\n mainColor = 'var(--instrument-enhanced-secondary-color)';\n tickmarkStyle = TickmarkStyle.regular;\n }\n return svg`\n ${adviceMask(advice.minAngle, advice.maxAngle, advice.state === AdviceState.triggered ? mainColor : 'none', mainColor)}\n ${tickmark(advice.minAngle, {\n size: TickmarkType.primary,\n style: tickmarkStyle,\n scale: 1,\n inside: false,\n textRadius: 0,\n maxDigits: 0,\n })}\n ${tickmark(advice.maxAngle, {\n size: TickmarkType.primary,\n style: tickmarkStyle,\n scale: 1,\n inside: false,\n textRadius: 0,\n maxDigits: 0,\n })}\n `;\n }\n}\n"],"names":["AdviceType","AdviceState"],"mappings":"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"}
1
+ {"version":3,"file":"advice.js","sources":["../../../src/navigation-instruments/watch/advice.ts"],"sourcesContent":["import {SVGTemplateResult, nothing, svg} from 'lit';\nimport {TickmarkStyle, TickmarkType, tickmark} from './tickmark.js';\n\nexport enum AdviceType {\n advice = 'advice',\n caution = 'caution',\n}\n\nexport enum AdviceState {\n regular = 'regular',\n hinted = 'hinted',\n triggered = 'triggered',\n}\n\nexport interface AngleAdviceRaw {\n minAngle: number;\n maxAngle: number;\n type: AdviceType;\n state: AdviceState;\n hideMinTickmark?: boolean;\n hideMaxTickmark?: boolean;\n}\n\nexport interface AngleAdvice {\n minAngle: number;\n maxAngle: number;\n type: AdviceType;\n hinted: boolean;\n}\n\nconst margin = (344 - 328) / 2 + 8;\nconst deltaAngle = Math.atan2(margin, (344 + 328) / 2);\n\nexport function adviceMask(\n minAngle: number,\n maxAngle: number,\n fill: string,\n stroke: string,\n radiusOffset = 0\n): SVGTemplateResult | typeof nothing {\n const spanDeg = (((maxAngle - minAngle) % 360) + 360) % 360;\n const spanRad = (spanDeg * Math.PI) / 180;\n if (spanRad <= deltaAngle * 2) return nothing;\n\n const radl = (minAngle * Math.PI) / 180 + deltaAngle;\n const radh = (maxAngle * Math.PI) / 180 - deltaAngle;\n const r1 = 328 / 2 + radiusOffset;\n const r2 = 344 / 2 + radiusOffset;\n const R = (r2 - r1) / 2;\n const x1l = Math.sin(radl) * r1;\n const y1l = -Math.cos(radl) * r1;\n const x2l = Math.sin(radl) * r2;\n const y2l = -Math.cos(radl) * r2;\n\n const x1h = Math.sin(radh) * r1;\n const y1h = -Math.cos(radh) * r1;\n const x2h = Math.sin(radh) * r2;\n const y2h = -Math.cos(radh) * r2;\n\n const path = `M ${x1l} ${y1l} \n A ${r1} ${r1} 0 0 1 ${x1h} ${y1h}\n A ${R} ${R} 0 0 0 ${x2h} ${y2h}\n A ${r2} ${r2} 0 0 0 ${x2l} ${y2l}\n A ${R} ${R} 0 0 0 ${x1l} ${y1l}\n Z`;\n return svg`<path d=${path} fill=${fill} stroke=${stroke} stroke-width=\"1\" vector-effect=\"non-scaling-stroke\" />`;\n}\n\nexport function renderAdvice(\n advice: AngleAdviceRaw,\n radiusOffset = 0\n): SVGTemplateResult | typeof nothing {\n if (advice.type === AdviceType.caution) {\n let mainColor;\n let fillColor: string | null = null;\n if (advice.state === AdviceState.hinted) {\n mainColor = 'var(--instrument-frame-tertiary-color)';\n } else if (advice.state === AdviceState.regular) {\n mainColor = 'var(--instrument-tick-mark-tertiary-color)';\n } else {\n mainColor = 'var(--on-caution-active-color)';\n fillColor = 'var(--alert-caution-color)';\n }\n const radialPattern = [];\n if (radiusOffset > 0) {\n // Draw hatch lines directly as short segments crossing the enlarged\n // annular band. The radial-fan-tile approach (rotate + translate) causes\n // artifacts at large offsets because each tile's center orbits the origin,\n // making stripes cross the band at inconsistent widths/angles.\n //\n // Geometry is derived from the original pattern at base radius:\n // - 45 tiles × 2 stripes = 90 crossings over 360° → 4° arc step\n // - At base rAvg 168, arc spacing ≈ 11.73 px\n // - Stripe slant ≈ 40.4° from radial direction\n // - Perpendicular line width ≈ 4 px\n const r1z = 328 / 2 + radiusOffset;\n const r2z = 344 / 2 + radiusOffset;\n const rAvg = (r1z + r2z) / 2;\n const baseSpacing = (2 * Math.PI * 168) / 90;\n const nLines = Math.round((2 * Math.PI * rAvg) / baseSpacing);\n const slant = 0.705; // 40.4° from radial direction\n // Extend lines well beyond r1z/r2z so slanted endpoints fully cover\n // the annular band edges. The mask clips any overshoot.\n const rInner = r1z - 12;\n const rOuter = r2z + 12;\n const halfDelta = (Math.tan(slant) * (rOuter - rInner)) / (2 * rAvg);\n for (let j = 0; j < nLines; j++) {\n const theta = (j * 2 * Math.PI) / nLines;\n const x1 = rInner * Math.sin(theta - halfDelta);\n const y1 = -rInner * Math.cos(theta - halfDelta);\n const x2 = rOuter * Math.sin(theta + halfDelta);\n const y2 = -rOuter * Math.cos(theta + halfDelta);\n radialPattern.push(\n svg`<line x1=${x1} y1=${y1} x2=${x2} y2=${y2} stroke=${mainColor} stroke-width=\"4\"/>`\n );\n }\n } else {\n for (let i = 0; i < 180; i += 4) {\n radialPattern.push(svg`<g transform=\"rotate(${i}) translate(-256 -256) \">\n <path d=\"M369.167 64.7317L144 194.732L142 191.268L367.167 61.2676L369.167 64.7317ZM369.167 320.732L144 450.732L142 447.267L367.167 317.267L369.167 320.732Z\" fill=${mainColor}/>\n </g>\n `);\n }\n }\n const maskId = `adviceMask-${advice.minAngle}-${advice.maxAngle}`;\n let tickmarkStyle = TickmarkStyle.regular;\n if (advice.state === AdviceState.regular) {\n tickmarkStyle = TickmarkStyle.regular;\n } else if (advice.state === AdviceState.triggered) {\n tickmarkStyle = TickmarkStyle.enhanced;\n }\n\n const maskStroke = radiusOffset > 0 ? 'none' : 'black';\n const maskShape = adviceMask(\n advice.minAngle,\n advice.maxAngle,\n 'white',\n maskStroke,\n radiusOffset\n );\n const outlineShape = adviceMask(\n advice.minAngle,\n advice.maxAngle,\n 'none',\n mainColor,\n radiusOffset\n );\n\n let mask;\n let fillRect;\n if (radiusOffset > 0) {\n const extent = 344 / 2 + radiusOffset + 32;\n mask = svg`<mask id=${maskId} maskUnits=\"userSpaceOnUse\" x=\"${-extent}\" y=\"${-extent}\" width=\"${extent * 2}\" height=\"${extent * 2}\">${maskShape}</mask>`;\n fillRect = fillColor\n ? svg`<rect x=\"${-extent}\" y=\"${-extent}\" width=\"${extent * 2}\" height=\"${extent * 2}\" fill=\"${fillColor}\"/>`\n : nothing;\n } else {\n mask = svg`<mask id=${maskId}>${maskShape}</mask>`;\n fillRect = fillColor\n ? svg`<rect x=\"-256\" y=\"-256\" width=\"512\" height=\"512\" fill=\"${fillColor}\"/>`\n : nothing;\n }\n\n return svg`\n ${mask}\n <g mask=\"url(#${maskId})\">\n ${fillRect}\n ${radialPattern}\n </g>\n ${outlineShape}\n ${\n advice.hideMinTickmark\n ? nothing\n : tickmark(advice.minAngle, {\n size: TickmarkType.primary,\n style: tickmarkStyle,\n scale: 1,\n inside: false,\n textRadius: 0,\n maxDigits: 0,\n radiusOffset,\n })\n }\n ${\n advice.hideMaxTickmark\n ? nothing\n : tickmark(advice.maxAngle, {\n size: TickmarkType.primary,\n style: tickmarkStyle,\n scale: 1,\n inside: false,\n textRadius: 0,\n maxDigits: 0,\n radiusOffset,\n })\n }\n `;\n } else {\n let mainColor;\n let tickmarkStyle;\n if (advice.state === AdviceState.hinted) {\n mainColor = 'var(--instrument-frame-tertiary-color)';\n tickmarkStyle = TickmarkStyle.regular;\n } else if (advice.state === AdviceState.regular) {\n mainColor = 'var(--instrument-regular-secondary-color)';\n tickmarkStyle = TickmarkStyle.regular;\n } else {\n mainColor = 'var(--instrument-enhanced-secondary-color)';\n tickmarkStyle = TickmarkStyle.regular;\n }\n return svg`\n ${adviceMask(advice.minAngle, advice.maxAngle, advice.state === AdviceState.triggered ? mainColor : 'none', mainColor, radiusOffset)}\n ${tickmark(advice.minAngle, {\n size: TickmarkType.primary,\n style: tickmarkStyle,\n scale: 1,\n inside: false,\n textRadius: 0,\n maxDigits: 0,\n radiusOffset,\n })}\n ${tickmark(advice.maxAngle, {\n size: TickmarkType.primary,\n style: tickmarkStyle,\n scale: 1,\n inside: false,\n textRadius: 0,\n maxDigits: 0,\n radiusOffset,\n })}\n `;\n }\n}\n"],"names":["AdviceType","AdviceState"],"mappings":";;AAGO,IAAK,+BAAAA,gBAAL;AACLA,cAAA,QAAA,IAAS;AACTA,cAAA,SAAA,IAAU;AAFA,SAAAA;AAAA,GAAA,cAAA,CAAA,CAAA;AAKL,IAAK,gCAAAC,iBAAL;AACLA,eAAA,SAAA,IAAU;AACVA,eAAA,QAAA,IAAS;AACTA,eAAA,WAAA,IAAY;AAHF,SAAAA;AAAA,GAAA,eAAA,CAAA,CAAA;AAsBZ,MAAM,UAAU,MAAM,OAAO,IAAI;AACjC,MAAM,aAAa,KAAK,MAAM,SAAS,MAAM,OAAO,CAAC;AAE9C,SAAS,WACd,UACA,UACA,MACA,QACA,eAAe,GACqB;AACpC,QAAM,YAAa,WAAW,YAAY,MAAO,OAAO;AACxD,QAAM,UAAW,UAAU,KAAK,KAAM;AACtC,MAAI,WAAW,aAAa,EAAG,QAAO;AAEtC,QAAM,OAAQ,WAAW,KAAK,KAAM,MAAM;AAC1C,QAAM,OAAQ,WAAW,KAAK,KAAM,MAAM;AAC1C,QAAM,KAAK,MAAM,IAAI;AACrB,QAAM,KAAK,MAAM,IAAI;AACrB,QAAM,KAAK,KAAK,MAAM;AACtB,QAAM,MAAM,KAAK,IAAI,IAAI,IAAI;AAC7B,QAAM,MAAM,CAAC,KAAK,IAAI,IAAI,IAAI;AAC9B,QAAM,MAAM,KAAK,IAAI,IAAI,IAAI;AAC7B,QAAM,MAAM,CAAC,KAAK,IAAI,IAAI,IAAI;AAE9B,QAAM,MAAM,KAAK,IAAI,IAAI,IAAI;AAC7B,QAAM,MAAM,CAAC,KAAK,IAAI,IAAI,IAAI;AAC9B,QAAM,MAAM,KAAK,IAAI,IAAI,IAAI;AAC7B,QAAM,MAAM,CAAC,KAAK,IAAI,IAAI,IAAI;AAE9B,QAAM,OAAO,KAAK,GAAG,IAAI,GAAG;AAAA,wBACN,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG;AAAA,wBAC5B,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG;AAAA,wBAC1B,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG;AAAA,wBAC5B,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG;AAAA;AAEhD,SAAO,cAAc,IAAI,SAAS,IAAI,WAAW,MAAM;AACzD;AAEO,SAAS,aACd,QACA,eAAe,GACqB;AACpC,MAAI,OAAO,SAAS,WAAoB;AACtC,QAAI;AACJ,QAAI,YAA2B;AAC/B,QAAI,OAAO,UAAU,UAAoB;AACvC,kBAAY;AAAA,IACd,WAAW,OAAO,UAAU,WAAqB;AAC/C,kBAAY;AAAA,IACd,OAAO;AACL,kBAAY;AACZ,kBAAY;AAAA,IACd;AACA,UAAM,gBAAgB,CAAA;AACtB,QAAI,eAAe,GAAG;AAWpB,YAAM,MAAM,MAAM,IAAI;AACtB,YAAM,MAAM,MAAM,IAAI;AACtB,YAAM,QAAQ,MAAM,OAAO;AAC3B,YAAM,cAAe,IAAI,KAAK,KAAK,MAAO;AAC1C,YAAM,SAAS,KAAK,MAAO,IAAI,KAAK,KAAK,OAAQ,WAAW;AAC5D,YAAM,QAAQ;AAGd,YAAM,SAAS,MAAM;AACrB,YAAM,SAAS,MAAM;AACrB,YAAM,YAAa,KAAK,IAAI,KAAK,KAAK,SAAS,WAAY,IAAI;AAC/D,eAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,cAAM,QAAS,IAAI,IAAI,KAAK,KAAM;AAClC,cAAM,KAAK,SAAS,KAAK,IAAI,QAAQ,SAAS;AAC9C,cAAM,KAAK,CAAC,SAAS,KAAK,IAAI,QAAQ,SAAS;AAC/C,cAAM,KAAK,SAAS,KAAK,IAAI,QAAQ,SAAS;AAC9C,cAAM,KAAK,CAAC,SAAS,KAAK,IAAI,QAAQ,SAAS;AAC/C,sBAAc;AAAA,UACZ,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,SAAS;AAAA,QAAA;AAAA,MAEpE;AAAA,IACF,OAAO;AACL,eAAS,IAAI,GAAG,IAAI,KAAK,KAAK,GAAG;AAC/B,sBAAc,KAAK,2BAA2B,CAAC;AAAA,gLACyH,SAAS;AAAA;AAAA,aAE5K;AAAA,MACP;AAAA,IACF;AACA,UAAM,SAAS,cAAc,OAAO,QAAQ,IAAI,OAAO,QAAQ;AAC/D,QAAI,gBAAgB,cAAc;AAClC,QAAI,OAAO,UAAU,WAAqB;AACxC,sBAAgB,cAAc;AAAA,IAChC,WAAW,OAAO,UAAU,aAAuB;AACjD,sBAAgB,cAAc;AAAA,IAChC;AAEA,UAAM,aAAa,eAAe,IAAI,SAAS;AAC/C,UAAM,YAAY;AAAA,MAChB,OAAO;AAAA,MACP,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAEF,UAAM,eAAe;AAAA,MACnB,OAAO;AAAA,MACP,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAGF,QAAI;AACJ,QAAI;AACJ,QAAI,eAAe,GAAG;AACpB,YAAM,SAAS,MAAM,IAAI,eAAe;AACxC,aAAO,eAAe,MAAM,kCAAkC,CAAC,MAAM,QAAQ,CAAC,MAAM,YAAY,SAAS,CAAC,aAAa,SAAS,CAAC,KAAK,SAAS;AAC/I,iBAAW,YACP,eAAe,CAAC,MAAM,QAAQ,CAAC,MAAM,YAAY,SAAS,CAAC,aAAa,SAAS,CAAC,WAAW,SAAS,QACtG;AAAA,IACN,OAAO;AACL,aAAO,eAAe,MAAM,IAAI,SAAS;AACzC,iBAAW,YACP,6DAA6D,SAAS,QACtE;AAAA,IACN;AAEA,WAAO;AAAA,cACG,IAAI;AAAA,4BACU,MAAM;AAAA,kBAChB,QAAQ;AAAA,kBACR,aAAa;AAAA;AAAA,cAEjB,YAAY;AAAA,cAEZ,OAAO,kBACH,UACA,SAAS,OAAO,UAAU;AAAA,MACxB,MAAM,aAAa;AAAA,MACnB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,IAAA,CACD,CACP;AAAA,cAEE,OAAO,kBACH,UACA,SAAS,OAAO,UAAU;AAAA,MACxB,MAAM,aAAa;AAAA,MACnB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,IAAA,CACD,CACP;AAAA;AAAA,EAEV,OAAO;AACL,QAAI;AACJ,QAAI;AACJ,QAAI,OAAO,UAAU,UAAoB;AACvC,kBAAY;AACZ,sBAAgB,cAAc;AAAA,IAChC,WAAW,OAAO,UAAU,WAAqB;AAC/C,kBAAY;AACZ,sBAAgB,cAAc;AAAA,IAChC,OAAO;AACL,kBAAY;AACZ,sBAAgB,cAAc;AAAA,IAChC;AACA,WAAO;AAAA,cACG,WAAW,OAAO,UAAU,OAAO,UAAU,OAAO,UAAU,cAAwB,YAAY,QAAQ,WAAW,YAAY,CAAC;AAAA,cAClI,SAAS,OAAO,UAAU;AAAA,MAC1B,MAAM,aAAa;AAAA,MACnB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,IAAA,CACD,CAAC;AAAA,cACA,SAAS,OAAO,UAAU;AAAA,MAC1B,MAAM,aAAa;AAAA,MACnB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,IAAA,CACD,CAAC;AAAA;AAAA,EAEZ;AACF;"}
@@ -19,7 +19,7 @@ export declare enum TickmarkStyle {
19
19
  enhanced = "enhanced"
20
20
  }
21
21
  export declare function tickmarkColor(style: TickmarkStyle, tickmarkType?: TickmarkType): string;
22
- export declare function tickmark(angle: number, { size, style, scale, text, inside, textRadius, rotation, maxDigits, color, }: {
22
+ export declare function tickmark(angle: number, { size, style, scale, text, inside, textRadius, rotation, maxDigits, color, radiusOffset, }: {
23
23
  size: TickmarkType;
24
24
  style: TickmarkStyle;
25
25
  scale: number;
@@ -29,5 +29,6 @@ export declare function tickmark(angle: number, { size, style, scale, text, insi
29
29
  rotation?: number;
30
30
  maxDigits: number;
31
31
  color?: string;
32
+ radiusOffset?: number;
32
33
  }): SVGTemplateResult | SVGTemplateResult[];
33
34
  //# sourceMappingURL=tickmark.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tickmark.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/watch/tickmark.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAM,MAAM,KAAK,CAAC;AAE3C,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,oBAAY,YAAY;IACtB,aAAa,kBAAkB;IAC/B,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,QAAQ,aAAa;IACrB,QAAQ,aAAa;CACtB;AAED,oBAAY,aAAa;IACvB,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,aAAa,EACpB,YAAY,CAAC,EAAE,YAAY,GAC1B,MAAM,CASR;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,EACE,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAI,EACJ,MAAM,EACN,UAAU,EACV,QAAQ,EACR,SAAS,EACT,KAAK,GACN,EAAE;IACD,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA,iBAAiB,GAAG,iBAAiB,EAAE,CAkEzC"}
1
+ {"version":3,"file":"tickmark.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/watch/tickmark.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAM,MAAM,KAAK,CAAC;AAE3C,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,oBAAY,YAAY;IACtB,aAAa,kBAAkB;IAC/B,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,QAAQ,aAAa;IACrB,QAAQ,aAAa;CACtB;AAED,oBAAY,aAAa;IACvB,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,aAAa,EACpB,YAAY,CAAC,EAAE,YAAY,GAC1B,MAAM,CASR;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,EACE,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAI,EACJ,MAAM,EACN,UAAU,EACV,QAAQ,EACR,SAAS,EACT,KAAK,EACL,YAAgB,GACjB,EAAE;IACD,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACA,iBAAiB,GAAG,iBAAiB,EAAE,CAmEzC"}
@@ -33,36 +33,38 @@ function tickmark(angle, {
33
33
  textRadius,
34
34
  rotation,
35
35
  maxDigits,
36
- color
36
+ color,
37
+ radiusOffset = 0
37
38
  }) {
38
39
  if (scale === Infinity || scale < 0) {
39
40
  throw new Error("Tick scale is not valid");
40
41
  }
42
+ const rOff = radiusOffset;
41
43
  let innerRadius;
42
44
  let outerRadius;
43
45
  textRadius = textRadius + (3 / scale + 3) * (inside ? -1 : 1);
44
46
  const rad = angle * Math.PI / 180;
45
47
  if (size === "primary") {
46
- innerRadius = 328 / 2;
47
- outerRadius = 368 / 2;
48
+ innerRadius = 328 / 2 + rOff;
49
+ outerRadius = 368 / 2 + rOff;
48
50
  } else if (size === "secondary") {
49
- innerRadius = 328 / 2;
50
- outerRadius = 344 / 2;
51
+ innerRadius = 328 / 2 + rOff;
52
+ outerRadius = 344 / 2 + rOff;
51
53
  } else if (size === "main" || size === "zeroLine") {
52
- innerRadius = 320 / 2;
53
- outerRadius = 368 / 2;
54
+ innerRadius = 320 / 2 + rOff;
55
+ outerRadius = 368 / 2 + rOff;
54
56
  } else if (size === "zeroLineThick") {
55
- innerRadius = 224 / 2;
56
- outerRadius = 368 / 2;
57
+ innerRadius = 224 / 2 + rOff;
58
+ outerRadius = 368 / 2 + rOff;
57
59
  } else if (size === "tertiary") {
58
- innerRadius = 328 / 2;
59
- outerRadius = 336 / 2;
60
+ innerRadius = 328 / 2 + rOff;
61
+ outerRadius = 336 / 2 + rOff;
60
62
  } else {
61
63
  return [textSvg(text ?? "", angle, inside, scale, textRadius)];
62
64
  }
63
65
  if (inside) {
64
- const outerRingRadius = 368 / 2;
65
- const ring2Radius = 320 / 2;
66
+ const outerRingRadius = 368 / 2 + rOff;
67
+ const ring2Radius = 320 / 2 + rOff;
66
68
  const tickLength = outerRadius - innerRadius;
67
69
  const gapFromRingEdge = Math.max(0, innerRadius - ring2Radius);
68
70
  outerRadius = outerRingRadius - gapFromRingEdge;