@oicl/openbridge-webcomponents 2.0.0-next.55 → 2.0.0-next.57

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 (29) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +395 -123
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +326 -2
  4. package/dist/automation/automation-tank/automation-tank.d.ts +11 -0
  5. package/dist/automation/automation-tank/automation-tank.d.ts.map +1 -1
  6. package/dist/automation/automation-tank/automation-tank.js.map +1 -1
  7. package/dist/navigation-instruments/compass-sector/compass-sector.css.js +12 -0
  8. package/dist/navigation-instruments/compass-sector/compass-sector.css.js.map +1 -1
  9. package/dist/navigation-instruments/compass-sector/compass-sector.d.ts +23 -0
  10. package/dist/navigation-instruments/compass-sector/compass-sector.d.ts.map +1 -1
  11. package/dist/navigation-instruments/compass-sector/compass-sector.js +47 -0
  12. package/dist/navigation-instruments/compass-sector/compass-sector.js.map +1 -1
  13. package/dist/navigation-instruments/pitch/pitch.d.ts +37 -0
  14. package/dist/navigation-instruments/pitch/pitch.d.ts.map +1 -1
  15. package/dist/navigation-instruments/pitch/pitch.js +130 -62
  16. package/dist/navigation-instruments/pitch/pitch.js.map +1 -1
  17. package/dist/navigation-instruments/pitch-roll/pitch-roll.d.ts +7 -0
  18. package/dist/navigation-instruments/pitch-roll/pitch-roll.d.ts.map +1 -1
  19. package/dist/navigation-instruments/pitch-roll/pitch-roll.js +58 -2
  20. package/dist/navigation-instruments/pitch-roll/pitch-roll.js.map +1 -1
  21. package/dist/navigation-instruments/roll/roll.d.ts +37 -0
  22. package/dist/navigation-instruments/roll/roll.d.ts.map +1 -1
  23. package/dist/navigation-instruments/roll/roll.js +119 -63
  24. package/dist/navigation-instruments/roll/roll.js.map +1 -1
  25. package/dist/navigation-instruments/rot-sector/rot-sector.d.ts +15 -0
  26. package/dist/navigation-instruments/rot-sector/rot-sector.d.ts.map +1 -1
  27. package/dist/navigation-instruments/rot-sector/rot-sector.js +53 -1
  28. package/dist/navigation-instruments/rot-sector/rot-sector.js.map +1 -1
  29. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"pitch-roll.js","sources":["../../../src/navigation-instruments/pitch-roll/pitch-roll.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n type WatchArea,\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n vesselImages,\n} from '../watch/watch.js';\nimport {TickmarkType} from '../watch/tickmark.js';\nimport {AdviceState, AdviceType, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\nimport {\n computeZoomToFitArcFrame,\n normalizeArcAngle,\n shiftArcFrameToOuterEdge,\n} from '../../svghelpers/arc-frame.js';\n\nexport enum PitchRollPriorityElement {\n pitch = 'pitch',\n roll = 'roll',\n}\n\n/** Half-side of the centre overlay viewBox in SVG units. */\nconst CENTRE_HALF = 200;\n\n/**\n * Minimum diagonal Euclidean distance (in central-layer / display\n * pixels on the default 400 px container) required between adjacent\n * zoomed arc bands' nearest corners (inner-to-inner and outer-to-outer\n * checked, the smaller binds). When two adjacent requested arcs would\n * sit closer than this — or actually overlap — both axes' visible arcs\n * are shortened (ratio-preserving so `aP : aR = pitchReq : rollReq`)\n * just enough to reach this clearance. The frame itself stays\n * unchanged so band thickness, position and zoom level keep matching\n * the standalone `obc-pitch` / `obc-roll` instruments.\n */\nconst CORNER_GAP_PX = 32;\n\n/** Numerical safety floor when an axis arc has to collapse for clearance. */\nconst MIN_ARC_HALF_DEG = 2;\n\n@customElement('obc-pitch-roll')\nexport class ObcPitchRoll extends LitElement {\n @property({type: Number}) pitch = 0;\n @property({type: Number}) roll = 0;\n @property({type: Number}) minAvgPitch = 0;\n @property({type: Number}) maxAvgPitch = 0;\n @property({type: Number}) minAvgRoll = 0;\n @property({type: Number}) maxAvgRoll = 0;\n @property({type: String}) vesselImageFore: VesselImage = VesselImage.psvFore;\n @property({type: String}) vesselImageSide: VesselImage = VesselImage.psvSide;\n @property({type: Number}) scaleForeImage = 1;\n @property({type: Number}) maxPitchAdvice: number | undefined = undefined;\n @property({type: Number}) maxRollAdvice: number | undefined = undefined;\n @property({type: Boolean}) triggerPitchAdvice = false;\n @property({type: Boolean}) triggerRollAdvice = false;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Array, attribute: false})\n priorityElements: PitchRollPriorityElement[] = [\n PitchRollPriorityElement.pitch,\n PitchRollPriorityElement.roll,\n ];\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n /**\n * Half-extent of each of the four watch arcs in degrees, measured from the\n * arc's natural center (0°/90°/180°/270°). Each arc spans\n * `center ± arcAngle`. Default `30` reproduces the historical 60°-wide\n * arcs; smaller values produce narrower arcs that, combined with\n * `zoomToFitArc`, reveal more detail in the relevant motion range.\n */\n @property({type: Number}) arcAngle: number = 30;\n /**\n * Optional per-axis override for the pitch arcs (top + bottom). Falls\n * back to {@link arcAngle} when undefined. Useful for rectangular layouts\n * where pitch and roll need different angular extents.\n */\n @property({type: Number}) pitchArcAngle?: number;\n /**\n * Optional per-axis override for the roll arcs (left + right). Falls\n * back to {@link arcAngle} when undefined.\n */\n @property({type: Number}) rollArcAngle?: number;\n\n private priorityFor(element: PitchRollPriorityElement): Priority {\n const selected = Array.isArray(this.priorityElements)\n ? this.priorityElements\n : [];\n return selected.includes(element) ? this.priority : Priority.regular;\n }\n\n private needleColor(element: PitchRollPriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private barColor(element: PitchRollPriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get normalizedScaleForeImage(): number {\n if (!Number.isFinite(this.scaleForeImage)) {\n return 1;\n }\n return Math.max(0, Math.min(2, this.scaleForeImage));\n }\n\n /** Requested (clamped to a minimum) half-extent for each axis. */\n private get requestedPitchArcAngle(): number {\n return normalizeArcAngle(this.pitchArcAngle ?? this.arcAngle, 30);\n }\n private get requestedRollArcAngle(): number {\n return normalizeArcAngle(this.rollArcAngle ?? this.arcAngle, 30);\n }\n\n override render() {\n const pitchReq = this.requestedPitchArcAngle;\n const rollReq = this.requestedRollArcAngle;\n const areas = [\n {\n startAngle: 90 - pitchReq,\n endAngle: 90 + pitchReq,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n {\n startAngle: 270 - pitchReq,\n endAngle: 270 + pitchReq,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n {\n startAngle: 360 - rollReq,\n endAngle: rollReq,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n {\n startAngle: 180 - rollReq,\n endAngle: 180 + rollReq,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n\n const overlayViewBox = `-${CENTRE_HALF} -${CENTRE_HALF} ${CENTRE_HALF * 2} ${CENTRE_HALF * 2}`;\n const vesselScale = 224 / 160;\n\n return html`\n <div class=\"container\">\n <svg viewBox=\"${overlayViewBox}\">\n ${svg`\n <line\n x1=\"-150\"\n y1=\"0\"\n x2=\"150\"\n y2=\"0\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n <g\n style=\"transform: rotate(${this.pitch}deg) scale(${vesselScale}) translate(-80px, -80px);\"\n >\n ${this.zoomToFitArc ? vesselImages[this.vesselImageSide] : nothing}\n </g>\n <g\n style=\"transform: rotate(${this.roll}deg) scale(${vesselScale * this.normalizedScaleForeImage}) translate(-80px, -80px);\"\n >\n ${this.zoomToFitArc ? vesselImages[this.vesselImageFore] : nothing}\n </g>\n `}\n </svg>\n ${this.zoomToFitArc\n ? this.renderZoomedArcs(pitchReq, rollReq)\n : this.renderFullWatch(areas)}\n </div>\n `;\n }\n\n /**\n * Zoomed-arc layer: four CSS-rotated `<obc-watch>` instances, each\n * containing a single arc rendered at the watch's natural top\n * (`0° ± arcAngle`). Each watch handles its own `zoomToFitArc` framing\n * so each visible arc spans almost the full container — exactly like the\n * pitch and roll narrow stories. The four are rotated 0 / 90 / 180 / 270\n * to land at top / right / bottom / left. Top + bottom carry pitch data,\n * left + right carry roll data.\n *\n * Each axis can request its own half-extent via `pitchArcAngle` /\n * `rollArcAngle`. The zoom-fit frame for each axis is computed with the\n * EXACT same math as `obc-pitch` / `obc-roll` at the requested\n * half-extent (same band thickness, same zoom level, same position) so\n * each cardinal sub-watch matches its standalone equivalent. With the\n * frames left untouched, two requested arcs may overlap at the\n * diagonals; to avoid that, both arcs are shortened (ratio-preserving:\n * `aP : aR = pitchReq : rollReq`) just enough that the diagonal\n * Euclidean distance between adjacent inner BBOX corners equals\n * {@link CORNER_GAP_PX}. The shortened half-extent is passed only to\n * the band's `areas` (and clamped advices) so the sub-watch renders a\n * shorter band with its native rounded end-caps; the frame itself is\n * unchanged.\n */\n private renderZoomedArcs(pitchReq: number, rollReq: number) {\n const tickmarks = [{angle: 0, type: TickmarkType.main}];\n\n // ---- Per-axis zoom-fit frames (requested half-extents) -------------\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n const innerNat = innerRingRadiusFor(WatchCircleType.double);\n const buildFrame = (halfDeg: number) => {\n const areas: WatchArea[] = [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n const baseFrame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerNat,\n extension: ext,\n targetSize,\n });\n const subArcFrame = shiftArcFrameToOuterEdge(\n baseFrame,\n OUTER_RING_RADIUS + baseFrame.radiusOffset,\n OUTER_RING_RADIUS,\n CENTRE_HALF\n );\n // Display scale: how many container px per obc-watch SVG unit.\n const scale = (CENTRE_HALF * 2) / subArcFrame.width;\n // Outer- and inner-arc circle radii of the band, in central\n // (container) px. The watch renders the area between\n // (OUTER_RING_RADIUS + radiusOffset) and (innerRingRadius +\n // radiusOffset), so radiusOffset shifts BOTH radii (band\n // thickness stays constant). Both arcs are centred at the watch's\n // SVG origin; that origin sits at central-coords (0, outerR-OR)\n // along the band's cardinal direction (= outerR-OR below centre\n // for the top band).\n const outerR = (OUTER_RING_RADIUS + baseFrame.radiusOffset) * scale;\n const innerR = (innerNat + baseFrame.radiusOffset) * scale;\n return {subArcFrame, outerR, innerR};\n };\n // Frames are built at the REQUESTED half-extents — identical to\n // what `obc-pitch` / `obc-roll` produce when `zoomToFitArc=true`.\n // Each cardinal sub-watch therefore matches its standalone\n // equivalent (band thickness, length, position, zoom level).\n const pitchFrame = buildFrame(pitchReq);\n const rollFrame = buildFrame(rollReq);\n\n // ---- Method A: shorten visible arc to clear adjacent corners --------\n // The frames stay UNCHANGED; only the half-extent passed to the\n // band's `areas` shrinks. obc-watch then renders a shorter arc with\n // its native rounded end-caps — same band thickness, same position,\n // same zoom level.\n //\n // Geometry of one band (top, cardinal = -y in container coords):\n // outer-edge endpoint at angle θ from cardinal\n // P_out(θ) = (outerR·sin θ, (outerR − OR) − outerR·cos θ)\n // inner-edge endpoint at angle θ\n // P_in(θ) = (innerR·sin θ, (outerR − OR) − innerR·cos θ)\n // The right band is the same template rotated 90° CW\n // (CSS rotate(90deg)): (x, y) → (−y, x).\n //\n // For pitch–roll layout the binding constraint is the diagonal\n // gap between the top band's right corners and the right band's\n // top corners (and analogously for the other three diagonals). Two\n // pairs need to clear each other:\n // (a) inner-corner vs inner-corner (P1 = P_in_top(+aP),\n // Q1 = rotate(P_in_right(−aR)))\n // (b) outer-corner vs outer-corner (P2 = P_out_top(+aP),\n // Q2 = rotate(P_out_right(−aR)))\n // Cap-line endpoints lie on the same arcs so any other point on\n // the cap is at least as far away.\n //\n // Define a SIGNED diagonal gap: positive when the two corners are\n // diagonally clear (both Δx > 0 AND Δy > 0), negative when either\n // projection has crossed (i.e. the bands overlap). Its magnitude\n // is the Euclidean distance between the corner pair. We bisect on\n // a scalar s ∈ [0, 1] (aP = pitchReq·s, aR = rollReq·s) so the\n // requested pitch:roll RATIO is preserved, until the MIN of the\n // inner and outer signed gaps equals CORNER_GAP_PX.\n const OR = OUTER_RING_RADIUS;\n const aPreqRad = (pitchReq * Math.PI) / 180;\n const aRreqRad = (rollReq * Math.PI) / 180;\n const signedDist = (\n px: number,\n py: number,\n qx: number,\n qy: number\n ): number => {\n const dx = qx - px;\n const dy = qy - py;\n const mag = Math.hypot(dx, dy);\n return dx > 0 && dy > 0 ? mag : -mag;\n };\n const cornerGaps = (\n apRad: number,\n arRad: number\n ): {inner: number; outer: number} => {\n const cosP = Math.cos(apRad);\n const sinP = Math.sin(apRad);\n const cosR = Math.cos(arRad);\n const sinR = Math.sin(arRad);\n // Top band's right corners (container coords).\n const p1x = pitchFrame.innerR * sinP;\n const p1y = pitchFrame.outerR - OR - pitchFrame.innerR * cosP;\n const p2x = pitchFrame.outerR * sinP;\n const p2y = pitchFrame.outerR - OR - pitchFrame.outerR * cosP;\n // Right band's top corners = top template's left corners rotated\n // 90° CW: (x, y) → (−y, x).\n // Top template's −aR inner corner: (−innerR·sin aR,\n // (outerR−OR) − innerR·cos aR) → rotated:\n // (OR − outerR + innerR·cos aR, −innerR·sin aR)\n const q1x = OR - rollFrame.outerR + rollFrame.innerR * cosR;\n const q1y = -rollFrame.innerR * sinR;\n const q2x = OR - rollFrame.outerR + rollFrame.outerR * cosR;\n const q2y = -rollFrame.outerR * sinR;\n return {\n inner: signedDist(p1x, p1y, q1x, q1y),\n outer: signedDist(p2x, p2y, q2x, q2y),\n };\n };\n const minGap = (apRad: number, arRad: number): number => {\n const g = cornerGaps(apRad, arRad);\n return Math.min(g.inner, g.outer);\n };\n let aP = aPreqRad;\n let aR = aRreqRad;\n if (minGap(aPreqRad, aRreqRad) < CORNER_GAP_PX) {\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (minGap(aPreqRad * mid, aRreqRad * mid) >= CORNER_GAP_PX) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n aP = aPreqRad * lo;\n aR = aRreqRad * lo;\n }\n const pitchClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aP * 180) / Math.PI);\n const rollClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aR * 180) / Math.PI);\n\n const subAreas = (halfDeg: number): WatchArea[] => [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n const pitchAreas = subAreas(pitchClampedDeg);\n const rollAreas = subAreas(rollClampedDeg);\n\n const pitchAdvices = this.subAdvices('pitch', pitchClampedDeg);\n const rollAdvices = this.subAdvices('roll', rollClampedDeg);\n\n // Clip each sub-watch to the angular sector actually covered by the\n // (possibly shortened) arc so the indicator pill and bar end-of-range\n // limit lines cannot leak past the visible band when the value falls\n // outside the clamped range. Advices are clamped to the band extent\n // in `subAdvices` so they fit naturally and are not affected by this\n // clip. The clip is a triangle in the element's CSS box, with one\n // vertex at the watch origin (SVG 0,0 mapped to CSS px) and two\n // vertices at the intersection of the sector edges with the top edge\n // of the box. Applied in unrotated local coords; CSS rotation then\n // carries it to the correct cardinal side.\n const sectorClip = (\n halfDeg: number,\n frame: typeof rollFrame.subArcFrame\n ): string => {\n // Watch origin (SVG 0,0) in CSS percentages of the element box.\n // Element fills the 100% × 100% .container; obc-watch fills it with\n // viewBox = frame.{x,y,width,height}, so SVG (0,0) sits at:\n // (-frame.x / frame.width, -frame.y / frame.height)\n const oxPct = (-frame.x / frame.width) * 100;\n const oyPct = (-frame.y / frame.height) * 100;\n // Sector half-angle, expressed as the horizontal offset (in pct)\n // a ray reaches when traveling from the origin up to the top edge.\n const dxPct = oyPct * Math.tan((halfDeg * Math.PI) / 180);\n // Clamp to box bounds so half-angles ≥ 45° still produce a polygon\n // that reaches the corners instead of going off-canvas.\n const lx = Math.max(0, oxPct - dxPct);\n const rx = Math.min(100, oxPct + dxPct);\n return `polygon(${oxPct}% ${oyPct}%, ${lx}% 0%, ${rx}% 0%)`;\n };\n const pitchClip = sectorClip(pitchClampedDeg, pitchFrame.subArcFrame);\n const rollClip = sectorClip(rollClampedDeg, rollFrame.subArcFrame);\n\n const rollNeedles = [\n {\n angle: this.roll,\n fillColor: this.needleColor(PitchRollPriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ];\n const pitchNeedles = [\n {\n angle: this.pitch,\n fillColor: this.needleColor(PitchRollPriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ];\n const rollBars = [\n {\n startAngle: this.minAvgRoll,\n endAngle: this.maxAvgRoll,\n fillColor: this.barColor(PitchRollPriorityElement.roll),\n },\n ];\n const pitchBars = [\n {\n startAngle: this.minAvgPitch,\n endAngle: this.maxAvgPitch,\n fillColor: this.barColor(PitchRollPriorityElement.pitch),\n },\n ];\n\n const subWatch = (\n rotation: number,\n arcFrame: typeof rollFrame.subArcFrame,\n areas: WatchArea[],\n barAreas: typeof rollBars,\n needles: typeof rollNeedles,\n advices: AngleAdviceRaw[],\n clipPath: string\n ) => html`\n <obc-watch\n class=\"sub-watch\"\n style=\"transform: rotate(${rotation}deg); clip-path: ${clipPath};\"\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${true}\n .arcFrame=${arcFrame}\n .areas=${areas}\n .barAreas=${barAreas}\n .needles=${needles}\n .vessels=${[]}\n .tickmarks=${tickmarks}\n .advices=${advices}\n ></obc-watch>\n `;\n\n return html`\n ${subWatch(\n 0,\n rollFrame.subArcFrame,\n rollAreas,\n rollBars,\n rollNeedles,\n rollAdvices,\n rollClip\n )}\n ${subWatch(\n 90,\n pitchFrame.subArcFrame,\n pitchAreas,\n pitchBars,\n pitchNeedles,\n pitchAdvices,\n pitchClip\n )}\n ${subWatch(\n 180,\n rollFrame.subArcFrame,\n rollAreas,\n rollBars,\n rollNeedles,\n rollAdvices,\n rollClip\n )}\n ${subWatch(\n 270,\n pitchFrame.subArcFrame,\n pitchAreas,\n pitchBars,\n pitchNeedles,\n pitchAdvices,\n pitchClip\n )}\n `;\n }\n\n /**\n * Caution advices for a single sub-watch axis, emitted at sub-watch local\n * angles (centred on 0°). The outer extent is clamped to the actually\n * rendered band half-extent (`halfDeg`) so advices fit naturally inside\n * the visible arc and are not visually cropped by the sub-watch's sector\n * clip-path. The clip-path itself remains in place to crop the needle.\n */\n private subAdvices(\n axis: 'pitch' | 'roll',\n halfDeg: number\n ): AngleAdviceRaw[] {\n const advices: AngleAdviceRaw[] = [];\n const max = axis === 'pitch' ? this.maxPitchAdvice : this.maxRollAdvice;\n if (max === undefined) return advices;\n const trigger =\n axis === 'pitch' ? this.triggerPitchAdvice : this.triggerRollAdvice;\n const cap = axis === 'pitch' ? 30 : 45;\n const outer = Math.min(halfDeg, cap);\n const inner = Math.min(max, outer);\n const state = trigger ? AdviceState.triggered : AdviceState.regular;\n advices.push({\n minAngle: -outer,\n maxAngle: -inner,\n type: AdviceType.caution,\n state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: inner,\n maxAngle: outer,\n type: AdviceType.caution,\n state,\n hideMaxTickmark: true,\n });\n return advices;\n }\n\n /** Full unzoomed watch — original single-instance render. */\n private renderFullWatch(areas: WatchArea[]) {\n return html`\n <obc-watch\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${false}\n .areas=${areas}\n .barAreas=${[\n {\n startAngle: this.minAvgRoll,\n endAngle: this.maxAvgRoll,\n fillColor: this.barColor(PitchRollPriorityElement.roll),\n },\n {\n startAngle: 180 + this.minAvgRoll,\n endAngle: 180 + this.maxAvgRoll,\n fillColor: this.barColor(PitchRollPriorityElement.roll),\n },\n {\n startAngle: 90 + this.minAvgPitch,\n endAngle: 90 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollPriorityElement.pitch),\n },\n {\n startAngle: 270 + this.minAvgPitch,\n endAngle: 270 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollPriorityElement.pitch),\n },\n ]}\n .needles=${[\n {\n angle: this.roll,\n fillColor: this.needleColor(PitchRollPriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: 180 + this.roll,\n fillColor: this.needleColor(PitchRollPriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: 90 + this.pitch,\n fillColor: this.needleColor(PitchRollPriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: 270 + this.pitch,\n fillColor: this.needleColor(PitchRollPriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ]}\n .vessels=${[\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageSide,\n transform: `rotate(${this.pitch}deg)`,\n },\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageFore,\n transform: `rotate(${this.roll}deg) scale(${this.normalizedScaleForeImage})`,\n },\n ]}\n .tickmarks=${[\n {angle: 0, type: TickmarkType.main},\n {angle: 90, type: TickmarkType.main},\n {angle: 180, type: TickmarkType.main},\n {angle: 270, type: TickmarkType.main},\n ]}\n .advices=${this.advices}\n ></obc-watch>\n `;\n }\n\n private get advices(): AngleAdviceRaw[] {\n const pitchReq = this.requestedPitchArcAngle;\n const rollReq = this.requestedRollArcAngle;\n const advices = [];\n if (this.maxPitchAdvice !== undefined) {\n const outer = Math.min(pitchReq, 30);\n const inner = Math.min(this.maxPitchAdvice, outer);\n const state = this.triggerPitchAdvice\n ? AdviceState.triggered\n : AdviceState.regular;\n advices.push({\n minAngle: 90 - outer,\n maxAngle: 90 - inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: 90 + inner,\n maxAngle: 90 + outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n });\n advices.push({\n minAngle: 270 - outer,\n maxAngle: 270 - inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: 270 + inner,\n maxAngle: 270 + outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n });\n }\n if (this.maxRollAdvice !== undefined) {\n const outer = Math.min(rollReq, 45);\n const inner = Math.min(this.maxRollAdvice, outer);\n const state = this.triggerRollAdvice\n ? AdviceState.triggered\n : AdviceState.regular;\n advices.push({\n minAngle: -outer,\n maxAngle: -inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: inner,\n maxAngle: outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n });\n advices.push({\n minAngle: 180 - outer,\n maxAngle: 180 - inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: 180 + inner,\n maxAngle: 180 + outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n });\n }\n return advices;\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-pitch-roll': ObcPitchRoll;\n }\n}\n"],"names":["PitchRollPriorityElement"],"mappings":"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"}
1
+ {"version":3,"file":"pitch-roll.js","sources":["../../../src/navigation-instruments/pitch-roll/pitch-roll.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n type WatchArea,\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n vesselImages,\n} from '../watch/watch.js';\nimport {TickmarkType} from '../watch/tickmark.js';\nimport {AdviceState, AdviceType, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../types.js';\nimport '../readout/readout.js';\nimport {ReadoutDirection, ReadoutVariant} from '../readout/readout.js';\nimport {\n computeZoomToFitArcFrame,\n normalizeArcAngle,\n shiftArcFrameToOuterEdge,\n} from '../../svghelpers/arc-frame.js';\n\nexport enum PitchRollPriorityElement {\n pitch = 'pitch',\n roll = 'roll',\n}\n\n/** Half-side of the centre overlay viewBox in SVG units. */\nconst CENTRE_HALF = 200;\n\n/**\n * Minimum diagonal Euclidean distance (in central-layer / display\n * pixels on the default 400 px container) required between adjacent\n * zoomed arc bands' nearest corners (inner-to-inner and outer-to-outer\n * checked, the smaller binds). When two adjacent requested arcs would\n * sit closer than this — or actually overlap — both axes' visible arcs\n * are shortened (ratio-preserving so `aP : aR = pitchReq : rollReq`)\n * just enough to reach this clearance. The frame itself stays\n * unchanged so band thickness, position and zoom level keep matching\n * the standalone `obc-pitch` / `obc-roll` instruments.\n */\nconst CORNER_GAP_PX = 32;\n\n/** Numerical safety floor when an axis arc has to collapse for clearance. */\nconst MIN_ARC_HALF_DEG = 2;\n\n@customElement('obc-pitch-roll')\nexport class ObcPitchRoll extends LitElement {\n @property({type: Number}) pitch = 0;\n @property({type: Number}) roll = 0;\n @property({type: Number}) minAvgPitch = 0;\n @property({type: Number}) maxAvgPitch = 0;\n @property({type: Number}) minAvgRoll = 0;\n @property({type: Number}) maxAvgRoll = 0;\n @property({type: String}) vesselImageFore: VesselImage = VesselImage.psvFore;\n @property({type: String}) vesselImageSide: VesselImage = VesselImage.psvSide;\n @property({type: Number}) scaleForeImage = 1;\n @property({type: Number}) maxPitchAdvice: number | undefined = undefined;\n @property({type: Number}) maxRollAdvice: number | undefined = undefined;\n @property({type: Boolean}) triggerPitchAdvice = false;\n @property({type: Boolean}) triggerRollAdvice = false;\n @property({type: String}) priority: Priority = Priority.regular;\n @property({type: Array, attribute: false})\n priorityElements: PitchRollPriorityElement[] = [\n PitchRollPriorityElement.pitch,\n PitchRollPriorityElement.roll,\n ];\n /**\n * When `true`, the centre shows two stacked `<obc-readout>`s (pitch above\n * roll) instead of the vessel images. Default `false`.\n */\n @property({type: Boolean}) hasReadout: boolean = false;\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n /**\n * Half-extent of each of the four watch arcs in degrees, measured from the\n * arc's natural center (0°/90°/180°/270°). Each arc spans\n * `center ± arcAngle`. Default `30` reproduces the historical 60°-wide\n * arcs; smaller values produce narrower arcs that, combined with\n * `zoomToFitArc`, reveal more detail in the relevant motion range.\n */\n @property({type: Number}) arcAngle: number = 30;\n /**\n * Optional per-axis override for the pitch arcs (top + bottom). Falls\n * back to {@link arcAngle} when undefined. Useful for rectangular layouts\n * where pitch and roll need different angular extents.\n */\n @property({type: Number}) pitchArcAngle?: number;\n /**\n * Optional per-axis override for the roll arcs (left + right). Falls\n * back to {@link arcAngle} when undefined.\n */\n @property({type: Number}) rollArcAngle?: number;\n\n private priorityFor(element: PitchRollPriorityElement): Priority {\n const selected = Array.isArray(this.priorityElements)\n ? this.priorityElements\n : [];\n return selected.includes(element) ? this.priority : Priority.regular;\n }\n\n private needleColor(element: PitchRollPriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private barColor(element: PitchRollPriorityElement): string {\n return this.priorityFor(element) === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get normalizedScaleForeImage(): number {\n if (!Number.isFinite(this.scaleForeImage)) {\n return 1;\n }\n return Math.max(0, Math.min(2, this.scaleForeImage));\n }\n\n /** Requested (clamped to a minimum) half-extent for each axis. */\n private get requestedPitchArcAngle(): number {\n return normalizeArcAngle(this.pitchArcAngle ?? this.arcAngle, 30);\n }\n private get requestedRollArcAngle(): number {\n return normalizeArcAngle(this.rollArcAngle ?? this.arcAngle, 30);\n }\n\n override render() {\n const pitchReq = this.requestedPitchArcAngle;\n const rollReq = this.requestedRollArcAngle;\n const areas = [\n {\n startAngle: 90 - pitchReq,\n endAngle: 90 + pitchReq,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n {\n startAngle: 270 - pitchReq,\n endAngle: 270 + pitchReq,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n {\n startAngle: 360 - rollReq,\n endAngle: rollReq,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n {\n startAngle: 180 - rollReq,\n endAngle: 180 + rollReq,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n\n const overlayViewBox = `-${CENTRE_HALF} -${CENTRE_HALF} ${CENTRE_HALF * 2} ${CENTRE_HALF * 2}`;\n const vesselScale = 224 / 160;\n\n return html`\n <div class=\"container\">\n <svg viewBox=\"${overlayViewBox}\">\n ${this.hasReadout\n ? nothing\n : svg`\n <line\n x1=\"-150\"\n y1=\"0\"\n x2=\"150\"\n y2=\"0\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n <g\n style=\"transform: rotate(${this.pitch}deg) scale(${vesselScale}) translate(-80px, -80px);\"\n >\n ${this.zoomToFitArc ? vesselImages[this.vesselImageSide] : nothing}\n </g>\n <g\n style=\"transform: rotate(${this.roll}deg) scale(${vesselScale * this.normalizedScaleForeImage}) translate(-80px, -80px);\"\n >\n ${this.zoomToFitArc ? vesselImages[this.vesselImageFore] : nothing}\n </g>\n `}\n </svg>\n ${this.zoomToFitArc\n ? this.renderZoomedArcs(pitchReq, rollReq)\n : this.renderFullWatch(areas)}\n ${this.hasReadout\n ? html`<div class=\"readout\">\n <div class=\"readout-group\">\n ${this.renderReadout(\n this.pitch,\n 'Pitch',\n PitchRollPriorityElement.pitch\n )}\n <div class=\"readout-divider\"></div>\n ${this.renderReadout(\n this.roll,\n 'Roll',\n PitchRollPriorityElement.roll\n )}\n </div>\n </div>`\n : nothing}\n </div>\n `;\n }\n\n private renderReadout(\n value: number,\n label: string,\n element: PitchRollPriorityElement\n ) {\n return html`\n <obc-readout\n .variant=${ReadoutVariant.enhanced}\n .direction=${ReadoutDirection.vertical}\n .hasSetpoint=${false}\n .hasAdvice=${false}\n .value=${value}\n .fractionDigits=${0}\n .valuePriority=${this.priorityFor(element)}\n label=${label}\n unit=\"DEG\"\n ></obc-readout>\n `;\n }\n\n /**\n * Zoomed-arc layer: four CSS-rotated `<obc-watch>` instances, each\n * containing a single arc rendered at the watch's natural top\n * (`0° ± arcAngle`). Each watch handles its own `zoomToFitArc` framing\n * so each visible arc spans almost the full container — exactly like the\n * pitch and roll narrow stories. The four are rotated 0 / 90 / 180 / 270\n * to land at top / right / bottom / left. Top + bottom carry pitch data,\n * left + right carry roll data.\n *\n * Each axis can request its own half-extent via `pitchArcAngle` /\n * `rollArcAngle`. The zoom-fit frame for each axis is computed with the\n * EXACT same math as `obc-pitch` / `obc-roll` at the requested\n * half-extent (same band thickness, same zoom level, same position) so\n * each cardinal sub-watch matches its standalone equivalent. With the\n * frames left untouched, two requested arcs may overlap at the\n * diagonals; to avoid that, both arcs are shortened (ratio-preserving:\n * `aP : aR = pitchReq : rollReq`) just enough that the diagonal\n * Euclidean distance between adjacent inner BBOX corners equals\n * {@link CORNER_GAP_PX}. The shortened half-extent is passed only to\n * the band's `areas` (and clamped advices) so the sub-watch renders a\n * shorter band with its native rounded end-caps; the frame itself is\n * unchanged.\n */\n private renderZoomedArcs(pitchReq: number, rollReq: number) {\n const tickmarks = [{angle: 0, type: TickmarkType.main}];\n\n // ---- Per-axis zoom-fit frames (requested half-extents) -------------\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n const innerNat = innerRingRadiusFor(WatchCircleType.double);\n const buildFrame = (halfDeg: number) => {\n const areas: WatchArea[] = [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n const baseFrame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerNat,\n extension: ext,\n targetSize,\n });\n const subArcFrame = shiftArcFrameToOuterEdge(\n baseFrame,\n OUTER_RING_RADIUS + baseFrame.radiusOffset,\n OUTER_RING_RADIUS,\n CENTRE_HALF\n );\n // Display scale: how many container px per obc-watch SVG unit.\n const scale = (CENTRE_HALF * 2) / subArcFrame.width;\n // Outer- and inner-arc circle radii of the band, in central\n // (container) px. The watch renders the area between\n // (OUTER_RING_RADIUS + radiusOffset) and (innerRingRadius +\n // radiusOffset), so radiusOffset shifts BOTH radii (band\n // thickness stays constant). Both arcs are centred at the watch's\n // SVG origin; that origin sits at central-coords (0, outerR-OR)\n // along the band's cardinal direction (= outerR-OR below centre\n // for the top band).\n const outerR = (OUTER_RING_RADIUS + baseFrame.radiusOffset) * scale;\n const innerR = (innerNat + baseFrame.radiusOffset) * scale;\n return {subArcFrame, outerR, innerR};\n };\n // Frames are built at the REQUESTED half-extents — identical to\n // what `obc-pitch` / `obc-roll` produce when `zoomToFitArc=true`.\n // Each cardinal sub-watch therefore matches its standalone\n // equivalent (band thickness, length, position, zoom level).\n const pitchFrame = buildFrame(pitchReq);\n const rollFrame = buildFrame(rollReq);\n\n // ---- Method A: shorten visible arc to clear adjacent corners --------\n // The frames stay UNCHANGED; only the half-extent passed to the\n // band's `areas` shrinks. obc-watch then renders a shorter arc with\n // its native rounded end-caps — same band thickness, same position,\n // same zoom level.\n //\n // Geometry of one band (top, cardinal = -y in container coords):\n // outer-edge endpoint at angle θ from cardinal\n // P_out(θ) = (outerR·sin θ, (outerR − OR) − outerR·cos θ)\n // inner-edge endpoint at angle θ\n // P_in(θ) = (innerR·sin θ, (outerR − OR) − innerR·cos θ)\n // The right band is the same template rotated 90° CW\n // (CSS rotate(90deg)): (x, y) → (−y, x).\n //\n // For pitch–roll layout the binding constraint is the diagonal\n // gap between the top band's right corners and the right band's\n // top corners (and analogously for the other three diagonals). Two\n // pairs need to clear each other:\n // (a) inner-corner vs inner-corner (P1 = P_in_top(+aP),\n // Q1 = rotate(P_in_right(−aR)))\n // (b) outer-corner vs outer-corner (P2 = P_out_top(+aP),\n // Q2 = rotate(P_out_right(−aR)))\n // Cap-line endpoints lie on the same arcs so any other point on\n // the cap is at least as far away.\n //\n // Define a SIGNED diagonal gap: positive when the two corners are\n // diagonally clear (both Δx > 0 AND Δy > 0), negative when either\n // projection has crossed (i.e. the bands overlap). Its magnitude\n // is the Euclidean distance between the corner pair. We bisect on\n // a scalar s ∈ [0, 1] (aP = pitchReq·s, aR = rollReq·s) so the\n // requested pitch:roll RATIO is preserved, until the MIN of the\n // inner and outer signed gaps equals CORNER_GAP_PX.\n const OR = OUTER_RING_RADIUS;\n const aPreqRad = (pitchReq * Math.PI) / 180;\n const aRreqRad = (rollReq * Math.PI) / 180;\n const signedDist = (\n px: number,\n py: number,\n qx: number,\n qy: number\n ): number => {\n const dx = qx - px;\n const dy = qy - py;\n const mag = Math.hypot(dx, dy);\n return dx > 0 && dy > 0 ? mag : -mag;\n };\n const cornerGaps = (\n apRad: number,\n arRad: number\n ): {inner: number; outer: number} => {\n const cosP = Math.cos(apRad);\n const sinP = Math.sin(apRad);\n const cosR = Math.cos(arRad);\n const sinR = Math.sin(arRad);\n // Top band's right corners (container coords).\n const p1x = pitchFrame.innerR * sinP;\n const p1y = pitchFrame.outerR - OR - pitchFrame.innerR * cosP;\n const p2x = pitchFrame.outerR * sinP;\n const p2y = pitchFrame.outerR - OR - pitchFrame.outerR * cosP;\n // Right band's top corners = top template's left corners rotated\n // 90° CW: (x, y) → (−y, x).\n // Top template's −aR inner corner: (−innerR·sin aR,\n // (outerR−OR) − innerR·cos aR) → rotated:\n // (OR − outerR + innerR·cos aR, −innerR·sin aR)\n const q1x = OR - rollFrame.outerR + rollFrame.innerR * cosR;\n const q1y = -rollFrame.innerR * sinR;\n const q2x = OR - rollFrame.outerR + rollFrame.outerR * cosR;\n const q2y = -rollFrame.outerR * sinR;\n return {\n inner: signedDist(p1x, p1y, q1x, q1y),\n outer: signedDist(p2x, p2y, q2x, q2y),\n };\n };\n const minGap = (apRad: number, arRad: number): number => {\n const g = cornerGaps(apRad, arRad);\n return Math.min(g.inner, g.outer);\n };\n let aP = aPreqRad;\n let aR = aRreqRad;\n if (minGap(aPreqRad, aRreqRad) < CORNER_GAP_PX) {\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (minGap(aPreqRad * mid, aRreqRad * mid) >= CORNER_GAP_PX) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n aP = aPreqRad * lo;\n aR = aRreqRad * lo;\n }\n const pitchClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aP * 180) / Math.PI);\n const rollClampedDeg = Math.max(MIN_ARC_HALF_DEG, (aR * 180) / Math.PI);\n\n const subAreas = (halfDeg: number): WatchArea[] => [\n {\n startAngle: -halfDeg,\n endAngle: halfDeg,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n const pitchAreas = subAreas(pitchClampedDeg);\n const rollAreas = subAreas(rollClampedDeg);\n\n const pitchAdvices = this.subAdvices('pitch', pitchClampedDeg);\n const rollAdvices = this.subAdvices('roll', rollClampedDeg);\n\n // Clip each sub-watch to the angular sector actually covered by the\n // (possibly shortened) arc so the indicator pill and bar end-of-range\n // limit lines cannot leak past the visible band when the value falls\n // outside the clamped range. Advices are clamped to the band extent\n // in `subAdvices` so they fit naturally and are not affected by this\n // clip. The clip is a triangle in the element's CSS box, with one\n // vertex at the watch origin (SVG 0,0 mapped to CSS px) and two\n // vertices at the intersection of the sector edges with the top edge\n // of the box. Applied in unrotated local coords; CSS rotation then\n // carries it to the correct cardinal side.\n const sectorClip = (\n halfDeg: number,\n frame: typeof rollFrame.subArcFrame\n ): string => {\n // Watch origin (SVG 0,0) in CSS percentages of the element box.\n // Element fills the 100% × 100% .container; obc-watch fills it with\n // viewBox = frame.{x,y,width,height}, so SVG (0,0) sits at:\n // (-frame.x / frame.width, -frame.y / frame.height)\n const oxPct = (-frame.x / frame.width) * 100;\n const oyPct = (-frame.y / frame.height) * 100;\n // Sector half-angle, expressed as the horizontal offset (in pct)\n // a ray reaches when traveling from the origin up to the top edge.\n const dxPct = oyPct * Math.tan((halfDeg * Math.PI) / 180);\n // Clamp to box bounds so half-angles ≥ 45° still produce a polygon\n // that reaches the corners instead of going off-canvas.\n const lx = Math.max(0, oxPct - dxPct);\n const rx = Math.min(100, oxPct + dxPct);\n return `polygon(${oxPct}% ${oyPct}%, ${lx}% 0%, ${rx}% 0%)`;\n };\n const pitchClip = sectorClip(pitchClampedDeg, pitchFrame.subArcFrame);\n const rollClip = sectorClip(rollClampedDeg, rollFrame.subArcFrame);\n\n const rollNeedles = [\n {\n angle: this.roll,\n fillColor: this.needleColor(PitchRollPriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ];\n const pitchNeedles = [\n {\n angle: this.pitch,\n fillColor: this.needleColor(PitchRollPriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ];\n const rollBars = [\n {\n startAngle: this.minAvgRoll,\n endAngle: this.maxAvgRoll,\n fillColor: this.barColor(PitchRollPriorityElement.roll),\n },\n ];\n const pitchBars = [\n {\n startAngle: this.minAvgPitch,\n endAngle: this.maxAvgPitch,\n fillColor: this.barColor(PitchRollPriorityElement.pitch),\n },\n ];\n\n const subWatch = (\n rotation: number,\n arcFrame: typeof rollFrame.subArcFrame,\n areas: WatchArea[],\n barAreas: typeof rollBars,\n needles: typeof rollNeedles,\n advices: AngleAdviceRaw[],\n clipPath: string\n ) => html`\n <obc-watch\n class=\"sub-watch\"\n style=\"transform: rotate(${rotation}deg); clip-path: ${clipPath};\"\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${true}\n .arcFrame=${arcFrame}\n .areas=${areas}\n .barAreas=${barAreas}\n .needles=${needles}\n .vessels=${[]}\n .tickmarks=${tickmarks}\n .advices=${advices}\n ></obc-watch>\n `;\n\n return html`\n ${subWatch(\n 0,\n rollFrame.subArcFrame,\n rollAreas,\n rollBars,\n rollNeedles,\n rollAdvices,\n rollClip\n )}\n ${subWatch(\n 90,\n pitchFrame.subArcFrame,\n pitchAreas,\n pitchBars,\n pitchNeedles,\n pitchAdvices,\n pitchClip\n )}\n ${subWatch(\n 180,\n rollFrame.subArcFrame,\n rollAreas,\n rollBars,\n rollNeedles,\n rollAdvices,\n rollClip\n )}\n ${subWatch(\n 270,\n pitchFrame.subArcFrame,\n pitchAreas,\n pitchBars,\n pitchNeedles,\n pitchAdvices,\n pitchClip\n )}\n `;\n }\n\n /**\n * Caution advices for a single sub-watch axis, emitted at sub-watch local\n * angles (centred on 0°). The outer extent is clamped to the actually\n * rendered band half-extent (`halfDeg`) so advices fit naturally inside\n * the visible arc and are not visually cropped by the sub-watch's sector\n * clip-path. The clip-path itself remains in place to crop the needle.\n */\n private subAdvices(\n axis: 'pitch' | 'roll',\n halfDeg: number\n ): AngleAdviceRaw[] {\n const advices: AngleAdviceRaw[] = [];\n const max = axis === 'pitch' ? this.maxPitchAdvice : this.maxRollAdvice;\n if (max === undefined) return advices;\n const trigger =\n axis === 'pitch' ? this.triggerPitchAdvice : this.triggerRollAdvice;\n const cap = axis === 'pitch' ? 30 : 45;\n const outer = Math.min(halfDeg, cap);\n const inner = Math.min(max, outer);\n const state = trigger ? AdviceState.triggered : AdviceState.regular;\n advices.push({\n minAngle: -outer,\n maxAngle: -inner,\n type: AdviceType.caution,\n state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: inner,\n maxAngle: outer,\n type: AdviceType.caution,\n state,\n hideMaxTickmark: true,\n });\n return advices;\n }\n\n /** Full unzoomed watch — original single-instance render. */\n private renderFullWatch(areas: WatchArea[]) {\n return html`\n <obc-watch\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${false}\n .areas=${areas}\n .barAreas=${[\n {\n startAngle: this.minAvgRoll,\n endAngle: this.maxAvgRoll,\n fillColor: this.barColor(PitchRollPriorityElement.roll),\n },\n {\n startAngle: 180 + this.minAvgRoll,\n endAngle: 180 + this.maxAvgRoll,\n fillColor: this.barColor(PitchRollPriorityElement.roll),\n },\n {\n startAngle: 90 + this.minAvgPitch,\n endAngle: 90 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollPriorityElement.pitch),\n },\n {\n startAngle: 270 + this.minAvgPitch,\n endAngle: 270 + this.maxAvgPitch,\n fillColor: this.barColor(PitchRollPriorityElement.pitch),\n },\n ]}\n .needles=${[\n {\n angle: this.roll,\n fillColor: this.needleColor(PitchRollPriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: 180 + this.roll,\n fillColor: this.needleColor(PitchRollPriorityElement.roll),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: 90 + this.pitch,\n fillColor: this.needleColor(PitchRollPriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n {\n angle: 270 + this.pitch,\n fillColor: this.needleColor(PitchRollPriorityElement.pitch),\n strokeColor: 'var(--border-silhouette-color)',\n },\n ]}\n .vessels=${this.hasReadout\n ? []\n : [\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageSide,\n transform: `rotate(${this.pitch}deg)`,\n },\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageFore,\n transform: `rotate(${this.roll}deg) scale(${this.normalizedScaleForeImage})`,\n },\n ]}\n .tickmarks=${[\n {angle: 0, type: TickmarkType.main},\n {angle: 90, type: TickmarkType.main},\n {angle: 180, type: TickmarkType.main},\n {angle: 270, type: TickmarkType.main},\n ]}\n .advices=${this.advices}\n ></obc-watch>\n `;\n }\n\n private get advices(): AngleAdviceRaw[] {\n const pitchReq = this.requestedPitchArcAngle;\n const rollReq = this.requestedRollArcAngle;\n const advices = [];\n if (this.maxPitchAdvice !== undefined) {\n const outer = Math.min(pitchReq, 30);\n const inner = Math.min(this.maxPitchAdvice, outer);\n const state = this.triggerPitchAdvice\n ? AdviceState.triggered\n : AdviceState.regular;\n advices.push({\n minAngle: 90 - outer,\n maxAngle: 90 - inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: 90 + inner,\n maxAngle: 90 + outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n });\n advices.push({\n minAngle: 270 - outer,\n maxAngle: 270 - inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: 270 + inner,\n maxAngle: 270 + outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n });\n }\n if (this.maxRollAdvice !== undefined) {\n const outer = Math.min(rollReq, 45);\n const inner = Math.min(this.maxRollAdvice, outer);\n const state = this.triggerRollAdvice\n ? AdviceState.triggered\n : AdviceState.regular;\n advices.push({\n minAngle: -outer,\n maxAngle: -inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: inner,\n maxAngle: outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n });\n advices.push({\n minAngle: 180 - outer,\n maxAngle: 180 - inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: 180 + inner,\n maxAngle: 180 + outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n });\n }\n return advices;\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 .readout {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .readout-group {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: fit-content;\n }\n\n .readout-divider {\n align-self: stretch;\n height: 1px;\n background: var(--border-divider-color);\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-pitch-roll': ObcPitchRoll;\n }\n}\n"],"names":["PitchRollPriorityElement"],"mappings":"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"}
@@ -1,6 +1,24 @@
1
1
  import { LitElement } from 'lit';
2
2
  import { VesselImage } from '../watch/watch.js';
3
+ import { Priority } from '../types.js';
3
4
  import '../watch/watch.js';
5
+ import '../readout/readout.js';
6
+ export declare enum ObcRollType {
7
+ /** Single arc scale at the bottom (default). */
8
+ singleScale = "single-scale",
9
+ /** Bottom scale duplicated to the top as well. */
10
+ dualScale = "dual-scale"
11
+ }
12
+ /**
13
+ * `<obc-roll>` — Roll (heel) indicator with a bottom arc scale.
14
+ *
15
+ * Shows `roll` against a watch arc centred at the bottom, with an average-roll
16
+ * band and a rotating indicator. Supports an optional top scale (`dual-scale`),
17
+ * a centre readout (`hasReadout`), and a `regular`/`enhanced` palette. See the
18
+ * individual properties for details.
19
+ *
20
+ * @element obc-roll
21
+ */
4
22
  export declare class ObcRoll extends LitElement {
5
23
  roll: number;
6
24
  minAvgRoll: number;
@@ -10,6 +28,22 @@ export declare class ObcRoll extends LitElement {
10
28
  maxRollAdvice: number | undefined;
11
29
  triggerRollAdvice: boolean;
12
30
  zoomToFitArc: boolean;
31
+ /**
32
+ * When `true`, the centre shows an `<obc-readout>` with the roll value
33
+ * (label `Roll`, unit `DEG`) instead of the horizon line, rotating indicator
34
+ * and vessel. Default `false`.
35
+ */
36
+ hasReadout: boolean;
37
+ /**
38
+ * `single-scale` shows one arc at the bottom (default); `dual-scale` also
39
+ * shows the scale on the top arc (the indicator's opposite end).
40
+ */
41
+ type: ObcRollType;
42
+ /**
43
+ * Colour palette for the scale fill / indicator and the readout value:
44
+ * `regular` (default) or `enhanced`.
45
+ */
46
+ priority: Priority;
13
47
  /**
14
48
  * Half-extent of the watch arc in degrees. The arc spans `180° ± arcAngle`
15
49
  * and roll values are placed at their true position within it. Default
@@ -24,7 +58,10 @@ export declare class ObcRoll extends LitElement {
24
58
  arcAngle: number;
25
59
  private _arcFrame;
26
60
  private get normalizedScaleForeImage();
61
+ private get scaleFillColor();
62
+ private get indicatorColor();
27
63
  render(): import('lit-html').TemplateResult<1>;
64
+ private renderScale;
28
65
  private get advices();
29
66
  static styles: import('lit').CSSResult;
30
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"roll.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/roll/roll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA0B,MAAM,KAAK,CAAC;AAExD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAEL,WAAW,EAKZ,MAAM,mBAAmB,CAAC;AAe3B,qBACa,OAAQ,SAAQ,UAAU;IACX,IAAI,SAAK;IACT,UAAU,SAAK;IACf,UAAU,SAAK;IACf,eAAe,EAAE,WAAW,CAAuB;IACnD,cAAc,SAAK;IACnB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAa;IAC7C,iBAAiB,UAAS;IAC1B,YAAY,EAAE,OAAO,CAAS;IACzD;;;;;;;;;;OAUG;IACuB,QAAQ,EAAE,MAAM,CAAM;IAEhD,OAAO,CAAC,SAAS,CAAgC;IAEjD,OAAO,KAAK,wBAAwB,GAKnC;IAEQ,MAAM;IA8Hf,OAAO,KAAK,OAAO,GA2BlB;IAED,OAAgB,MAAM,0BAkBpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,UAAU,EAAE,OAAO,CAAC;KACrB;CACF"}
1
+ {"version":3,"file":"roll.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/roll/roll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA0B,MAAM,KAAK,CAAC;AAExD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAEL,WAAW,EAMZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,uBAAuB,CAAC;AAE/B,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAerC,oBAAY,WAAW;IACrB,gDAAgD;IAChD,WAAW,iBAAiB;IAC5B,kDAAkD;IAClD,SAAS,eAAe;CACzB;AAED;;;;;;;;;GASG;AACH,qBACa,OAAQ,SAAQ,UAAU;IACX,IAAI,SAAK;IACT,UAAU,SAAK;IACf,UAAU,SAAK;IACf,eAAe,EAAE,WAAW,CAAuB;IACnD,cAAc,SAAK;IACnB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAa;IAC7C,iBAAiB,UAAS;IAC1B,YAAY,EAAE,OAAO,CAAS;IACzD;;;;OAIG;IACwB,UAAU,EAAE,OAAO,CAAS;IACvD;;;OAGG;IACuB,IAAI,EAAE,WAAW,CAA2B;IACtE;;;OAGG;IACuB,QAAQ,EAAE,QAAQ,CAAoB;IAChE;;;;;;;;;;OAUG;IACuB,QAAQ,EAAE,MAAM,CAAM;IAEhD,OAAO,CAAC,SAAS,CAAgC;IAEjD,OAAO,KAAK,wBAAwB,GAKnC;IAED,OAAO,KAAK,cAAc,GAIzB;IAED,OAAO,KAAK,cAAc,GAIzB;IAEQ,MAAM;IA+Gf,OAAO,CAAC,WAAW;IAuCnB,OAAO,KAAK,OAAO,GA4BlB;IAED,OAAgB,MAAM,0BA4BpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,UAAU,EAAE,OAAO,CAAC;KACrB;CACF"}
@@ -1,11 +1,13 @@
1
1
  import { css, LitElement, nothing, svg, html } from "lit";
2
2
  import { property } from "lit/decorators.js";
3
3
  import { innerRingRadiusFor, WatchCircleType, OUTER_RING_RADIUS } from "../watch/watch.js";
4
+ import { ReadoutVariant, ReadoutDirection } from "../readout/readout.js";
5
+ import { Priority } from "../types.js";
4
6
  import { TickmarkType } from "../watch/tickmark.js";
5
7
  import { AdviceState, AdviceType } from "../watch/advice.js";
6
8
  import { customElement } from "../../decorator.js";
7
9
  import { normalizeArcAngle, computeZoomToFitArcFrame, shiftArcFrameToOuterEdge } from "../../svghelpers/arc-frame.js";
8
- import { VesselImage, VesselImageSize, vesselImages } from "../watch/vessel.js";
10
+ import { VesselImage, vesselImages, VesselImageSize } from "../watch/vessel.js";
9
11
  var __defProp = Object.defineProperty;
10
12
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
13
  var __decorateClass = (decorators, target, key, kind) => {
@@ -18,6 +20,11 @@ var __decorateClass = (decorators, target, key, kind) => {
18
20
  };
19
21
  const watchRadius = OUTER_RING_RADIUS;
20
22
  const CENTRE_HALF = 200;
23
+ var ObcRollType = /* @__PURE__ */ ((ObcRollType2) => {
24
+ ObcRollType2["singleScale"] = "single-scale";
25
+ ObcRollType2["dualScale"] = "dual-scale";
26
+ return ObcRollType2;
27
+ })(ObcRollType || {});
21
28
  let ObcRoll = class extends LitElement {
22
29
  constructor() {
23
30
  super(...arguments);
@@ -29,6 +36,9 @@ let ObcRoll = class extends LitElement {
29
36
  this.maxRollAdvice = void 0;
30
37
  this.triggerRollAdvice = false;
31
38
  this.zoomToFitArc = false;
39
+ this.hasReadout = false;
40
+ this.type = "single-scale";
41
+ this.priority = Priority.regular;
32
42
  this.arcAngle = 45;
33
43
  }
34
44
  get normalizedScaleForeImage() {
@@ -37,6 +47,12 @@ let ObcRoll = class extends LitElement {
37
47
  }
38
48
  return Math.max(0, Math.min(2, this.scaleForeImage));
39
49
  }
50
+ get scaleFillColor() {
51
+ return this.priority === Priority.enhanced ? "var(--instrument-enhanced-tertiary-color)" : "var(--instrument-regular-tertiary-color)";
52
+ }
53
+ get indicatorColor() {
54
+ return this.priority === Priority.enhanced ? "var(--instrument-enhanced-secondary-color)" : "var(--instrument-regular-secondary-color)";
55
+ }
40
56
  render() {
41
57
  const arcAngle = normalizeArcAngle(this.arcAngle, 45);
42
58
  const x = watchRadius * Math.sin(arcAngle * Math.PI / 180);
@@ -74,97 +90,117 @@ let ObcRoll = class extends LitElement {
74
90
  return html`
75
91
  <div class="container">
76
92
  <svg viewBox="${centreViewBox}">
77
- ${svg`
78
- <line
79
- x1="-${watchRadius}"
80
- y1="0"
81
- x2="${watchRadius}"
82
- y2="0"
83
- stroke="var(--instrument-frame-tertiary-color)"
84
- />
85
- <line
86
- x1="0"
87
- y1="0"
88
- y2="${watchRadius - 10}"
89
- x2="0"
90
- stroke="var(--instrument-enhanced-secondary-color)"
91
- transform="${needleTransform}"
92
- />
93
- <g
94
- style="transform: rotate(${this.roll}deg) scale(${vesselScale * this.normalizedScaleForeImage}) translate(-80px, -80px);"
95
- >
96
- ${this.zoomToFitArc ? vesselImages[this.vesselImageFore] : nothing}
97
- </g>
98
- ${this.zoomToFitArc ? nothing : svg`
99
- <path
100
- d="M ${-x} ${y} A ${watchRadius} ${watchRadius} 0 1 1 ${x} ${y}"
101
- fill="none"
102
- stroke="var(--instrument-frame-tertiary-color)"
103
- />
104
- `}
105
- `}
93
+ ${this.hasReadout ? nothing : svg`
94
+ <line
95
+ x1="-${watchRadius}"
96
+ y1="0"
97
+ x2="${watchRadius}"
98
+ y2="0"
99
+ stroke="var(--instrument-frame-tertiary-color)"
100
+ />
101
+ <line
102
+ x1="0"
103
+ y1="0"
104
+ y2="${watchRadius - 10}"
105
+ x2="0"
106
+ stroke="${this.indicatorColor}"
107
+ transform="${needleTransform}"
108
+ />
109
+ <g
110
+ style="transform: rotate(${this.roll}deg) scale(${vesselScale * this.normalizedScaleForeImage}) translate(-80px, -80px);"
111
+ >
112
+ ${this.zoomToFitArc ? vesselImages[this.vesselImageFore] : nothing}
113
+ </g>
114
+ `}
115
+ ${this.zoomToFitArc ? nothing : svg`
116
+ <path
117
+ d="M ${-x} ${y} A ${watchRadius} ${watchRadius} 0 1 1 ${x} ${y}"
118
+ fill="none"
119
+ stroke="var(--instrument-frame-tertiary-color)"
120
+ />
121
+ `}
106
122
  </svg>
107
- <obc-watch
108
- .watchCircleType=${WatchCircleType.double}
109
- .zoomToFitArc=${this.zoomToFitArc}
110
- .arcFrame=${this._arcFrame}
111
- tickmarksInside
112
- .areas=${areas}
113
- .barAreas=${[
123
+ ${this.renderScale(areas, false)}
124
+ ${this.type === "dual-scale" ? this.renderScale(areas, true) : nothing}
125
+ ${this.hasReadout ? html`<div class="readout">
126
+ <obc-readout
127
+ .variant=${ReadoutVariant.enhanced}
128
+ .direction=${ReadoutDirection.vertical}
129
+ .hasSetpoint=${false}
130
+ .hasAdvice=${false}
131
+ .value=${this.roll}
132
+ .fractionDigits=${0}
133
+ .valuePriority=${this.priority}
134
+ label="Roll"
135
+ unit="DEG"
136
+ ></obc-readout>
137
+ </div>` : nothing}
138
+ </div>
139
+ `;
140
+ }
141
+ // `top` rotates a second watch 180° onto the top arc for dual-scale — a
142
+ // rotation (opposite end of the indicator), not a mirror. A separate watch
143
+ // keeps the zoomed `arcFrame` correct.
144
+ renderScale(areas, top) {
145
+ return html`
146
+ <obc-watch
147
+ class=${top ? "scale-top" : nothing}
148
+ .priority=${this.priority}
149
+ .watchCircleType=${WatchCircleType.double}
150
+ .zoomToFitArc=${this.zoomToFitArc}
151
+ .arcFrame=${this._arcFrame}
152
+ tickmarksInside
153
+ .areas=${areas}
154
+ .barAreas=${[
114
155
  {
115
156
  startAngle: 180 + this.minAvgRoll,
116
157
  endAngle: 180 + this.maxAvgRoll,
117
- fillColor: "var(--instrument-enhanced-tertiary-color)"
158
+ fillColor: this.scaleFillColor
118
159
  }
119
160
  ]}
120
- .needles=${[
161
+ .needles=${[
121
162
  {
122
163
  angle: 180 + this.roll,
123
- fillColor: "var(--instrument-enhanced-secondary-color)",
164
+ fillColor: this.indicatorColor,
124
165
  strokeColor: "var(--border-silhouette-color)"
125
166
  }
126
167
  ]}
127
- .vessels=${this.zoomToFitArc ? [] : [
168
+ .vessels=${top || this.zoomToFitArc || this.hasReadout ? [] : [
128
169
  {
129
170
  size: VesselImageSize.large,
130
171
  vesselImage: this.vesselImageFore,
131
172
  transform: `rotate(${this.roll}deg) scale(${this.normalizedScaleForeImage})`
132
173
  }
133
174
  ]}
134
- .tickmarks=${[
135
- {
136
- angle: 180,
137
- type: TickmarkType.main
138
- }
139
- ]}
140
- .advices=${this.advices}
141
- ></obc-watch>
142
- </div>
175
+ .tickmarks=${[{ angle: 180, type: TickmarkType.main }]}
176
+ .advices=${this.advices}
177
+ ></obc-watch>
143
178
  `;
144
179
  }
145
180
  get advices() {
146
- const advices = [];
147
- if (this.maxRollAdvice !== void 0) {
148
- const arcAngle = normalizeArcAngle(this.arcAngle, 45);
149
- const outer = Math.min(arcAngle, 45);
150
- const inner = Math.min(this.maxRollAdvice, outer);
151
- const state = this.triggerRollAdvice ? AdviceState.triggered : AdviceState.regular;
152
- advices.push({
181
+ if (this.maxRollAdvice === void 0) {
182
+ return [];
183
+ }
184
+ const arcAngle = normalizeArcAngle(this.arcAngle, 45);
185
+ const outer = Math.min(arcAngle, 45);
186
+ const inner = Math.min(this.maxRollAdvice, outer);
187
+ const state = this.triggerRollAdvice ? AdviceState.triggered : AdviceState.regular;
188
+ return [
189
+ {
153
190
  minAngle: 180 - outer,
154
191
  maxAngle: 180 - inner,
155
192
  type: AdviceType.caution,
156
193
  state,
157
194
  hideMinTickmark: true
158
- });
159
- advices.push({
195
+ },
196
+ {
160
197
  minAngle: 180 + inner,
161
198
  maxAngle: 180 + outer,
162
199
  type: AdviceType.caution,
163
200
  state,
164
201
  hideMaxTickmark: true
165
- });
166
- }
167
- return advices;
202
+ }
203
+ ];
168
204
  }
169
205
  };
170
206
  ObcRoll.styles = css`
@@ -185,6 +221,16 @@ ObcRoll.styles = css`
185
221
  width: 100%;
186
222
  height: 100%;
187
223
  }
224
+
225
+ .readout {
226
+ display: flex;
227
+ align-items: center;
228
+ justify-content: center;
229
+ }
230
+
231
+ .scale-top {
232
+ transform: rotate(180deg);
233
+ }
188
234
  `;
189
235
  __decorateClass([
190
236
  property({ type: Number })
@@ -210,6 +256,15 @@ __decorateClass([
210
256
  __decorateClass([
211
257
  property({ type: Boolean })
212
258
  ], ObcRoll.prototype, "zoomToFitArc", 2);
259
+ __decorateClass([
260
+ property({ type: Boolean })
261
+ ], ObcRoll.prototype, "hasReadout", 2);
262
+ __decorateClass([
263
+ property({ type: String })
264
+ ], ObcRoll.prototype, "type", 2);
265
+ __decorateClass([
266
+ property({ type: String })
267
+ ], ObcRoll.prototype, "priority", 2);
213
268
  __decorateClass([
214
269
  property({ type: Number })
215
270
  ], ObcRoll.prototype, "arcAngle", 2);
@@ -217,6 +272,7 @@ ObcRoll = __decorateClass([
217
272
  customElement("obc-roll")
218
273
  ], ObcRoll);
219
274
  export {
220
- ObcRoll
275
+ ObcRoll,
276
+ ObcRollType
221
277
  };
222
278
  //# sourceMappingURL=roll.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"roll.js","sources":["../../../src/navigation-instruments/roll/roll.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {\n OUTER_RING_RADIUS,\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n innerRingRadiusFor,\n vesselImages,\n} from '../watch/watch.js';\nimport {TickmarkType} from '../watch/tickmark.js';\nimport {AdviceState, AdviceType, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {\n computeZoomToFitArcFrame,\n normalizeArcAngle,\n shiftArcFrameToOuterEdge,\n type ZoomToFitArcFrame,\n} from '../../svghelpers/arc-frame.js';\n\nconst watchRadius = OUTER_RING_RADIUS;\n/** Half-side of the centre overlay viewBox in SVG units. */\nconst CENTRE_HALF = 200;\n\n@customElement('obc-roll')\nexport class ObcRoll extends LitElement {\n @property({type: Number}) roll = 0;\n @property({type: Number}) minAvgRoll = 0;\n @property({type: Number}) maxAvgRoll = 0;\n @property({type: String}) vesselImageFore: VesselImage = VesselImage.psvFore;\n @property({type: Number}) scaleForeImage = 1;\n @property({type: Number}) maxRollAdvice: number | undefined = undefined;\n @property({type: Boolean}) triggerRollAdvice = false;\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n /**\n * Half-extent of the watch arc in degrees. The arc spans `180° ± arcAngle`\n * and roll values are placed at their true position within it. Default\n * `45` reproduces the historical 90°-wide arc.\n *\n * Smaller values render a narrower arc. Combined with `zoomToFitArc`, the\n * narrower arc is enlarged (its radius grows) on its own layer, while the\n * vessel image and the rotating indicator line stay at their natural size\n * and position on a separate central layer. The two layers are\n * intentionally visually disconnected.\n */\n @property({type: Number}) arcAngle: number = 45;\n\n private _arcFrame: ZoomToFitArcFrame | undefined;\n\n private get normalizedScaleForeImage(): number {\n if (!Number.isFinite(this.scaleForeImage)) {\n return 1;\n }\n return Math.max(0, Math.min(2, this.scaleForeImage));\n }\n\n override render() {\n const arcAngle = normalizeArcAngle(this.arcAngle, 45);\n // Outer thin-ring complement endpoints. The arc band is centred at\n // watch angle 180° (bottom) and spans 180° ± arcAngle, so its edges\n // sit at SVG coords (±R·sin(arcAngle), R·cos(arcAngle)).\n const x = watchRadius * Math.sin((arcAngle * Math.PI) / 180);\n const y = watchRadius * Math.cos((arcAngle * Math.PI) / 180);\n\n const areas = [\n {\n startAngle: 180 - arcAngle,\n endAngle: 180 + arcAngle,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n\n if (this.zoomToFitArc) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n // Pure arc-only fit (compass-sector style). The viewBox is centred on\n // the enlarged arc bbox, so the origin (centre of the instrument) is\n // typically OUTSIDE this viewBox. The vessel and central elements\n // therefore need their own normal-scale layer.\n const baseFrame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerRingRadiusFor(WatchCircleType.double),\n extension: ext,\n targetSize,\n });\n // Push the enlarged arc to the side so its outer edge aligns with the\n // central layer's outer ring. Direction is derived from the arc bbox\n // centre so left/right/top/bottom is handled automatically.\n this._arcFrame = shiftArcFrameToOuterEdge(\n baseFrame,\n OUTER_RING_RADIUS + baseFrame.radiusOffset,\n OUTER_RING_RADIUS,\n CENTRE_HALF\n );\n } else {\n this._arcFrame = undefined;\n }\n\n const needleTransform = `rotate(${this.roll} 0 0)`;\n const centreViewBox = `-${CENTRE_HALF} -${CENTRE_HALF} ${CENTRE_HALF * 2} ${CENTRE_HALF * 2}`;\n const vesselScale = 224 / 160;\n\n return html`\n <div class=\"container\">\n <svg viewBox=\"${centreViewBox}\">\n ${svg`\n <line\n x1=\"-${watchRadius}\"\n y1=\"0\"\n x2=\"${watchRadius}\"\n y2=\"0\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n <line\n x1=\"0\"\n y1=\"0\"\n y2=\"${watchRadius - 10}\"\n x2=\"0\"\n stroke=\"var(--instrument-enhanced-secondary-color)\"\n transform=\"${needleTransform}\"\n />\n <g\n style=\"transform: rotate(${this.roll}deg) scale(${vesselScale * this.normalizedScaleForeImage}) translate(-80px, -80px);\"\n >\n ${this.zoomToFitArc ? vesselImages[this.vesselImageFore] : nothing}\n </g>\n ${\n this.zoomToFitArc\n ? nothing\n : svg`\n <path\n d=\"M ${-x} ${y} A ${watchRadius} ${watchRadius} 0 1 1 ${x} ${y}\"\n fill=\"none\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n `\n }\n `}\n </svg>\n <obc-watch\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${this.zoomToFitArc}\n .arcFrame=${this._arcFrame}\n tickmarksInside\n .areas=${areas}\n .barAreas=${[\n {\n startAngle: 180 + this.minAvgRoll,\n endAngle: 180 + this.maxAvgRoll,\n fillColor: 'var(--instrument-enhanced-tertiary-color)',\n },\n ]}\n .needles=${[\n {\n angle: 180 + this.roll,\n fillColor: 'var(--instrument-enhanced-secondary-color)',\n strokeColor: 'var(--border-silhouette-color)',\n },\n ]}\n .vessels=${this.zoomToFitArc\n ? []\n : [\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageFore,\n transform: `rotate(${this.roll}deg) scale(${this.normalizedScaleForeImage})`,\n },\n ]}\n .tickmarks=${[\n {\n angle: 180,\n type: TickmarkType.main,\n },\n ]}\n .advices=${this.advices}\n ></obc-watch>\n </div>\n `;\n }\n\n private get advices(): AngleAdviceRaw[] {\n const advices = [];\n if (this.maxRollAdvice !== undefined) {\n const arcAngle = normalizeArcAngle(this.arcAngle, 45);\n // Caution band fills the remainder of the arc out to a default 45°\n // caution range (clamped to the arc edge).\n const outer = Math.min(arcAngle, 45);\n const inner = Math.min(this.maxRollAdvice, outer);\n const state = this.triggerRollAdvice\n ? AdviceState.triggered\n : AdviceState.regular;\n advices.push({\n minAngle: 180 - outer,\n maxAngle: 180 - inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n });\n advices.push({\n minAngle: 180 + inner,\n maxAngle: 180 + outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n });\n }\n return advices;\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-roll': ObcRoll;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"roll.js","sources":["../../../src/navigation-instruments/roll/roll.ts"],"sourcesContent":["import {LitElement, css, html, nothing, svg} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport '../watch/watch.js';\nimport {\n OUTER_RING_RADIUS,\n VesselImage,\n VesselImageSize,\n WatchCircleType,\n innerRingRadiusFor,\n vesselImages,\n type WatchArea,\n} from '../watch/watch.js';\nimport '../readout/readout.js';\nimport {ReadoutDirection, ReadoutVariant} from '../readout/readout.js';\nimport {Priority} from '../types.js';\nimport {TickmarkType} from '../watch/tickmark.js';\nimport {AdviceState, AdviceType, AngleAdviceRaw} from '../watch/advice.js';\nimport {customElement} from '../../decorator.js';\nimport {\n computeZoomToFitArcFrame,\n normalizeArcAngle,\n shiftArcFrameToOuterEdge,\n type ZoomToFitArcFrame,\n} from '../../svghelpers/arc-frame.js';\n\nconst watchRadius = OUTER_RING_RADIUS;\n/** Half-side of the centre overlay viewBox in SVG units. */\nconst CENTRE_HALF = 200;\n\nexport enum ObcRollType {\n /** Single arc scale at the bottom (default). */\n singleScale = 'single-scale',\n /** Bottom scale duplicated to the top as well. */\n dualScale = 'dual-scale',\n}\n\n/**\n * `<obc-roll>` — Roll (heel) indicator with a bottom arc scale.\n *\n * Shows `roll` against a watch arc centred at the bottom, with an average-roll\n * band and a rotating indicator. Supports an optional top scale (`dual-scale`),\n * a centre readout (`hasReadout`), and a `regular`/`enhanced` palette. See the\n * individual properties for details.\n *\n * @element obc-roll\n */\n@customElement('obc-roll')\nexport class ObcRoll extends LitElement {\n @property({type: Number}) roll = 0;\n @property({type: Number}) minAvgRoll = 0;\n @property({type: Number}) maxAvgRoll = 0;\n @property({type: String}) vesselImageFore: VesselImage = VesselImage.psvFore;\n @property({type: Number}) scaleForeImage = 1;\n @property({type: Number}) maxRollAdvice: number | undefined = undefined;\n @property({type: Boolean}) triggerRollAdvice = false;\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n /**\n * When `true`, the centre shows an `<obc-readout>` with the roll value\n * (label `Roll`, unit `DEG`) instead of the horizon line, rotating indicator\n * and vessel. Default `false`.\n */\n @property({type: Boolean}) hasReadout: boolean = false;\n /**\n * `single-scale` shows one arc at the bottom (default); `dual-scale` also\n * shows the scale on the top arc (the indicator's opposite end).\n */\n @property({type: String}) type: ObcRollType = ObcRollType.singleScale;\n /**\n * Colour palette for the scale fill / indicator and the readout value:\n * `regular` (default) or `enhanced`.\n */\n @property({type: String}) priority: Priority = Priority.regular;\n /**\n * Half-extent of the watch arc in degrees. The arc spans `180° ± arcAngle`\n * and roll values are placed at their true position within it. Default\n * `45` reproduces the historical 90°-wide arc.\n *\n * Smaller values render a narrower arc. Combined with `zoomToFitArc`, the\n * narrower arc is enlarged (its radius grows) on its own layer, while the\n * vessel image and the rotating indicator line stay at their natural size\n * and position on a separate central layer. The two layers are\n * intentionally visually disconnected.\n */\n @property({type: Number}) arcAngle: number = 45;\n\n private _arcFrame: ZoomToFitArcFrame | undefined;\n\n private get normalizedScaleForeImage(): number {\n if (!Number.isFinite(this.scaleForeImage)) {\n return 1;\n }\n return Math.max(0, Math.min(2, this.scaleForeImage));\n }\n\n private get scaleFillColor(): string {\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n private get indicatorColor(): string {\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n override render() {\n const arcAngle = normalizeArcAngle(this.arcAngle, 45);\n // Outer thin-ring complement endpoints. The arc band is centred at\n // watch angle 180° (bottom) and spans 180° ± arcAngle, so its edges\n // sit at SVG coords (±R·sin(arcAngle), R·cos(arcAngle)).\n const x = watchRadius * Math.sin((arcAngle * Math.PI) / 180);\n const y = watchRadius * Math.cos((arcAngle * Math.PI) / 180);\n\n const areas: WatchArea[] = [\n {\n startAngle: 180 - arcAngle,\n endAngle: 180 + arcAngle,\n roundOutsideCut: true,\n roundInsideCut: true,\n },\n ];\n\n if (this.zoomToFitArc) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n // Pure arc-only fit (compass-sector style). The viewBox is centred on\n // the enlarged arc bbox, so the origin (centre of the instrument) is\n // typically OUTSIDE this viewBox. The vessel and central elements\n // therefore need their own normal-scale layer.\n const baseFrame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerRingRadiusFor(WatchCircleType.double),\n extension: ext,\n targetSize,\n });\n // Push the enlarged arc to the side so its outer edge aligns with the\n // central layer's outer ring. Direction is derived from the arc bbox\n // centre so left/right/top/bottom is handled automatically.\n this._arcFrame = shiftArcFrameToOuterEdge(\n baseFrame,\n OUTER_RING_RADIUS + baseFrame.radiusOffset,\n OUTER_RING_RADIUS,\n CENTRE_HALF\n );\n } else {\n this._arcFrame = undefined;\n }\n\n const needleTransform = `rotate(${this.roll} 0 0)`;\n const centreViewBox = `-${CENTRE_HALF} -${CENTRE_HALF} ${CENTRE_HALF * 2} ${CENTRE_HALF * 2}`;\n const vesselScale = 224 / 160;\n\n return html`\n <div class=\"container\">\n <svg viewBox=\"${centreViewBox}\">\n ${this.hasReadout\n ? nothing\n : svg`\n <line\n x1=\"-${watchRadius}\"\n y1=\"0\"\n x2=\"${watchRadius}\"\n y2=\"0\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n <line\n x1=\"0\"\n y1=\"0\"\n y2=\"${watchRadius - 10}\"\n x2=\"0\"\n stroke=\"${this.indicatorColor}\"\n transform=\"${needleTransform}\"\n />\n <g\n style=\"transform: rotate(${this.roll}deg) scale(${vesselScale * this.normalizedScaleForeImage}) translate(-80px, -80px);\"\n >\n ${this.zoomToFitArc ? vesselImages[this.vesselImageFore] : nothing}\n </g>\n `}\n ${this.zoomToFitArc\n ? nothing\n : svg`\n <path\n d=\"M ${-x} ${y} A ${watchRadius} ${watchRadius} 0 1 1 ${x} ${y}\"\n fill=\"none\"\n stroke=\"var(--instrument-frame-tertiary-color)\"\n />\n `}\n </svg>\n ${this.renderScale(areas, false)}\n ${this.type === ObcRollType.dualScale\n ? this.renderScale(areas, true)\n : nothing}\n ${this.hasReadout\n ? html`<div class=\"readout\">\n <obc-readout\n .variant=${ReadoutVariant.enhanced}\n .direction=${ReadoutDirection.vertical}\n .hasSetpoint=${false}\n .hasAdvice=${false}\n .value=${this.roll}\n .fractionDigits=${0}\n .valuePriority=${this.priority}\n label=\"Roll\"\n unit=\"DEG\"\n ></obc-readout>\n </div>`\n : nothing}\n </div>\n `;\n }\n\n // `top` rotates a second watch 180° onto the top arc for dual-scale — a\n // rotation (opposite end of the indicator), not a mirror. A separate watch\n // keeps the zoomed `arcFrame` correct.\n private renderScale(areas: WatchArea[], top: boolean) {\n return html`\n <obc-watch\n class=${top ? 'scale-top' : nothing}\n .priority=${this.priority}\n .watchCircleType=${WatchCircleType.double}\n .zoomToFitArc=${this.zoomToFitArc}\n .arcFrame=${this._arcFrame}\n tickmarksInside\n .areas=${areas}\n .barAreas=${[\n {\n startAngle: 180 + this.minAvgRoll,\n endAngle: 180 + this.maxAvgRoll,\n fillColor: this.scaleFillColor,\n },\n ]}\n .needles=${[\n {\n angle: 180 + this.roll,\n fillColor: this.indicatorColor,\n strokeColor: 'var(--border-silhouette-color)',\n },\n ]}\n .vessels=${top || this.zoomToFitArc || this.hasReadout\n ? []\n : [\n {\n size: VesselImageSize.large,\n vesselImage: this.vesselImageFore,\n transform: `rotate(${this.roll}deg) scale(${this.normalizedScaleForeImage})`,\n },\n ]}\n .tickmarks=${[{angle: 180, type: TickmarkType.main}]}\n .advices=${this.advices}\n ></obc-watch>\n `;\n }\n\n private get advices(): AngleAdviceRaw[] {\n if (this.maxRollAdvice === undefined) {\n return [];\n }\n const arcAngle = normalizeArcAngle(this.arcAngle, 45);\n // Caution band fills the remainder of the arc out to a default 45° caution\n // range (clamped to the arc edge).\n const outer = Math.min(arcAngle, 45);\n const inner = Math.min(this.maxRollAdvice, outer);\n const state = this.triggerRollAdvice\n ? AdviceState.triggered\n : AdviceState.regular;\n return [\n {\n minAngle: 180 - outer,\n maxAngle: 180 - inner,\n type: AdviceType.caution,\n state: state,\n hideMinTickmark: true,\n },\n {\n minAngle: 180 + inner,\n maxAngle: 180 + outer,\n type: AdviceType.caution,\n state: state,\n hideMaxTickmark: true,\n },\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 .readout {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .scale-top {\n transform: rotate(180deg);\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-roll': ObcRoll;\n }\n}\n"],"names":["ObcRollType"],"mappings":"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"}
@@ -3,6 +3,7 @@ import { AdviceType } from '../watch/advice.js';
3
3
  import { Priority } from '../types.js';
4
4
  import { TickmarkStyle } from '../watch/tickmark.js';
5
5
  import '../../building-blocks/instrument-radial/instrument-radial.js';
6
+ import '../readout/readout.js';
6
7
  export declare enum ObcGaugeRadialType {
7
8
  filled = "filled",
8
9
  bar = "bar",
@@ -120,11 +121,25 @@ export declare class ObcRotSector extends ObcRotSector_base {
120
121
  advices: GaugeRadialAdvice[];
121
122
  zoomToFitArc: boolean;
122
123
  rotArcExtent: number;
124
+ /**
125
+ * When `true`, shows a centered `<obc-readout>` (label `ROT`, unit `DEG/min`)
126
+ * under the arc with the current rate-of-turn value. Default `false`.
127
+ */
128
+ hasReadout: boolean;
123
129
  getAngle: (v: number) => number;
124
130
  get _type(): ObcGaugeRadialType;
125
131
  private get _barColor();
132
+ /**
133
+ * Vertical position of the readout, in % of the host. In the zoomed view the
134
+ * arc's lower edge shifts with `rotArcExtent`, so the position is interpolated
135
+ * between the narrow- and wide-arc anchors to keep a roughly constant gap
136
+ * between the arc and the readout. The static (unzoomed) arc uses a fixed
137
+ * position.
138
+ */
139
+ private get _readoutTopPercent();
126
140
  render(): import('lit-html').TemplateResult<1>;
127
141
  private get _needleColor();
142
+ static styles: import('lit').CSSResult;
128
143
  }
129
144
  declare global {
130
145
  interface HTMLElementTagNameMap {
@@ -1 +1 @@
1
- {"version":3,"file":"rot-sector.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rot-sector/rot-sector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAO,MAAM,KAAK,CAAC;AAGrC,OAAO,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAErC,OAAO,8DAA8D,CAAC;AACtE,OAAO,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAEnD,oBAAY,kBAAkB;IAC5B,MAAM,WAAW;IACjB,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,qBACa,YAAa,SAAQ,iBAAyB;IAC/B,KAAK,SAAK;IACV,QAAQ,SAAO;IAEzC;;;;;OAKG;IACH,IACI,UAAU,CAAC,CAAC,EAAE,MAAM,EAEvB;IACD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACH,IACI,aAAa,CAAC,CAAC,EAAE,MAAM,EAE1B;IACD,IAAI,aAAa,IAAI,MAAM,CAE1B;IAC0B,UAAU,EAAE,OAAO,CAAS;IACvD,mDAAmD;IACxB,eAAe,EAAE,OAAO,CAAS;IAC5D;;;OAGG;IACuB,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAM;IAC3E;;;OAGG;IACuB,yBAAyB,EAAE,MAAM,GAAG,SAAS,CAAM;IAC7E;;;OAGG;IACuB,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAC1D;IACc,QAAQ,EAAE,QAAQ,CAAoB;IACrC,aAAa,EAAE,OAAO,CAAS;IAChC,aAAa,EAAE,aAAa,CAC9B;IACmB,OAAO,EAAE,iBAAiB,EAAE,CAAM;IAClD,YAAY,EAAE,OAAO,CAAS;IAC/B,YAAY,EAAE,MAAM,CAAM;IAEpD,QAAQ,GAAI,GAAG,MAAM,KAAG,MAAM,CAG5B;IAEF,IAAI,KAAK,IAAI,kBAAkB,CAE9B;IAED,OAAO,KAAK,SAAS,GAepB;IAEQ,MAAM;IAkCf,OAAO,KAAK,YAAY,GAgBvB;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,YAAY,CAAC;KAChC;CACF"}
1
+ {"version":3,"file":"rot-sector.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/rot-sector/rot-sector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAqB,MAAM,KAAK,CAAC;AAGnD,OAAO,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAErC,OAAO,8DAA8D,CAAC;AACtE,OAAO,uBAAuB,CAAC;AAE/B,OAAO,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAEnD,oBAAY,kBAAkB;IAC5B,MAAM,WAAW;IACjB,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,qBACa,YAAa,SAAQ,iBAAyB;IAC/B,KAAK,SAAK;IACV,QAAQ,SAAO;IAEzC;;;;;OAKG;IACH,IACI,UAAU,CAAC,CAAC,EAAE,MAAM,EAEvB;IACD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACH,IACI,aAAa,CAAC,CAAC,EAAE,MAAM,EAE1B;IACD,IAAI,aAAa,IAAI,MAAM,CAE1B;IAC0B,UAAU,EAAE,OAAO,CAAS;IACvD,mDAAmD;IACxB,eAAe,EAAE,OAAO,CAAS;IAC5D;;;OAGG;IACuB,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAM;IAC3E;;;OAGG;IACuB,yBAAyB,EAAE,MAAM,GAAG,SAAS,CAAM;IAC7E;;;OAGG;IACuB,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAC1D;IACc,QAAQ,EAAE,QAAQ,CAAoB;IACrC,aAAa,EAAE,OAAO,CAAS;IAChC,aAAa,EAAE,aAAa,CAC9B;IACmB,OAAO,EAAE,iBAAiB,EAAE,CAAM;IAClD,YAAY,EAAE,OAAO,CAAS;IAC/B,YAAY,EAAE,MAAM,CAAM;IACpD;;;OAGG;IACwB,UAAU,EAAE,OAAO,CAAS;IAEvD,QAAQ,GAAI,GAAG,MAAM,KAAG,MAAM,CAG5B;IAEF,IAAI,KAAK,IAAI,kBAAkB,CAE9B;IAED,OAAO,KAAK,SAAS,GAepB;IAED;;;;;;OAMG;IACH,OAAO,KAAK,kBAAkB,GAQ7B;IAEQ,MAAM;IAiDf,OAAO,KAAK,YAAY,GAgBvB;IAED,OAAgB,MAAM,0BAiBpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,YAAY,CAAC;KAChC;CACF"}