@ixfx/components 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/bundle/index.d.ts +213 -117
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +1356 -658
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.js +3 -3
  6. package/dist/ac-text.js.map +1 -1
  7. package/dist/{button-B9ztaKyl.js → button-DMt5XWUK.js} +4 -4
  8. package/dist/{button-B9ztaKyl.js.map → button-DMt5XWUK.js.map} +1 -1
  9. package/dist/button.js +1 -1
  10. package/dist/checkbox.d.ts +2 -3
  11. package/dist/checkbox.d.ts.map +1 -1
  12. package/dist/checkbox.js +1 -1
  13. package/dist/checkbox.js.map +1 -1
  14. package/dist/{colour-C3MQIjFJ-BJV-QC-3.js → colour-C3MQIjFJ-BLXg8W3U.js} +2 -2
  15. package/dist/{colour-C3MQIjFJ-BJV-QC-3.js.map → colour-C3MQIjFJ-BLXg8W3U.js.map} +1 -1
  16. package/dist/{colour-picker-BNqDz4wK.js → colour-picker-K6zu82lm.js} +5 -5
  17. package/dist/{colour-picker-BNqDz4wK.js.map → colour-picker-K6zu82lm.js.map} +1 -1
  18. package/dist/colour-picker.js +1 -1
  19. package/dist/crumbs.d.ts +2 -3
  20. package/dist/crumbs.d.ts.map +1 -1
  21. package/dist/crumbs.js +10 -10
  22. package/dist/crumbs.js.map +1 -1
  23. package/dist/data-display.js +3 -3
  24. package/dist/{decorate-O4m1U4l3.js → decorate-D7rC1gLP.js} +10 -8
  25. package/dist/decorate-D7rC1gLP.js.map +1 -0
  26. package/dist/{defaults-FEZaGiYZ.js → defaults-C7elhuyJ.js} +2 -2
  27. package/dist/{defaults-FEZaGiYZ.js.map → defaults-C7elhuyJ.js.map} +1 -1
  28. package/dist/{dist-By5URG0Y.js → dist-BX0OVIm7.js} +2 -2
  29. package/dist/{dist-By5URG0Y.js.map → dist-BX0OVIm7.js.map} +1 -1
  30. package/dist/{dist-D7kJgnSE.js → dist-TAGYwaju.js} +1 -1
  31. package/dist/{dist-D7kJgnSE.js.map → dist-TAGYwaju.js.map} +1 -1
  32. package/dist/editable-label.d.ts +6 -1
  33. package/dist/editable-label.d.ts.map +1 -1
  34. package/dist/editable-label.js +49 -2
  35. package/dist/editable-label.js.map +1 -1
  36. package/dist/{hex-editor-gH3mteMr.js → hex-editor-CsN_ySkH.js} +85 -85
  37. package/dist/hex-editor-CsN_ySkH.js.map +1 -0
  38. package/dist/{hex-editor-2_s0Ua5t.d.ts → hex-editor-DlfoA65y.d.ts} +5 -5
  39. package/dist/{hex-editor-2_s0Ua5t.d.ts.map → hex-editor-DlfoA65y.d.ts.map} +1 -1
  40. package/dist/hex.d.ts +1 -1
  41. package/dist/hex.js +1 -1
  42. package/dist/{highlight-CAjwQ4GE.js → highlight-TPbSHruI.js} +3 -3
  43. package/dist/highlight-TPbSHruI.js.map +1 -0
  44. package/dist/{icon-CYACf6o8.js → icon-9NWTXtE1.js} +4 -5
  45. package/dist/icon-9NWTXtE1.js.map +1 -0
  46. package/dist/icon-CeTDJhC7.d.ts.map +1 -1
  47. package/dist/icons.js +3 -3
  48. package/dist/{incr-search-BZawvrfl.js → incr-search-DSKKsk6w.js} +12 -10
  49. package/dist/incr-search-DSKKsk6w.js.map +1 -0
  50. package/dist/incr-search.d.ts +1 -1
  51. package/dist/incr-search.js +2 -2
  52. package/dist/{index-CwGkb9s1.d.ts → index--hrxPBkQ.d.ts} +69 -69
  53. package/dist/index--hrxPBkQ.d.ts.map +1 -0
  54. package/dist/{index-kY5gxbkI.d.ts → index-DSlPeWLK.d.ts} +15 -15
  55. package/dist/{index-kY5gxbkI.d.ts.map → index-DSlPeWLK.d.ts.map} +1 -1
  56. package/dist/{index-V2cJorlA.d.ts → index-hXFn14tM.d.ts} +4 -4
  57. package/dist/index-hXFn14tM.d.ts.map +1 -0
  58. package/dist/index.d.ts +109 -13
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +666 -24
  61. package/dist/index.js.map +1 -1
  62. package/dist/keyboard-De_vOHLg.js.map +1 -1
  63. package/dist/{labelled-input-base-BvgH7ldm.js → labelled-input-base-CqPL5rKm.js} +2 -2
  64. package/dist/labelled-input-base-CqPL5rKm.js.map +1 -0
  65. package/dist/labelled-radial-input.js +3 -3
  66. package/dist/labelled-radial-input.js.map +1 -1
  67. package/dist/labelled-range-input.js +2 -2
  68. package/dist/led.js +1 -1
  69. package/dist/{menu-C3eANB5M.js → menu-DJJuCm-5.js} +48 -48
  70. package/dist/menu-DJJuCm-5.js.map +1 -0
  71. package/dist/{menu-item-6IU5weHi.js → menu-item-CKRfP0pN.js} +10 -10
  72. package/dist/menu-item-CKRfP0pN.js.map +1 -0
  73. package/dist/menu.d.ts +1 -1
  74. package/dist/menu.js +2 -2
  75. package/dist/miller.d.ts +5 -7
  76. package/dist/miller.d.ts.map +1 -1
  77. package/dist/miller.js +14 -14
  78. package/dist/miller.js.map +1 -1
  79. package/dist/narrowed-text.d.ts.map +1 -1
  80. package/dist/narrowed-text.js +4 -4
  81. package/dist/narrowed-text.js.map +1 -1
  82. package/dist/panel.js +2 -2
  83. package/dist/panel.js.map +1 -1
  84. package/dist/plots.js +1 -1
  85. package/dist/polar-pad.d.ts.map +1 -1
  86. package/dist/polar-pad.js +1 -1
  87. package/dist/polar-pad.js.map +1 -1
  88. package/dist/{popup-Ddx9LCzY.js → popup-ImtS9KnS.js} +1 -1
  89. package/dist/{popup-Ddx9LCzY.js.map → popup-ImtS9KnS.js.map} +1 -1
  90. package/dist/{prominence-CreDBdCs.js → prominence--ic9uWBl.js} +1 -1
  91. package/dist/{prominence-CreDBdCs.js.map → prominence--ic9uWBl.js.map} +1 -1
  92. package/dist/{radial-input-Dbc6fgCK.js → radial-input-DZA6WaFu.js} +14 -14
  93. package/dist/radial-input-DZA6WaFu.js.map +1 -0
  94. package/dist/radial-input.js +1 -1
  95. package/dist/range-input.js +1 -1
  96. package/dist/range.js +2 -2
  97. package/dist/{registry-CZEB1YI9.js → registry-Q2gYQCHM.js} +1 -1
  98. package/dist/{registry-CZEB1YI9.js.map → registry-Q2gYQCHM.js.map} +1 -1
  99. package/dist/selecthorizontal.js +1 -1
  100. package/dist/snap-container.js +1 -1
  101. package/dist/split-layout.js +4 -4
  102. package/dist/split-layout.js.map +1 -1
  103. package/dist/swipe.d.ts +1 -2
  104. package/dist/swipe.d.ts.map +1 -1
  105. package/dist/swipe.js +2 -2
  106. package/dist/swipe.js.map +1 -1
  107. package/dist/tabs.js +2 -2
  108. package/dist/tabs.js.map +1 -1
  109. package/dist/{timeline-B62Sz6J_.js → timeline-Cv75Th2U.js} +120 -116
  110. package/dist/timeline-Cv75Th2U.js.map +1 -0
  111. package/dist/timeline.d.ts +1 -1
  112. package/dist/timeline.js +1 -1
  113. package/dist/tooltip-CwGfb4lp.d.ts.map +1 -1
  114. package/dist/tree-CvvKbO-f.js +1330 -0
  115. package/dist/tree-CvvKbO-f.js.map +1 -0
  116. package/dist/{tree-component-CQpoPo4s.d.ts → tree-component-D8Bg48tt.d.ts} +12 -12
  117. package/dist/{tree-component-CQpoPo4s.d.ts.map → tree-component-D8Bg48tt.d.ts.map} +1 -1
  118. package/dist/tree.d.ts +1 -1
  119. package/dist/tree.js +1 -1143
  120. package/dist/xy-axis-D9uwpGTT.d.ts.map +1 -1
  121. package/dist/{xy-axis-C7fNxDwY.js → xy-axis-DL0tfJDr.js} +10 -10
  122. package/dist/{xy-axis-C7fNxDwY.js.map → xy-axis-DL0tfJDr.js.map} +1 -1
  123. package/dist/xy-pad.js +2 -2
  124. package/package.json +3 -3
  125. package/dist/decorate-O4m1U4l3.js.map +0 -1
  126. package/dist/hex-editor-gH3mteMr.js.map +0 -1
  127. package/dist/highlight-CAjwQ4GE.js.map +0 -1
  128. package/dist/icon-CYACf6o8.js.map +0 -1
  129. package/dist/incr-search-BZawvrfl.js.map +0 -1
  130. package/dist/index-CwGkb9s1.d.ts.map +0 -1
  131. package/dist/index-V2cJorlA.d.ts.map +0 -1
  132. package/dist/labelled-input-base-BvgH7ldm.js.map +0 -1
  133. package/dist/menu-C3eANB5M.js.map +0 -1
  134. package/dist/menu-item-6IU5weHi.js.map +0 -1
  135. package/dist/radial-input-Dbc6fgCK.js.map +0 -1
  136. package/dist/timeline-B62Sz6J_.js.map +0 -1
  137. package/dist/tree-data-model-DGvRVOFY.js +0 -190
  138. package/dist/tree-data-model-DGvRVOFY.js.map +0 -1
  139. package/dist/tree.js.map +0 -1
  140. /package/dist/{interaction-CQDQJf2Q.js → interaction-DG7X1rhI.js} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radial-input-DZA6WaFu.js","names":["#_radius","#dragging","#dragStartY","#valueAtDragStart","#onPointerMove","#onPointerUp","#setValueFromRelative","#getRelativeValue","#lanes","#quantise","#isUserInteraction","#scheduleChangeEvent","#fireChangeEvent","#changeDebounceTimer","#getCssVar","#getEffectiveMarkerStyle","#getNeedlePath","#onPointerDown","#onKeyDown","#renderCircleFill","#renderWedge","#renderCircleBorder","#renderLane","#renderMidpointMarker","#renderValueMarker","customElement"],"sources":["../src/radial-input/svg-utils.ts","../src/radial-input/radial-input.ts"],"sourcesContent":["/**\n * SVG utilities for radial input component\n * Handles geometry calculations for flattened circle arcs\n */\n\nimport type { ValueMode } from './types.js';\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface ArcParameters {\n startAngle: number; // radians\n endAngle: number; // radians\n radius: number;\n center: Point;\n}\n\nconst PI2 = Math.PI * 2;\nconst MIDPOINT_ANGLE = -Math.PI / 2; // Top-center of circle\n\n/**\n * Convert polar coordinates (angle in radians, radius) to SVG Cartesian coordinates\n * @param angle - Angle in radians (0 = right/east, increases clockwise in SVG)\n * @param radius - Distance from center\n * @param center - Center point (default: {x: 50, y: 50})\n * @returns Point in SVG coordinates\n */\nexport function polarToCartesian(\n angle: number,\n radius: number,\n center: Point = { x: 50, y: 50 },\n): Point {\n return {\n x: center.x + Math.cos(angle) * radius,\n y: center.y + Math.sin(angle) * radius,\n };\n}\n\n/**\n * Convert SVG Cartesian coordinates to polar (angle in radians, radius)\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param center - Center point (default: {x: 50, y: 50})\n * @returns Angle in radians (0..2π) and radius\n */\nexport function cartesianToPolar(\n x: number,\n y: number,\n center: Point = { x: 50, y: 50 },\n): { angle: number; radius: number } {\n const dx = x - center.x;\n const dy = y - center.y;\n const radius = Math.sqrt(dx * dx + dy * dy);\n const raw = Math.atan2(dy, dx);\n const angle = ((raw % PI2) + PI2) % PI2; // Normalize to 0..2π\n return { angle, radius };\n}\n\n/**\n * Calculate start and end angles for a flattened circle\n * @param flatten - How much of the circle to hide (0..1): 0 = full circle, 0.5 = half circle, 1 = no arc\n * @returns Start and end angles in radians\n */\nexport function getFlattenedCircleAngles(flatten: number): {\n startAngle: number;\n endAngle: number;\n totalArc: number;\n} {\n // flatten represents the percentage of circle hidden\n // 0 = full circle (360°), 0.5 = half circle (180°), 1 = no arc (0°)\n const visibleArc = PI2 * (1 - flatten); // Total visible arc in radians\n\n // Center the visible arc at the top (angle = -π/2)\n // Start and end angles are symmetric around top-center\n const halfArc = visibleArc / 2;\n const topAngle = -Math.PI / 2; // Top center (270° in standard coords, but -90° from east)\n\n const startAngle = topAngle - halfArc;\n const endAngle = topAngle + halfArc;\n const totalArc = endAngle - startAngle;\n\n return { startAngle, endAngle, totalArc };\n}\n\n/**\n * Map a value (0..1) to an angle based on value mode\n * @param relativeValue - Value in 0..1 range\n * @param valueMode - How to interpret the value\n * @param flatten - Circle flattening amount (0..1)\n * @returns Angle in radians\n */\nexport function valueToAngle(\n relativeValue: number,\n valueMode: ValueMode,\n flatten: number,\n): number {\n const { startAngle, endAngle, totalArc } = getFlattenedCircleAngles(flatten);\n\n switch (valueMode) {\n case `range`:\n // Linear mapping from start to end\n return startAngle + relativeValue * totalArc;\n\n case `bipolar`: {\n // Midpoint is at top (MIDPOINT_ANGLE = -π/2)\n if (relativeValue <= 0.5) {\n // Map 0..0.5 to startAngle..MIDPOINT_ANGLE (going counterclockwise to top)\n const t = relativeValue / 0.5;\n return startAngle + t * (MIDPOINT_ANGLE - startAngle);\n } else {\n // Map 0.5..1 to MIDPOINT_ANGLE..endAngle (going clockwise from top)\n const t = (relativeValue - 0.5) / 0.5;\n return MIDPOINT_ANGLE + t * (endAngle - MIDPOINT_ANGLE);\n }\n }\n\n case `unipolar`: {\n // Marker stays at top for unipolar mode\n return MIDPOINT_ANGLE;\n }\n\n default:\n return startAngle;\n }\n}\n\n/**\n * Get start and end angles for a value arc\n * @param relativeValue - Value in 0..1 range\n * @param valueMode - How to interpret the value\n * @param flatten - Circle flattening amount (0..1)\n * @returns Start and end angles for the arc\n */\nexport function getValueArcAngles(\n relativeValue: number,\n valueMode: ValueMode,\n flatten: number,\n): { startAngle: number; endAngle: number } {\n const { startAngle, endAngle, totalArc } = getFlattenedCircleAngles(flatten);\n\n switch (valueMode) {\n case `range`:\n // Arc from start to value position\n return {\n startAngle,\n endAngle: startAngle + relativeValue * totalArc,\n };\n\n case `bipolar`: {\n // Midpoint is at top (MIDPOINT_ANGLE = -π/2)\n if (relativeValue < 0.5) {\n // Arc from some point toward top (going counterclockwise)\n const t = relativeValue / 0.5;\n const valueAngle = startAngle + t * (MIDPOINT_ANGLE - startAngle);\n return {\n startAngle: valueAngle,\n endAngle: MIDPOINT_ANGLE,\n };\n } else if (relativeValue > 0.5) {\n // Arc from top going clockwise\n const t = (relativeValue - 0.5) / 0.5;\n const valueAngle = MIDPOINT_ANGLE + t * (endAngle - MIDPOINT_ANGLE);\n return {\n startAngle: MIDPOINT_ANGLE,\n endAngle: valueAngle,\n };\n } else {\n // Exactly at midpoint, no arc\n return { startAngle: MIDPOINT_ANGLE, endAngle: MIDPOINT_ANGLE };\n }\n }\n\n case `unipolar`: {\n // Spread symmetrically from top (MIDPOINT_ANGLE = -π/2)\n const spreadAmount = relativeValue * totalArc / 2;\n return {\n startAngle: MIDPOINT_ANGLE - spreadAmount,\n endAngle: MIDPOINT_ANGLE + spreadAmount,\n };\n }\n\n default:\n return { startAngle, endAngle: startAngle };\n }\n}\n\n/**\n * Get start and end angles for an anchored arc\n * Centered on current value position, extends equally in both directions\n * @param relativeValue - Current value position (0..1)\n * @param laneValue - Width of the arc (0..1, where 1 = full range)\n * @param valueMode - How to interpret the value\n * @param flatten - Circle flattening amount (0..1)\n * @returns Start and end angles for the arc\n */\nexport function getAnchoredArcAngles(\n relativeValue: number,\n laneValue: number,\n valueMode: ValueMode,\n flatten: number,\n): { startAngle: number; endAngle: number } {\n const { startAngle, endAngle, totalArc } = getFlattenedCircleAngles(flatten);\n\n // Get the angle for the current value (this is the center of the arc)\n const centerAngle = valueToAngle(relativeValue, valueMode, flatten);\n\n // Calculate half-width of the arc\n // laneValue is 0..1, where 1 = full range\n const halfWidth = (laneValue * totalArc) / 2;\n\n let arcStart = centerAngle - halfWidth;\n let arcEnd = centerAngle + halfWidth;\n\n // Clamp to valid bounds (prevent wrapping)\n // The valid range is [startAngle, endAngle]\n if (arcStart < startAngle)\n arcStart = startAngle;\n if (arcEnd > endAngle)\n arcEnd = endAngle;\n\n // If the arc would be degenerate after clamping, return a single point\n if (arcStart >= arcEnd) {\n return { startAngle: centerAngle, endAngle: centerAngle };\n }\n\n return { startAngle: arcStart, endAngle: arcEnd };\n}\n\n/**\n * Generate SVG path for an arc\n * @param startAngle - Start angle in radians\n * @param endAngle - End angle in radians\n * @param radius - Arc radius\n * @param center - Center point\n * @returns SVG path data string\n */\nexport function generateArcPath(\n startAngle: number,\n endAngle: number,\n radius: number,\n center: Point = { x: 50, y: 50 },\n): string {\n if (startAngle === endAngle) {\n return ``; // No arc to draw\n }\n\n // Calculate arc length to determine large-arc-flag\n let arcLength = endAngle - startAngle;\n\n // Handle wrap-around case (e.g., from 5.5 to 0.5 radians)\n if (arcLength < 0) {\n arcLength += PI2;\n }\n\n // Handle full or near-full circle case\n // When arcLength is nearly 2π, start and end points are essentially the same\n // and drawing a full circle needs special handling\n if (arcLength >= PI2 - 0.001) {\n // Draw a full circle by going almost all the way around\n const adjustedEnd = startAngle + PI2 - 0.001;\n const start = polarToCartesian(startAngle, radius, center);\n const end = polarToCartesian(adjustedEnd, radius, center);\n return `M ${start.x},${start.y} A ${radius},${radius} 0 1 1 ${end.x},${end.y}`;\n }\n\n const start = polarToCartesian(startAngle, radius, center);\n const end = polarToCartesian(endAngle, radius, center);\n\n const largeArcFlag = arcLength > Math.PI ? 1 : 0;\n\n return `M ${start.x},${start.y} A ${radius},${radius} 0 ${largeArcFlag} 1 ${end.x},${end.y}`;\n}\n\n/**\n * Generate SVG path for a full flattened circle border\n * @param radius - Circle radius\n * @param flatten - Flattening amount (0..1)\n * @param center - Center point\n * @returns SVG path data string\n */\nexport function generateCircleBorderPath(\n radius: number,\n flatten: number,\n center: Point = { x: 50, y: 50 },\n): string {\n const { startAngle, endAngle } = getFlattenedCircleAngles(flatten);\n return generateArcPath(startAngle, endAngle, radius, center);\n}\n\n/**\n * Generate SVG path data for a filled wedge (pie-slice) sector\n * @param startAngle - Start angle in radians\n * @param endAngle - End angle in radians\n * @param radius - Wedge radius (same as dial radius)\n * @param center - Center point\n * @param clockwise - Whether to draw arc clockwise (true) or counterclockwise (false)\n * @returns SVG path data string for filled wedge\n */\nexport function generateWedgePath(\n startAngle: number,\n endAngle: number,\n radius: number,\n center: Point = { x: 50, y: 50 },\n clockwise: boolean = true,\n): string {\n if (startAngle === endAngle) {\n return ``; // No wedge to draw\n }\n\n // Calculate arc length (always positive, representing shortest path)\n let arcLength = endAngle - startAngle;\n if (arcLength < 0) {\n arcLength += PI2;\n }\n\n // Handle full or near-full circle case\n if (arcLength >= PI2 - 0.001) {\n // Draw a near-full circle wedge\n const start = polarToCartesian(startAngle, radius, center);\n const adjustedEnd = startAngle + PI2 - 0.001;\n const adjEnd = polarToCartesian(adjustedEnd, radius, center);\n const largeArcFlag = 1;\n const sweepFlag = clockwise ? 1 : 0;\n return `M ${center.x},${center.y} L ${start.x},${start.y} A ${radius},${radius} 0 ${largeArcFlag} ${sweepFlag} ${adjEnd.x},${adjEnd.y} Z`;\n }\n\n let actualStartAngle = startAngle;\n let actualEndAngle = endAngle;\n let actualClockwise = clockwise;\n\n // When going counterclockwise and arcLength > π, we want the short clockwise path instead\n // by swapping start and end\n if (!clockwise && arcLength > Math.PI) {\n actualStartAngle = endAngle;\n actualEndAngle = startAngle;\n actualClockwise = true;\n arcLength = PI2 - arcLength;\n }\n\n const start = polarToCartesian(actualStartAngle, radius, center);\n const end = polarToCartesian(actualEndAngle, radius, center);\n\n const largeArcFlag = arcLength > Math.PI ? 1 : 0;\n const sweepFlag = actualClockwise ? 1 : 0;\n\n // M center L start A radius radius 0 large sweep end Z\n return `M ${center.x},${center.y} L ${start.x},${start.y} A ${radius},${radius} 0 ${largeArcFlag} ${sweepFlag} ${end.x},${end.y} Z`;\n}\n\n/**\n * Get wedge angles based on value mode\n * @param relativeValue - Value in 0..1 range\n * @param valueMode - How to interpret the value\n * @param flatten - Circle flattening amount (0..1)\n * @returns Object with startAngle, endAngle, and clockwise flag\n */\nexport function getWedgeAngles(\n relativeValue: number,\n valueMode: ValueMode,\n flatten: number,\n): { startAngle: number; endAngle: number; clockwise: boolean } {\n const { startAngle, endAngle, totalArc } = getFlattenedCircleAngles(flatten);\n const valueAngle = valueToAngle(relativeValue, valueMode, flatten);\n\n switch (valueMode) {\n case `range`:\n // Wedge from startAngle to valueAngle (always clockwise)\n return {\n startAngle,\n endAngle: valueAngle,\n clockwise: true,\n };\n\n case `bipolar`: {\n // When value < 0.5, go counterclockwise from midpoint to value\n // When value >= 0.5, go clockwise from midpoint to value\n if (relativeValue < 0.5) {\n return {\n startAngle: MIDPOINT_ANGLE,\n endAngle: valueAngle,\n clockwise: false,\n };\n } else {\n return {\n startAngle: MIDPOINT_ANGLE,\n endAngle: valueAngle,\n clockwise: true,\n };\n }\n }\n\n case `unipolar`: {\n // Wedge centered at MIDPOINT, spreading value * totalArc/2 in each direction\n const halfSpread = relativeValue * totalArc / 2;\n return {\n startAngle: MIDPOINT_ANGLE - halfSpread,\n endAngle: MIDPOINT_ANGLE + halfSpread,\n clockwise: true,\n };\n }\n\n default:\n return { startAngle, endAngle: startAngle, clockwise: true };\n }\n}\n\n/**\n * Get position for a marker (needle or dot) at a given value\n * @param relativeValue - Value in 0..1 range\n * @param valueMode - How to interpret the value\n * @param flatten - Circle flattening amount (0..1)\n * @param radius - Circle radius\n * @param center - Center point\n * @returns Angle in radians and position point\n */\nexport function getMarkerPosition(\n relativeValue: number,\n valueMode: ValueMode,\n flatten: number,\n radius: number,\n center: Point = { x: 50, y: 50 },\n): { angle: number; position: Point } {\n const angle = valueToAngle(relativeValue, valueMode, flatten);\n const position = polarToCartesian(angle, radius, center);\n return { angle, position };\n}\n\n/**\n * Get position for midpoint marker (used in bipolar/unipolar modes)\n * @param radius - Circle radius\n * @param center - Center point\n * @returns Position at top-center of circle\n */\nexport function getMidpointPosition(\n radius: number,\n center: Point = { x: 50, y: 50 },\n): { angle: number; position: Point } {\n const position = polarToCartesian(MIDPOINT_ANGLE, radius, center);\n return { angle: MIDPOINT_ANGLE, position };\n}\n\n/**\n * Clamp a value between min and max\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Scale a value from one range to another\n */\nexport function scale(\n value: number,\n fromMin: number,\n fromMax: number,\n toMin: number,\n toMax: number,\n): number {\n const normalized = (value - fromMin) / (fromMax - fromMin);\n return toMin + normalized * (toMax - toMin);\n}\n","/**\n * Radial input component\n * A rotary dial input inspired by Ableton Live and music production software\n */\n\nimport type { PropertyValues } from 'lit';\nimport type {\n LaneData,\n LaneType,\n MarkerStyle,\n RadialInputChangeDetail,\n RadialInputInputDetail,\n ValueMode,\n} from './types.js';\nimport { css, html, LitElement, svg } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { KEY_STEP_DIVISOR, resolveStep } from '../keyboard.js';\nimport { prominenceStyles } from '../styles/prominence.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport {\n clamp,\n generateArcPath,\n generateCircleBorderPath,\n generateWedgePath,\n getAnchoredArcAngles,\n getMarkerPosition,\n getMidpointPosition,\n getValueArcAngles,\n getWedgeAngles,\n scale,\n} from './svg-utils.js';\n\nconst CENTER = { x: 50, y: 50 }; // Center point in viewBox\n\n@customElement(`ixfx-radial-input`)\nexport class RadialInputElement extends LitElement {\n // Internal backing field for radius (used with custom setter for clamping)\n #_radius = 45;\n\n // Radius property (controls dial size, 10-50 range to prevent clipping)\n @property({ type: Number })\n get radius(): number {\n return this.#_radius;\n }\n\n set radius(v: number) {\n this.#_radius = clamp(v, 10, 50);\n }\n\n // Value properties (matches ixfx-range API)\n @property({ type: Number })\n value = 0;\n\n @property({ type: Number })\n min = 0;\n\n @property({ type: Number })\n max = 100;\n\n @property({ type: Number })\n step: number | undefined = undefined;\n\n @property({ type: Number })\n stops?: number;\n\n // Value mode\n @property({ type: String, attribute: `value-mode` })\n valueMode: ValueMode = `range`;\n\n // Appearance\n @property({ type: Number })\n flatten = 0.3;\n\n @property({ type: String, attribute: `marker-style` })\n markerStyle: MarkerStyle = `needle`;\n\n @property({ type: Boolean })\n wedge = false;\n\n // Interaction\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n // Internal state\n #lanes: Map<string, LaneData> = new Map();\n #dragging = false;\n #dragStartY = 0;\n #valueAtDragStart = 0;\n #changeDebounceTimer: number | undefined;\n #isUserInteraction = false;\n\n constructor() {\n super();\n // Initialize default lanes\n // Note: value lane will be updated in willUpdate() to reflect initial value\n this.#lanes.set(`track`, {\n key: `track`,\n value: 1, // Full range\n type: `fixed`,\n offset: 0,\n width: 0.16,\n });\n this.#lanes.set(`value`, {\n key: `value`,\n value: 0, // Will be updated in willUpdate()\n type: `value`,\n offset: 0,\n width: 0.24,\n });\n }\n\n // Lane management API\n addLane(\n key: string,\n options?: {\n value?: number;\n type?: LaneType;\n offset?: number;\n width?: number;\n },\n ): void {\n const relativeValue = this.#getRelativeValue();\n this.#lanes.set(key, {\n key,\n value: options?.value ?? relativeValue,\n type: options?.type ?? `value`,\n offset: options?.offset ?? 0,\n width: options?.width ?? 0.1,\n });\n this.requestUpdate();\n }\n\n setLaneValue(key: string, value: number): void {\n const lane = this.#lanes.get(key);\n if (lane) {\n lane.value = clamp(value, 0, 1);\n this.requestUpdate();\n }\n }\n\n removeLane(key: string): void {\n this.#lanes.delete(key);\n this.requestUpdate();\n }\n\n getLanes(): ReadonlyMap<string, LaneData> {\n return new Map(this.#lanes);\n }\n\n getLane(key: string): LaneData | undefined {\n return this.#lanes.get(key);\n }\n\n // Internal helpers\n #getRelativeValue(): number {\n return scale(this.value, this.min, this.max, 0, 1);\n }\n\n #getEffectiveMarkerStyle(): MarkerStyle {\n if (this.valueMode === `unipolar` && this.markerStyle === `needle`) {\n return `none`;\n }\n return this.markerStyle;\n }\n\n #quantise(value: number): number {\n if (this.stops && this.stops > 1) {\n const range = this.max - this.min;\n const step = range / this.stops;\n return Math.round((value - this.min) / step) * step + this.min;\n }\n return value;\n }\n\n #setValueFromRelative(relativeValue: number, isUserInteraction = false): void {\n const newValue = scale(relativeValue, 0, 1, this.min, this.max);\n const clampedValue = this.#quantise(clamp(newValue, this.min, this.max));\n\n if (clampedValue === this.value)\n return;\n\n const previousValue = this.value;\n this.value = clampedValue;\n this.#isUserInteraction = isUserInteraction;\n\n // Update 'value' lane if it exists\n const valueLane = this.#lanes.get(`value`);\n if (valueLane && valueLane.type === `value`) {\n valueLane.value = this.#getRelativeValue();\n }\n\n // Update data-tooltip for live tooltips\n if (this.hasAttribute(`data-tooltip-live`)) {\n const percentage = Math.round(this.#getRelativeValue() * 100);\n this.setAttribute(`data-tooltip`, `${percentage}%`);\n }\n\n // Fire input event only for user interactions\n if (isUserInteraction) {\n this.dispatchEvent(\n new CustomEvent<RadialInputInputDetail>(`input`, {\n detail: {\n value: this.value,\n valueRelative: this.#getRelativeValue(),\n },\n bubbles: true,\n composed: true,\n }),\n );\n\n // Debounce change event\n this.#scheduleChangeEvent(previousValue);\n } else {\n // Immediate change event for programmatic changes\n this.#fireChangeEvent(previousValue);\n }\n }\n\n #scheduleChangeEvent(previousValue: number): void {\n if (this.#changeDebounceTimer !== undefined) {\n clearTimeout(this.#changeDebounceTimer);\n }\n\n this.#changeDebounceTimer = window.setTimeout(() => {\n this.#fireChangeEvent(previousValue);\n this.#changeDebounceTimer = undefined;\n }, 150);\n }\n\n #fireChangeEvent(previousValue: number): void {\n this.dispatchEvent(\n new CustomEvent<RadialInputChangeDetail>(`change`, {\n detail: {\n value: this.value,\n valueRelative: this.#getRelativeValue(),\n previousValue,\n },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n // Pointer interaction handlers\n #onPointerDown = (event: PointerEvent): void => {\n if (this.disabled)\n return;\n\n event.preventDefault();\n const svg = this.renderRoot.querySelector(`svg`);\n svg?.focus();\n this.#dragging = true;\n this.#dragStartY = event.clientY;\n this.#valueAtDragStart = this.value;\n this.toggleAttribute(`dragging`, true);\n\n if (svg) {\n svg.setPointerCapture(event.pointerId);\n }\n\n window.addEventListener(`pointermove`, this.#onPointerMove);\n window.addEventListener(`pointerup`, this.#onPointerUp);\n window.addEventListener(`pointercancel`, this.#onPointerUp);\n };\n\n #onPointerMove = (event: PointerEvent): void => {\n if (!this.#dragging)\n return;\n\n event.preventDefault();\n\n // Calculate sensitivity: full range = 2× component height\n const sensitivity = this.clientHeight * 2;\n const shiftDivisor = event.shiftKey ? KEY_STEP_DIVISOR : 1;\n const effectiveSensitivity = sensitivity * shiftDivisor;\n\n // Calculate delta (negative because up = increase)\n const deltaY = this.#dragStartY - event.clientY;\n const deltaValue = (deltaY / effectiveSensitivity) * (this.max - this.min);\n const newValue = this.#valueAtDragStart + deltaValue;\n\n const relativeValue = scale(newValue, this.min, this.max, 0, 1);\n this.#setValueFromRelative(clamp(relativeValue, 0, 1), true);\n };\n\n #onPointerUp = (): void => {\n this.#dragging = false;\n this.toggleAttribute(`dragging`, false);\n\n const svg = this.renderRoot.querySelector(`svg`);\n if (svg && `hasPointerCapture` in svg && typeof svg.hasPointerCapture === `function`) {\n if (svg.hasPointerCapture(1)) {\n svg.releasePointerCapture(1);\n }\n }\n\n window.removeEventListener(`pointermove`, this.#onPointerMove);\n window.removeEventListener(`pointerup`, this.#onPointerUp);\n window.removeEventListener(`pointercancel`, this.#onPointerUp);\n };\n\n // Keyboard interaction handler\n #onKeyDown = (event: KeyboardEvent): void => {\n if (this.disabled)\n return;\n\n const shiftDivisor = event.shiftKey ? KEY_STEP_DIVISOR : 1;\n const range = this.max - this.min;\n\n const effectiveStep = resolveStep(range, this.stops, this.step) / shiftDivisor;\n\n let handled = false;\n\n switch (event.key) {\n case `ArrowUp`:\n case `ArrowRight`:\n this.#setValueFromRelative(\n this.#getRelativeValue() + effectiveStep / range,\n true,\n );\n handled = true;\n break;\n\n case `ArrowDown`:\n case `ArrowLeft`:\n this.#setValueFromRelative(\n this.#getRelativeValue() - effectiveStep / range,\n true,\n );\n handled = true;\n break;\n\n case `Home`:\n this.#setValueFromRelative(0, true);\n handled = true;\n break;\n\n case `End`:\n this.#setValueFromRelative(1, true);\n handled = true;\n break;\n }\n\n if (handled) {\n event.preventDefault();\n }\n };\n\n // Rendering helpers\n #renderCircleBorder() {\n const path = generateCircleBorderPath(this.radius, this.flatten, CENTER);\n const borderWidth = this.#getCssVar(`--dial-border-width`, 2);\n const borderColor = getComputedStyle(this).getPropertyValue(`--dial-border-color`).trim() || `var(--surface-4)`;\n return svg`<path class=\"dial-border\" d=\"${path}\" fill=\"none\" stroke=\"${borderColor}\" stroke-width=\"${borderWidth}\" stroke-linecap=\"round\" vector-effect=\"non-scaling-stroke\" />`;\n }\n\n #renderCircleFill() {\n const path = generateCircleBorderPath(this.radius, this.flatten, CENTER);\n const fill = getComputedStyle(this).getPropertyValue(`--dial-fill`).trim() || `transparent`;\n return svg`<path class=\"dial-fill\" d=\"${path}\" fill=\"${fill}\" />`;\n }\n\n #renderWedge() {\n const relativeValue = this.#getRelativeValue();\n const { startAngle, endAngle, clockwise } = getWedgeAngles(\n relativeValue,\n this.valueMode,\n this.flatten,\n );\n\n const path = generateWedgePath(startAngle, endAngle, this.radius, CENTER, clockwise);\n if (!path)\n return svg``;\n\n return svg`<path class=\"wedge\" d=\"${path}\" />`;\n }\n\n #renderLane(lane: LaneData) {\n let arcPath = ``;\n\n if (lane.type === `fixed`) {\n // Fixed lanes always show full range\n arcPath = generateCircleBorderPath(\n this.radius - lane.offset * this.radius,\n this.flatten,\n CENTER,\n );\n } else if (lane.type === `anchored`) {\n // Anchored lanes: centered on current value, arc width based on lane.value\n const { startAngle, endAngle } = getAnchoredArcAngles(\n this.#getRelativeValue(),\n lane.value,\n this.valueMode,\n this.flatten,\n );\n arcPath = generateArcPath(\n startAngle,\n endAngle,\n this.radius - lane.offset * this.radius,\n CENTER,\n );\n } else {\n // Value lanes follow the value mode\n const { startAngle, endAngle } = getValueArcAngles(\n lane.value,\n this.valueMode,\n this.flatten,\n );\n arcPath = generateArcPath(\n startAngle,\n endAngle,\n this.radius - lane.offset * this.radius,\n CENTER,\n );\n }\n\n if (!arcPath)\n return svg``;\n\n return svg`\n <path \n class=\"lane\" \n data-lane-key=\"${lane.key}\" \n part=\"lane lane-${lane.key}\"\n d=\"${arcPath}\"\n style=\"\n stroke-width: calc(var(--lane-${lane.key}-width, var(--lane-width)) * ${this.radius}%);\n stroke-linecap: round;\n \"\n />\n `;\n }\n\n #getNeedlePath(angle: number, length: number, offset: number): string {\n const startRadius = offset * this.radius;\n const endRadius = length * this.radius;\n\n const start = {\n x: CENTER.x + Math.cos(angle) * startRadius,\n y: CENTER.y + Math.sin(angle) * startRadius,\n };\n const end = {\n x: CENTER.x + Math.cos(angle) * endRadius,\n y: CENTER.y + Math.sin(angle) * endRadius,\n };\n\n return `M ${start.x} ${start.y} L ${end.x} ${end.y}`;\n }\n\n #renderValueMarker(needlePath?: string) {\n const relativeValue = this.#getRelativeValue();\n const { angle, position } = getMarkerPosition(\n relativeValue,\n this.valueMode,\n this.flatten,\n this.radius,\n CENTER,\n );\n\n const markerOffset = this.#getCssVar(`--marker-offset`, 1);\n const markerBorderWidth = this.#getCssVar(`--marker-border-width`, 0);\n const effectiveStyle = this.#getEffectiveMarkerStyle();\n\n if (effectiveStyle === `dot`) {\n const size = this.#getCssVar(`--marker-thickness`, 0.15);\n const r = size * this.radius;\n const dotX = CENTER.x + (position.x - CENTER.x) * markerOffset;\n const dotY = CENTER.y + (position.y - CENTER.y) * markerOffset;\n\n if (markerBorderWidth > 0) {\n return svg`\n <g class=\"value-marker\" part=\"value-marker\">\n <use href=\"#dot-path\" class=\"marker-border\" />\n <use href=\"#dot-path\" class=\"marker-fill\" />\n </g>\n `;\n }\n\n return svg`\n <g class=\"value-marker\" part=\"value-marker\">\n <circle cx=\"${dotX}\" cy=\"${dotY}\" r=\"${r}\" />\n </g>\n `;\n } else if (effectiveStyle === `needle`) {\n if (markerBorderWidth > 0 && needlePath) {\n return svg`\n <g class=\"value-marker\" part=\"value-marker\">\n <use href=\"#needle-path\" class=\"marker-border\" />\n <use href=\"#needle-path\" class=\"marker-fill\" />\n </g>\n `;\n }\n\n const length = this.#getCssVar(`--marker-length`, 0.8);\n const offset = this.#getCssVar(`--marker-offset`, 0.2);\n const path = this.#getNeedlePath(angle, length, offset);\n\n return svg`\n <g class=\"value-marker\" part=\"value-marker\">\n <path d=\"${path}\" />\n </g>\n `;\n }\n }\n\n #renderMidpointMarker() {\n // Only show in bipolar/unipolar modes\n if (this.valueMode !== `bipolar` && this.valueMode !== `unipolar`) {\n return svg``;\n }\n\n const { position } = getMidpointPosition(this.radius, CENTER);\n\n if (this.markerStyle === `dot`) {\n const size = this.#getCssVar(`--midpoint-thickness`, 0.08);\n return svg`\n <g class=\"midpoint-marker\" part=\"midpoint-marker\">\n <circle \n cx=\"${position.x}\" \n cy=\"${position.y}\" \n r=\"${size * this.radius}\" \n />\n </g>\n `;\n } else {\n // Needle style\n const length = this.#getCssVar(`--midpoint-length`, 0.15);\n const offset = this.#getCssVar(`--midpoint-offset`, 0.85);\n\n const angle = -Math.PI / 2; // Top of circle\n const startRadius = offset * this.radius;\n const endRadius = (offset + length) * this.radius;\n\n const start = {\n x: CENTER.x + Math.cos(angle) * startRadius,\n y: CENTER.y + Math.sin(angle) * startRadius,\n };\n const end = {\n x: CENTER.x + Math.cos(angle) * endRadius,\n y: CENTER.y + Math.sin(angle) * endRadius,\n };\n\n return svg`\n <g class=\"midpoint-marker\" part=\"midpoint-marker\">\n <line \n x1=\"${start.x}\" \n y1=\"${start.y}\" \n x2=\"${end.x}\" \n y2=\"${end.y}\" \n />\n </g>\n `;\n }\n }\n\n #getCssVar(name: string, defaultValue: number): number {\n const style = getComputedStyle(this);\n const val = style.getPropertyValue(name).trim();\n if (!val)\n return defaultValue;\n\n // Handle CSS calc() expressions with var(--value-relative)\n if (val.includes(`calc(`)) {\n // Get the current --value-relative value\n const valueRelative = style.getPropertyValue(`--value-relative`).trim();\n if (!valueRelative) {\n // Fallback to default if --value-relative not set\n const parsed = Number.parseFloat(val.replace(/[^0-9.-]/g, ``));\n return Number.isNaN(parsed) ? defaultValue : parsed;\n }\n\n // Replace var(--value-relative) with the actual value\n const evalStr = val.replace(/var\\(--value-relative\\)/g, valueRelative);\n\n // Use Function constructor for safe evaluation (no eval)\n try {\n // Create a function that evaluates math expressions\n const fn = new Function(`return ${evalStr.replace(/calc\\s*\\(([^)]+)\\)/g, `$1`)}`);\n const result = fn();\n return typeof result === `number` && !Number.isNaN(result) ? result : defaultValue;\n } catch (e) {\n // Fallback: try to parse just numbers\n const parsed = Number.parseFloat(val.replace(/[^0-9.-]/g, ``));\n return Number.isNaN(parsed) ? defaultValue : parsed;\n }\n }\n\n const parsed = Number.parseFloat(val);\n return Number.isNaN(parsed) ? defaultValue : parsed;\n }\n\n // Lifecycle methods\n\n protected override willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n\n // Ensure value lane reflects current value before first render\n // This handles declaratively set initial values\n if (changed.has(`value`) || !this.hasUpdated) {\n const valueLane = this.#lanes.get(`value`);\n if (valueLane && valueLane.type === `value`) {\n valueLane.value = this.#getRelativeValue();\n }\n }\n }\n\n override render(): unknown {\n const lanes = Array.from(this.#lanes.values());\n\n const relativeValue = this.#getRelativeValue();\n const { angle, position } = getMarkerPosition(\n relativeValue,\n this.valueMode,\n this.flatten,\n this.radius,\n CENTER,\n );\n\n const needleLength = this.#getCssVar(`--marker-length`, 0.8);\n const needleOffset = this.#getCssVar(`--marker-offset`, 0.2);\n const markerBorderWidth = this.#getCssVar(`--marker-border-width`, 0);\n const needlePath = markerBorderWidth > 0 ? this.#getNeedlePath(angle, needleLength, needleOffset) : undefined;\n\n const dotSize = this.#getCssVar(`--marker-thickness`, 0.15);\n const dotR = dotSize * this.radius;\n\n const defs = [];\n if (needlePath) {\n defs.push(svg`<path id=\"needle-path\" d=\"${needlePath}\" />`);\n }\n if (markerBorderWidth > 0) {\n defs.push(svg`<circle id=\"dot-path\" cx=\"${position.x}\" cy=\"${position.y}\" r=\"${dotR}\" />`);\n }\n\n return html`\n <svg\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"xMidYMid meet\"\n tabindex=\"${this.disabled ? -1 : 0}\"\n @pointerdown=\"${this.#onPointerDown}\"\n @keydown=\"${this.#onKeyDown}\"\n style=\"cursor: ${this.#dragging ? `ns-resize` : `grab`}\"\n >\n ${defs.length > 0 ? svg`<defs>${defs}</defs>` : ``}\n ${this.#renderCircleFill()}\n ${this.wedge ? this.#renderWedge() : ``}\n ${this.#renderCircleBorder()}\n ${lanes.map(lane => this.#renderLane(lane))}\n ${this.#renderMidpointMarker()}\n ${this.#renderValueMarker(needlePath)}\n </svg>\n `;\n }\n\n protected override updated(changed: PropertyValues): void {\n super.updated(changed);\n\n // Update --radius CSS variable when property changes\n if (changed.has(`radius`)) {\n this.style.setProperty(`--radius`, `${this.radius}%`);\n }\n\n // Update --value-relative CSS variable\n this.style.setProperty(`--value-relative`, this.#getRelativeValue().toString());\n\n // Adjust component height based on flatten to reduce wasted vertical space.\n // The dial is flattened at the top, so we don't need full height.\n if (changed.has(`flatten`)) {\n const markerThickness = this.#getCssVar(`--marker-thickness`, 0.15);\n const radius = this.#getCssVar(`--radius`, 45);\n const markerPadding = Math.round(markerThickness * radius) + 5;\n const viewBoxHeight = Math.round(100 * (1 - this.flatten)) + markerPadding;\n // Set CSS variable to control host height\n this.style.setProperty(`--dial-height`, `${viewBoxHeight}px`);\n // Also update SVG viewBox to match\n const svg = this.renderRoot.querySelector(`svg`);\n if (svg) {\n svg.setAttribute(`viewBox`, `0 0 100 ${viewBoxHeight}`);\n }\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.#changeDebounceTimer !== undefined) {\n clearTimeout(this.#changeDebounceTimer);\n }\n this.#onPointerUp();\n }\n\n override firstUpdated(): void {\n const markerThickness = this.#getCssVar(`--marker-thickness`, 0.15);\n const radius = this.#getCssVar(`--radius`, 45);\n const markerPadding = Math.round(markerThickness * radius);\n const viewBoxHeight = Math.round(100 * (1 - this.flatten)) + markerPadding;\n this.style.setProperty(`--dial-height`, `${viewBoxHeight}px`);\n const svg = this.renderRoot.querySelector(`svg`);\n if (svg) {\n svg.setAttribute(`viewBox`, `0 0 100 ${viewBoxHeight}`);\n }\n }\n\n static override styles = [prominenceStyles, css`\n :host {\n display: inline-block;\n width: 100px;\n height: var(--dial-height, 100px);\n touch-action: none;\n user-select: none;\n tabindex: 0;\n\n /* Dynamic value - set by JS */\n --value-relative: 0;\n\n /* Lane widths (used in stroke-width calculations) */\n --lane-width: 0.16;\n --lane-track-width: 0.08;\n --lane-value-width: 0.12;\n }\n\n :host([disabled]) {\n cursor: not-allowed;\n }\n\n svg {\n width: 100%;\n height: 100%;\n outline: none;\n }\n\n svg:active {\n cursor: grabbing;\n }\n\n svg:focus-visible {\n outline: var(--radial-input-svg-focus-outline, 2px solid var(--accent));\n outline-offset: var(--radial-input-svg-focus-outline-offset, 2px);\n }\n\n .dial-border {\n fill: none;\n stroke: var(--dial-border-color, var(--surface-4));\n stroke-width: var(--dial-border-width, 2px);\n stroke-linecap: round;\n vector-effect: non-scaling-stroke;\n }\n\n .dial-fill {\n fill: var(--dial-fill, transparent);\n }\n\n .wedge {\n fill: var(--wedge-fill, var(--accent));\n fill-opacity: var(--wedge-fill-opacity, 0.25);\n stroke: var(--wedge-border-color, var(--accent));\n stroke-width: var(--wedge-border-width, 0);\n stroke-opacity: var(--wedge-border-opacity, 1);\n vector-effect: non-scaling-stroke;\n }\n\n .lane {\n fill: none;\n stroke-linecap: round;\n stroke-dasharray: var(--lane-dasharray, none);\n stroke-dashoffset: var(--lane-dashoffset, 0);\n vector-effect: non-scaling-stroke;\n }\n\n .lane[data-lane-key='track'] {\n stroke: var(--lane-track-color, var(--surface-4));\n }\n\n .lane[data-lane-key='value'] {\n stroke: var(--lane-value-color, var(--accent));\n }\n\n .lane:not([data-lane-key='track']):not([data-lane-key='value']) {\n stroke: var(--lane-color, var(--accent));\n }\n\n .value-marker path,\n .value-marker .marker-fill {\n stroke: var(--marker-color, var(--accent));\n stroke-width: calc(var(--marker-thickness, 0.15) * var(--radius, 45%));\n stroke-linecap: round;\n stroke-dasharray: var(--marker-dasharray, none);\n stroke-dashoffset: var(--marker-dashoffset, 0);\n vector-effect: non-scaling-stroke;\n }\n\n .value-marker .marker-border {\n stroke: var(--marker-border-color, transparent);\n stroke-width: calc((var(--marker-thickness, 0.15) + var(--marker-border-width, 0) * 2) * var(--radius, 45%));\n stroke-linecap: round;\n vector-effect: non-scaling-stroke;\n }\n\n .value-marker .marker-border {\n fill: none;\n }\n\n .value-marker .marker-fill,\n .value-marker circle {\n fill: var(--marker-color, var(--accent));\n }\n\n .midpoint-marker line {\n stroke: var(--midpoint-color, var(--surface-muted-text));\n stroke-width: var(--midpoint-thickness, 1px);\n stroke-linecap: round;\n vector-effect: non-scaling-stroke;\n }\n\n .midpoint-marker circle {\n fill: var(--midpoint-color, var(--surface-muted-text));\n stroke: var(--midpoint-border-color, transparent);\n stroke-width: var(--midpoint-border-width, 0);\n vector-effect: non-scaling-stroke;\n }\n `];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-radial-input': RadialInputElement;\n }\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { t as RadialInputElement } from "./radial-input-Dbc6fgCK.js";
1
+ import { t as RadialInputElement } from "./radial-input-DZA6WaFu.js";
2
2
  export { RadialInputElement };
@@ -1,4 +1,4 @@
1
- import { n as safeCustomElement, t as __decorate } from "./decorate-O4m1U4l3.js";
1
+ import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
2
2
  import { t as tooltipValueStyles } from "./tooltip-DMxmBNky.js";
3
3
  import { LitElement, css, html, nothing } from "lit";
4
4
  import { property, query } from "lit/decorators.js";
package/dist/range.js CHANGED
@@ -1,5 +1,5 @@
1
- import { n as safeCustomElement, t as __decorate } from "./decorate-O4m1U4l3.js";
2
- import { t as prominenceStyles } from "./prominence-CreDBdCs.js";
1
+ import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
2
+ import { t as prominenceStyles } from "./prominence--ic9uWBl.js";
3
3
  import { t as tooltipValueStyles } from "./tooltip-DMxmBNky.js";
4
4
  import { LitElement, css, html, nothing } from "lit";
5
5
  import { property } from "lit/decorators.js";
@@ -18,4 +18,4 @@ function svgToDataUri(svg) {
18
18
  //#endregion
19
19
  export { svgToDataUri as a, registerIcon as i, hasIcon as n, iconBus as r, getIcon as t };
20
20
 
21
- //# sourceMappingURL=registry-CZEB1YI9.js.map
21
+ //# sourceMappingURL=registry-Q2gYQCHM.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry-CZEB1YI9.js","names":[],"sources":["../src/icons/registry.ts"],"sourcesContent":["const _registry = new Map<string, string>();\n\nexport const iconBus = new EventTarget();\n\nexport type IconChangedDetail = { readonly name: string };\nexport type IconChangedEvent = CustomEvent<IconChangedDetail>;\n\nexport function registerIcon(name: string, svg: string): void {\n _registry.set(name, svg);\n iconBus.dispatchEvent(new CustomEvent<IconChangedDetail>(`ixfx-icon-change`, { detail: { name } }));\n}\n\nexport function getIcon(name: string): string | undefined {\n return _registry.get(name);\n}\n\nexport function hasIcon(name: string): boolean {\n return _registry.has(name);\n}\n\n/** Converts an SVG string to a CSS data-URI value, e.g. for use as a mask-image. */\nexport function svgToDataUri(svg: string): string {\n return `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`;\n}\n"],"mappings":";AAAA,MAAM,4BAAY,IAAI,IAAoB;AAE1C,MAAa,UAAU,IAAI,YAAY;AAKvC,SAAgB,aAAa,MAAc,KAAmB;CAC5D,UAAU,IAAI,MAAM,GAAG;CACvB,QAAQ,cAAc,IAAI,YAA+B,oBAAoB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;AACpG;AAEA,SAAgB,QAAQ,MAAkC;CACxD,OAAO,UAAU,IAAI,IAAI;AAC3B;AAEA,SAAgB,QAAQ,MAAuB;CAC7C,OAAO,UAAU,IAAI,IAAI;AAC3B;;AAGA,SAAgB,aAAa,KAAqB;CAChD,OAAO,2BAA2B,mBAAmB,GAAG,EAAE;AAC5D"}
1
+ {"version":3,"file":"registry-Q2gYQCHM.js","names":[],"sources":["../src/icons/registry.ts"],"sourcesContent":["const _registry = new Map<string, string>();\n\nexport const iconBus = new EventTarget();\n\nexport type IconChangedDetail = { readonly name: string };\nexport type IconChangedEvent = CustomEvent<IconChangedDetail>;\n\nexport function registerIcon(name: string, svg: string): void {\n _registry.set(name, svg);\n iconBus.dispatchEvent(new CustomEvent<IconChangedDetail>(`ixfx-icon-change`, { detail: { name } }));\n}\n\nexport function getIcon(name: string): string | undefined {\n return _registry.get(name);\n}\n\nexport function hasIcon(name: string): boolean {\n return _registry.has(name);\n}\n\n/** Converts an SVG string to a CSS data-URI value, e.g. for use as a mask-image. */\nexport function svgToDataUri(svg: string): string {\n return `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`;\n}\n"],"mappings":";AAAA,MAAM,4BAAY,IAAI,IAAoB;AAE1C,MAAa,UAAU,IAAI,YAAY;AAKvC,SAAgB,aAAa,MAAc,KAAmB;CAC5D,UAAU,IAAI,MAAM,GAAG;CACvB,QAAQ,cAAc,IAAI,YAA+B,oBAAoB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;AACpG;AAEA,SAAgB,QAAQ,MAAkC;CACxD,OAAO,UAAU,IAAI,IAAI;AAC3B;AAEA,SAAgB,QAAQ,MAAuB;CAC7C,OAAO,UAAU,IAAI,IAAI;AAC3B;;AAGA,SAAgB,aAAa,KAAqB;CAChD,OAAO,2BAA2B,mBAAmB,GAAG,EAAE;AAC5D"}
@@ -1,4 +1,4 @@
1
- import { n as safeCustomElement, t as __decorate } from "./decorate-O4m1U4l3.js";
1
+ import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
2
2
  import { LitElement, css, html } from "lit";
3
3
  import { property } from "lit/decorators.js";
4
4
  //#region src/selecthorizontal.ts
@@ -1,4 +1,4 @@
1
- import { n as safeCustomElement, t as __decorate } from "./decorate-O4m1U4l3.js";
1
+ import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
2
2
  import { LitElement, css, html } from "lit";
3
3
  import { property, state } from "lit/decorators.js";
4
4
  //#region src/snap-container/snap-container.ts
@@ -1,5 +1,5 @@
1
- import { n as safeCustomElement, t as __decorate } from "./decorate-O4m1U4l3.js";
2
- import { t as clamp } from "./dist-D7kJgnSE.js";
1
+ import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
2
+ import { t as clamp } from "./dist-TAGYwaju.js";
3
3
  import { LitElement, css, html } from "lit";
4
4
  import { property, state } from "lit/decorators.js";
5
5
  //#region src/split-layout/split-layout.ts
@@ -173,7 +173,7 @@ let SplitLayoutElement = class SplitLayoutElement extends LitElement {
173
173
  const cursorZoneLocalY = event.clientY - zoneBounds.top;
174
174
  if (this.layout === `vertical` && nestedSplit.layout === `horizontal`) {
175
175
  let newOuterFraction = cursorZoneLocalX / outerBounds.width;
176
- let newNestedFraction = cursorZoneLocalY / outerBounds.height;
176
+ const newNestedFraction = cursorZoneLocalY / outerBounds.height;
177
177
  const { sizeA: constrainedA, sizeB: constrainedB } = this.#applyConstraints(`${newOuterFraction * 100}%`, `${(1 - newOuterFraction) * 100}%`, outerBounds.width);
178
178
  newOuterFraction = this.#parseSizeAsFraction(constrainedA, outerBounds.width);
179
179
  this.sizeA = constrainedA;
@@ -189,7 +189,7 @@ let SplitLayoutElement = class SplitLayoutElement extends LitElement {
189
189
  cornerZone.style.top = `${cursorZoneLocalY - 6}px`;
190
190
  }
191
191
  } else if (this.layout === `horizontal` && nestedSplit.layout === `vertical`) {
192
- let newNestedFraction = cursorZoneLocalX / outerBounds.width;
192
+ const newNestedFraction = cursorZoneLocalX / outerBounds.width;
193
193
  let newOuterFraction = cursorZoneLocalY / outerBounds.height;
194
194
  const { sizeA: constrainedA, sizeB: constrainedB } = this.#applyConstraints(`${newOuterFraction * 100}%`, `${(1 - newOuterFraction) * 100}%`, outerBounds.height);
195
195
  newOuterFraction = this.#parseSizeAsFraction(constrainedA, outerBounds.height);
@@ -1 +1 @@
1
- {"version":3,"file":"split-layout.js","names":["#elementBounds","#startSizeA","#startSizeB","#onResizeHandleUp","#onResizeHandleMove","#collapsedAPointerAtCollapse","#hysteresisThreshold","#dispatchCollapsedEvent","#applyConstraints","#collapsedBPointerAtCollapse","#cornerStartX","#cornerStartY","#getNestedSplit","#nestedSplitInitialSizeA","#nestedSplitBounds","#nestedHandleBounds","#onCornerResizeUp","#onCornerResizeMove","#parseSizeAsFraction","#pendingNestedUpdate","#applyPendingNestedUpdate","#observer","#setupNestedSplitObserver","#updateCornerPosition","#updateDataCollapsed","#checkForNestedSplit","#nestedSplit","#minSizeToFraction","#maxSizeToFraction","#parseSizeToPx","#getIntersectionPoint","#onCornerResizeDown","#onResizeHandleDown","customElement"],"sources":["../src/split-layout/split-layout.ts"],"sourcesContent":["import { clamp } from \"@ixfx/numbers\";\nimport { css, html, LitElement } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\nimport { safeCustomElement as customElement } from \"../util/custom-elements.js\";\n\n// TODO: Fire event when panels have been resized\n/**\n * Lays out two elements within a container, with a bar to resize them\n * proportionally.\n *\n * Events\n * ixfx-split-collapsed: Dispatched when a panel is collapsed/uncollapsed via drag.\n * detail: { panel: 'A' | 'B', collapsed: boolean }\n *\n * Attributes\n * layout: `vertical`|`horizontal`\n * sizeA/B: CSS size of section A or B. Can use relative or absolute values\n * fixedA/B: If _true_ size will be calculated in pixels. By default (_false_) it uses % of whole\n * collapsible: If _true_, panels can be collapsed by dragging to edge (default: false)\n * minSizeA/B: Minimum size for panel A or B (e.g., \"100px\" or \"20%\"). Default: none\n * maxSizeA/B: Maximum size for panel A or B (e.g., \"200px\" or \"80%\"). Default: none\n *\n * CSS variables\n * --handle-size: 2px; // Width/height of resize handle\n * --handle-colour: var(--surface-5); // Colour of handle\n * --handle-hover-colour: var(--surface-6); // Colour of handle when hovering\n * --handle-active-colour: var(--accent); // Colour of handle when being used\n */\n@customElement(`ixfx-split-layout`)\nexport class SplitLayoutElement extends LitElement {\n @property({ type: String })\n layout: `vertical` | `horizontal` = `vertical`;\n\n @property({ type: String })\n sizeA = ``;\n\n @property({ type: String })\n sizeB = ``;\n\n @property({ type: Boolean })\n fixedA = false;\n\n @property({ type: Boolean })\n fixedB = false;\n\n @property({ type: Boolean })\n collapsible = false;\n\n @property({ type: Boolean, reflect: true })\n collapsedA = false;\n\n @property({ type: Boolean, reflect: true })\n collapsedB = false;\n\n @property({ type: String })\n minSizeA = ``;\n\n @property({ type: String })\n maxSizeA = ``;\n\n @property({ type: String })\n minSizeB = ``;\n\n @property({ type: String })\n maxSizeB = ``;\n\n @state()\n private _hasCorner = false;\n\n #elementBounds: DOMRect | undefined;\n #startSizeA = ``;\n #startSizeB = ``;\n #cornerStartX = 0;\n #cornerStartY = 0;\n #nestedSplitInitialSizeA = ``;\n\n #cornerZone: HTMLElement | undefined;\n #nestedSplit: SplitLayoutElement | undefined;\n #nestedSplitBounds: DOMRect | undefined;\n #nestedHandleBounds: DOMRect | undefined;\n #observer: MutationObserver | undefined;\n #pendingNestedUpdate: { sizeA: number; sizeB: number } | null = null;\n #collapsedAPointerAtCollapse: number | undefined;\n #collapsedBPointerAtCollapse: number | undefined;\n #hysteresisThreshold = 0.1;\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.#observer?.disconnect();\n }\n\n firstUpdated() {\n this.#setupNestedSplitObserver();\n }\n\n updated(changedProperties: Map<string, unknown>) {\n if (changedProperties.has(`sizeA`) || changedProperties.has(`sizeB`)\n || changedProperties.has(`collapsedA`) || changedProperties.has(`collapsedB`)) {\n this.#updateCornerPosition();\n }\n if (changedProperties.has(`sizeA`) || changedProperties.has(`sizeB`)) {\n this.#updateDataCollapsed();\n }\n }\n\n #updateDataCollapsed() {\n if (this.collapsedA) {\n this.setAttribute(`data-collapsed-a`, ``);\n } else {\n this.removeAttribute(`data-collapsed-a`);\n }\n if (this.collapsedB) {\n this.setAttribute(`data-collapsed-b`, ``);\n } else {\n this.removeAttribute(`data-collapsed-b`);\n }\n }\n\n #dispatchCollapsedEvent(panel: `A` | `B`, collapsed: boolean) {\n this.dispatchEvent(new CustomEvent(`ixfx-split-collapsed`, {\n detail: { panel, collapsed },\n bubbles: true,\n composed: true,\n }));\n }\n\n #setupNestedSplitObserver() {\n const slotA = this.shadowRoot?.querySelector(`slot[name=\"a\"]`) as HTMLSlotElement | undefined;\n if (!slotA)\n return;\n\n this.#observer = new MutationObserver(() => {\n this.#checkForNestedSplit();\n });\n\n this.#observer.observe(slotA, { characterData: true, childList: true, subtree: true });\n this.#checkForNestedSplit();\n }\n\n #checkForNestedSplit() {\n const slotA = this.shadowRoot?.querySelector(`slot[name=\"a\"]`) as HTMLSlotElement | undefined;\n if (!slotA)\n return;\n\n const assignedElements = slotA.assignedElements();\n\n const findNestedSplit = (elements: Element[]): SplitLayoutElement | undefined => {\n for (const el of elements) {\n if (el.tagName === `IXFX-SPLIT-LAYOUT`) {\n return el as SplitLayoutElement;\n }\n const nested = findNestedSplit(Array.from(el.children));\n if (nested)\n return nested;\n }\n return undefined;\n };\n\n const nestedSplit = findNestedSplit(assignedElements);\n\n if (nestedSplit) {\n this.#nestedSplit = nestedSplit;\n this._hasCorner = true;\n requestAnimationFrame(() => this.#updateCornerPosition());\n } else {\n this.#nestedSplit = undefined;\n this._hasCorner = false;\n }\n }\n\n #getNestedSplit(): SplitLayoutElement | undefined {\n if (this.#nestedSplit)\n return this.#nestedSplit;\n\n const slotA = this.shadowRoot?.querySelector(`slot[name=\"a\"]`) as HTMLSlotElement | undefined;\n if (!slotA)\n return undefined;\n const assignedElements = slotA.assignedElements();\n return assignedElements.find(\n el => el.tagName === `IXFX-SPLIT-LAYOUT`,\n ) as SplitLayoutElement | undefined;\n }\n\n #parseSizeAsFraction(size: string, total: number): number {\n if (size.endsWith(`px`)) {\n return Number.parseFloat(size.replace(`px`, ``)) / total;\n } else if (size.endsWith(`%`)) {\n return Number.parseFloat(size.replace(`%`, ``)) / 100;\n }\n return 0.5;\n }\n\n #parseSizeToPx(size: string, total: number): number | null {\n if (size.endsWith(`px`)) {\n return Number.parseFloat(size.replace(`px`, ``));\n } else if (size.endsWith(`%`)) {\n return (Number.parseFloat(size.replace(`%`, ``)) / 100) * total;\n }\n return null;\n }\n\n #applyConstraints(sizeA: string, sizeB: string, total: number): { sizeA: string; sizeB: string } {\n let fractionA = this.#parseSizeAsFraction(sizeA, total);\n let fractionB = this.#parseSizeAsFraction(sizeB, total);\n\n const minA = this.#minSizeToFraction(this.minSizeA, total);\n const minB = this.#minSizeToFraction(this.minSizeB, total);\n const maxA = this.#maxSizeToFraction(this.maxSizeA, total);\n const maxB = this.#maxSizeToFraction(this.maxSizeB, total);\n\n if (minA !== null || minB !== null) {\n const minSum = (minA ?? 0) + (minB ?? 0);\n if (minSum > 1) {\n const scale = 1 / minSum;\n if (minA !== null)\n minA !== null ? fractionA = minA * scale : fractionA = 0;\n if (minB !== null)\n minB !== null ? fractionB = minB * scale : fractionB = 0;\n }\n\n if (fractionA < (minA ?? 0))\n fractionA = minA ?? 0;\n if (fractionB < (minB ?? 0))\n fractionB = minB ?? 0;\n }\n\n if (maxA !== null) {\n if (fractionA > maxA)\n fractionA = maxA;\n }\n if (maxB !== null) {\n if (fractionB > maxB)\n fractionB = maxB;\n }\n\n fractionB = 1 - fractionA;\n\n const isPercentA = !this.sizeA.endsWith(`px`);\n const isPercentB = !this.sizeB.endsWith(`px`);\n\n if (isPercentA) {\n return { sizeA: `${fractionA * 100}%`, sizeB: `${fractionB * 100}%` };\n } else {\n return { sizeA: `${fractionA * total}px`, sizeB: `${fractionB * total}px` };\n }\n }\n\n #minSizeToFraction(minSize: string, total: number): number | null {\n if (minSize.length === 0)\n return null;\n const px = this.#parseSizeToPx(minSize, total);\n if (px !== null)\n return px / total;\n if (minSize.endsWith(`%`))\n return Number.parseFloat(minSize.replace(`%`, ``)) / 100;\n return null;\n }\n\n #maxSizeToFraction(maxSize: string, total: number): number | null {\n if (maxSize.length === 0)\n return null;\n const px = this.#parseSizeToPx(maxSize, total);\n if (px !== null)\n return px / total;\n if (maxSize.endsWith(`%`))\n return Number.parseFloat(maxSize.replace(`%`, ``)) / 100;\n return null;\n }\n\n #getIntersectionPoint(): { x: number; y: number } | null {\n const outerBounds = this.getBoundingClientRect();\n const zoneEl = this.getZone();\n if (!zoneEl)\n return null;\n\n const nestedSplit = this.#getNestedSplit();\n if (!nestedSplit)\n return null;\n\n const zoneBounds = zoneEl.getBoundingClientRect();\n\n const outerFraction = this.#parseSizeAsFraction(this.sizeA || `50%`, outerBounds.width);\n\n let x: number, y: number;\n\n if (this.layout === `vertical` && nestedSplit.layout === `horizontal`) {\n x = outerFraction * outerBounds.width;\n const nestedFraction = this.#parseSizeAsFraction(nestedSplit.sizeA || `50%`, outerBounds.height);\n y = nestedFraction * outerBounds.height;\n } else if (this.layout === `horizontal` && nestedSplit.layout === `vertical`) {\n const nestedFraction = this.#parseSizeAsFraction(nestedSplit.sizeA || `50%`, outerBounds.width);\n x = nestedFraction * outerBounds.width;\n y = outerFraction * outerBounds.height;\n } else {\n return null;\n }\n\n return { x, y };\n }\n\n #updateCornerPosition() {\n if (!this._hasCorner)\n return;\n\n const cornerZone = this.shadowRoot?.querySelector(`.corner-zone`) as HTMLElement | undefined;\n if (!cornerZone)\n return;\n\n const zoneEl = this.getZone();\n if (!zoneEl)\n return;\n\n const intersection = this.#getIntersectionPoint();\n if (!intersection) {\n cornerZone.style.display = `none`;\n return;\n }\n\n const cornerX = intersection.x - 6;\n const cornerY = intersection.y - 6;\n\n cornerZone.style.left = `${cornerX}px`;\n cornerZone.style.top = `${cornerY}px`;\n cornerZone.style.display = `block`;\n\n const nestedSplit = this.#getNestedSplit();\n if (nestedSplit) {\n if (this.layout === `vertical` && nestedSplit.layout === `horizontal`) {\n cornerZone.style.cursor = `nwse-resize`;\n } else if (this.layout === `horizontal` && nestedSplit.layout === `vertical`) {\n cornerZone.style.cursor = `nesw-resize`;\n }\n }\n }\n\n getZone(): HTMLElement | undefined {\n if (!this.shadowRoot)\n return;\n const el = this.shadowRoot.querySelector(`#zone`);\n if (!el)\n return undefined;\n return el as HTMLElement;\n }\n\n #onResizeHandleDown = (event: PointerEvent) => {\n event.preventDefault();\n const zoneEl = this.getZone();\n if (zoneEl) {\n zoneEl.classList.add(`user-resizing`);\n }\n this.#elementBounds = this.getBoundingClientRect();\n this.#startSizeA = this.sizeA;\n this.#startSizeB = this.sizeB;\n window.addEventListener(`pointerup`, this.#onResizeHandleUp);\n window.addEventListener(`pointermove`, this.#onResizeHandleMove);\n };\n\n #onResizeHandleUp = (event: PointerEvent) => {\n event.preventDefault();\n const zoneEl = this.getZone();\n if (zoneEl) {\n zoneEl.classList.remove(`user-resizing`);\n }\n window.removeEventListener(`pointerup`, this.#onResizeHandleUp);\n window.removeEventListener(`pointermove`, this.#onResizeHandleMove);\n };\n\n #onResizeHandleMove = (event: PointerEvent) => {\n const bounds = this.#elementBounds;\n if (!bounds)\n return;\n\n const threshold = 5;\n\n if (this.layout === `horizontal`) {\n const y = event.y - bounds.y;\n const relativeY = clamp(y / bounds.height);\n\n if (this.collapsible && this.collapsedA) {\n if (relativeY > (this.#collapsedAPointerAtCollapse ?? 0.05) + this.#hysteresisThreshold) {\n this.collapsedA = false;\n this.#dispatchCollapsedEvent(`A`, false);\n this.#collapsedAPointerAtCollapse = undefined;\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeY * 100}%`,\n `${(1 - relativeY) * 100}%`,\n bounds.height,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n } else if (this.collapsible && !this.collapsedA && relativeY < threshold / bounds.height) {\n this.collapsedA = true;\n this.#dispatchCollapsedEvent(`A`, true);\n this.sizeA = `0px`;\n this.sizeB = `100%`;\n this.#collapsedAPointerAtCollapse = relativeY;\n } else if (!this.collapsedA) {\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeY * 100}%`,\n `${(1 - relativeY) * 100}%`,\n bounds.height,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n\n if (this.collapsible && this.collapsedB) {\n if (relativeY < (this.#collapsedBPointerAtCollapse ?? 0.95) - this.#hysteresisThreshold) {\n this.collapsedB = false;\n this.#dispatchCollapsedEvent(`B`, false);\n this.#collapsedBPointerAtCollapse = undefined;\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeY * 100}%`,\n `${(1 - relativeY) * 100}%`,\n bounds.height,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n } else if (this.collapsible && !this.collapsedB && relativeY > (1 - threshold / bounds.height)) {\n this.collapsedB = true;\n this.#dispatchCollapsedEvent(`B`, true);\n this.sizeA = `100%`;\n this.sizeB = `0px`;\n this.#collapsedBPointerAtCollapse = relativeY;\n }\n } else {\n const x = event.x - bounds.x;\n const relativeX = clamp(x / bounds.width);\n\n if (this.collapsible && this.collapsedA) {\n if (relativeX > (this.#collapsedAPointerAtCollapse ?? 0.05) + this.#hysteresisThreshold) {\n this.collapsedA = false;\n this.#dispatchCollapsedEvent(`A`, false);\n this.#collapsedAPointerAtCollapse = undefined;\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeX * 100}%`,\n `${(1 - relativeX) * 100}%`,\n bounds.width,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n } else if (this.collapsible && !this.collapsedA && relativeX < threshold / bounds.width) {\n this.collapsedA = true;\n this.#dispatchCollapsedEvent(`A`, true);\n this.sizeA = `0px`;\n this.sizeB = `100%`;\n this.#collapsedAPointerAtCollapse = relativeX;\n } else if (!this.collapsedA) {\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeX * 100}%`,\n `${(1 - relativeX) * 100}%`,\n bounds.width,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n\n if (this.collapsible && this.collapsedB) {\n if (relativeX < (this.#collapsedBPointerAtCollapse ?? 0.95) - this.#hysteresisThreshold) {\n this.collapsedB = false;\n this.#dispatchCollapsedEvent(`B`, false);\n this.#collapsedBPointerAtCollapse = undefined;\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeX * 100}%`,\n `${(1 - relativeX) * 100}%`,\n bounds.width,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n } else if (this.collapsible && !this.collapsedB && relativeX > (1 - threshold / bounds.width)) {\n this.collapsedB = true;\n this.#dispatchCollapsedEvent(`B`, true);\n this.sizeA = `100%`;\n this.sizeB = `0px`;\n this.#collapsedBPointerAtCollapse = relativeX;\n }\n }\n event.preventDefault();\n };\n\n #onCornerResizeDown = (event: PointerEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n const zoneEl = this.getZone();\n if (zoneEl) {\n zoneEl.classList.add(`user-resizing`);\n }\n\n this.#elementBounds = this.getBoundingClientRect();\n this.#cornerStartX = event.clientX;\n this.#cornerStartY = event.clientY;\n this.#startSizeA = this.sizeA;\n this.#startSizeB = this.sizeB;\n\n const nestedSplit = this.#getNestedSplit();\n if (nestedSplit) {\n this.#nestedSplitInitialSizeA = nestedSplit.sizeA;\n const nestedBounds = nestedSplit.getBoundingClientRect();\n const nestedHandle = nestedSplit.shadowRoot?.querySelector(`.resize-handle`) as HTMLElement;\n if (nestedHandle) {\n this.#nestedSplitBounds = nestedBounds;\n this.#nestedHandleBounds = nestedHandle.getBoundingClientRect();\n }\n const nestedZoneEl = nestedSplit.getZone();\n if (nestedZoneEl) {\n nestedZoneEl.classList.add(`user-resizing`);\n }\n }\n\n window.addEventListener(`pointerup`, this.#onCornerResizeUp);\n window.addEventListener(`pointermove`, this.#onCornerResizeMove);\n };\n\n #onCornerResizeUp = (event: PointerEvent) => {\n event.preventDefault();\n const zoneEl = this.getZone();\n if (zoneEl) {\n zoneEl.classList.remove(`user-resizing`);\n }\n const nestedSplit = this.#getNestedSplit();\n if (nestedSplit) {\n const nestedZoneEl = nestedSplit.getZone();\n if (nestedZoneEl) {\n nestedZoneEl.classList.remove(`user-resizing`);\n }\n }\n window.removeEventListener(`pointerup`, this.#onCornerResizeUp);\n window.removeEventListener(`pointermove`, this.#onCornerResizeMove);\n };\n\n #applyPendingNestedUpdate() {\n if (!this.#pendingNestedUpdate)\n return;\n const { sizeA, sizeB } = this.#pendingNestedUpdate;\n const nested = this.#getNestedSplit();\n if (nested) {\n nested.sizeA = `${sizeA * 100}%`;\n nested.sizeB = `${sizeB * 100}%`;\n }\n this.#pendingNestedUpdate = null;\n }\n\n #onCornerResizeMove = (event: PointerEvent) => {\n const outerBounds = this.#elementBounds;\n const zoneEl = this.getZone();\n const nestedSplit = this.#getNestedSplit();\n if (!outerBounds || !zoneEl || !nestedSplit)\n return;\n\n const zoneBounds = zoneEl.getBoundingClientRect();\n const cursorZoneLocalX = event.clientX - zoneBounds.left;\n const cursorZoneLocalY = event.clientY - zoneBounds.top;\n\n if (this.layout === `vertical` && nestedSplit.layout === `horizontal`) {\n let newOuterFraction = cursorZoneLocalX / outerBounds.width;\n let newNestedFraction = cursorZoneLocalY / outerBounds.height;\n\n const { sizeA: constrainedA, sizeB: constrainedB } = this.#applyConstraints(\n `${newOuterFraction * 100}%`,\n `${(1 - newOuterFraction) * 100}%`,\n outerBounds.width,\n );\n newOuterFraction = this.#parseSizeAsFraction(constrainedA, outerBounds.width);\n\n this.sizeA = constrainedA;\n this.sizeB = constrainedB;\n\n this.#pendingNestedUpdate = {\n sizeA: newNestedFraction,\n sizeB: 1 - newNestedFraction,\n };\n requestAnimationFrame(() => this.#applyPendingNestedUpdate());\n\n const cornerZone = this.shadowRoot?.querySelector(`.corner-zone`) as HTMLElement | undefined;\n if (cornerZone) {\n cornerZone.style.left = `${cursorZoneLocalX - 6}px`;\n cornerZone.style.top = `${cursorZoneLocalY - 6}px`;\n }\n } else if (this.layout === `horizontal` && nestedSplit.layout === `vertical`) {\n let newNestedFraction = cursorZoneLocalX / outerBounds.width;\n let newOuterFraction = cursorZoneLocalY / outerBounds.height;\n\n const { sizeA: constrainedA, sizeB: constrainedB } = this.#applyConstraints(\n `${newOuterFraction * 100}%`,\n `${(1 - newOuterFraction) * 100}%`,\n outerBounds.height,\n );\n newOuterFraction = this.#parseSizeAsFraction(constrainedA, outerBounds.height);\n\n this.sizeA = constrainedA;\n this.sizeB = constrainedB;\n\n this.#pendingNestedUpdate = {\n sizeA: newNestedFraction,\n sizeB: 1 - newNestedFraction,\n };\n requestAnimationFrame(() => this.#applyPendingNestedUpdate());\n\n const cornerZone = this.shadowRoot?.querySelector(`.corner-zone`) as HTMLElement | undefined;\n if (cornerZone) {\n cornerZone.style.left = `${cursorZoneLocalX - 6}px`;\n cornerZone.style.top = `${cursorZoneLocalY - 6}px`;\n }\n }\n\n event.preventDefault();\n };\n\n render() {\n const sizePrefix = this.layout === `vertical` ? `width` : `height`;\n let sizeA = this.sizeA;\n let sizeB = this.sizeB;\n\n if (this.collapsedA) {\n sizeA = `0px`;\n } else if (sizeA.length === 0 && sizeB.length === 0) {\n sizeB = sizeA = `50%`;\n } else if (sizeA.length === 0) {\n sizeA = `auto`;\n } else if (sizeB.length === 0) {\n sizeB = `auto`;\n }\n\n if (this.collapsedB) {\n sizeB = `0px`;\n }\n\n sizeA = `${sizePrefix}:${sizeA}`;\n sizeB = `${sizePrefix}:${sizeB}`;\n\n return html`\n <div id=\"zone\">\n <slot style=${sizeA} name=\"a\"></slot>\n ${this._hasCorner ? html`<div class=\"corner-zone\" @pointerdown=${this.#onCornerResizeDown}></div>` : ``}\n <div @pointerdown=${this.#onResizeHandleDown} class=\"resize-handle\"></div>\n <slot style=${sizeB} name=\"b\"></slot> \n </div>`;\n }\n\n static styles = css`\n :host {\n --handle-size: 2px;\n --handle-colour: var(--surface-5);\n --handle-hover-colour: var(--surface-6);\n --handle-active-colour: var(--accent);\n\n display: block;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n }\n * {\n box-sizing: border-box;\n }\n #zone {\n display: flex;\n height: 100%;\n position: relative;\n }\n slot {\n display: block;\n overflow: hidden;\n }\n :slotted(*) {\n width: 100%;\n height: 100%;\n }\n\n .resize-handle {\n background-color: var(--handle-colour);\n width: var(--handle-size);\n height: 100%;\n cursor: ew-resize;\n flex-shrink: 0;\n }\n #zone.user-resizing {\n slot {\n opacity: 0.5;\n }\n .resize-handle {\n background-color: var(--handle-active-colour);\n }\n }\n .resize-handle:hover {\n background-color: var(--handle-hover-colour);\n }\n\n .corner-zone {\n position: absolute;\n width: 12px;\n height: 12px;\n z-index: 10;\n border-radius: 50%;\n background: transparent;\n }\n .corner-zone:hover {\n background: transparent;\n }\n\n :host([layout='horizontal']) {\n #zone {\n flex-direction: column;\n }\n .resize-handle {\n background-color: silver;\n height: var(--handle-size);\n width: 100%;\n cursor: ns-resize;\n }\n .resize-handle:hover {\n background-color: var(--handle-hover-colour);\n }\n #zone.user-resizing .resize-handle {\n background-color: var(--handle-active-colour);\n }\n }\n\n :host([data-collapsed-a]) slot[name=\"a\"],\n :host([data-collapsed-b]) slot[name=\"b\"] {\n display: none;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ixfx-split-layout\": SplitLayoutElement;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"split-layout.js","names":["#elementBounds","#startSizeA","#startSizeB","#onResizeHandleUp","#onResizeHandleMove","#collapsedAPointerAtCollapse","#hysteresisThreshold","#dispatchCollapsedEvent","#applyConstraints","#collapsedBPointerAtCollapse","#cornerStartX","#cornerStartY","#getNestedSplit","#nestedSplitInitialSizeA","#nestedSplitBounds","#nestedHandleBounds","#onCornerResizeUp","#onCornerResizeMove","#parseSizeAsFraction","#pendingNestedUpdate","#applyPendingNestedUpdate","#observer","#setupNestedSplitObserver","#updateCornerPosition","#updateDataCollapsed","#checkForNestedSplit","#nestedSplit","#minSizeToFraction","#maxSizeToFraction","#parseSizeToPx","#getIntersectionPoint","#onCornerResizeDown","#onResizeHandleDown","customElement"],"sources":["../src/split-layout/split-layout.ts"],"sourcesContent":["import { clamp } from \"@ixfx/numbers\";\nimport { css, html, LitElement } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\nimport { safeCustomElement as customElement } from \"../util/custom-elements.js\";\n\n// TODO: Fire event when panels have been resized\n/**\n * Lays out two elements within a container, with a bar to resize them\n * proportionally.\n *\n * Events\n * ixfx-split-collapsed: Dispatched when a panel is collapsed/uncollapsed via drag.\n * detail: { panel: 'A' | 'B', collapsed: boolean }\n *\n * Attributes\n * layout: `vertical`|`horizontal`\n * sizeA/B: CSS size of section A or B. Can use relative or absolute values\n * fixedA/B: If _true_ size will be calculated in pixels. By default (_false_) it uses % of whole\n * collapsible: If _true_, panels can be collapsed by dragging to edge (default: false)\n * minSizeA/B: Minimum size for panel A or B (e.g., \"100px\" or \"20%\"). Default: none\n * maxSizeA/B: Maximum size for panel A or B (e.g., \"200px\" or \"80%\"). Default: none\n *\n * CSS variables\n * --handle-size: 2px; // Width/height of resize handle\n * --handle-colour: var(--surface-5); // Colour of handle\n * --handle-hover-colour: var(--surface-6); // Colour of handle when hovering\n * --handle-active-colour: var(--accent); // Colour of handle when being used\n */\n@customElement(`ixfx-split-layout`)\nexport class SplitLayoutElement extends LitElement {\n @property({ type: String })\n layout: `vertical` | `horizontal` = `vertical`;\n\n @property({ type: String })\n sizeA = ``;\n\n @property({ type: String })\n sizeB = ``;\n\n @property({ type: Boolean })\n fixedA = false;\n\n @property({ type: Boolean })\n fixedB = false;\n\n @property({ type: Boolean })\n collapsible = false;\n\n @property({ type: Boolean, reflect: true })\n collapsedA = false;\n\n @property({ type: Boolean, reflect: true })\n collapsedB = false;\n\n @property({ type: String })\n minSizeA = ``;\n\n @property({ type: String })\n maxSizeA = ``;\n\n @property({ type: String })\n minSizeB = ``;\n\n @property({ type: String })\n maxSizeB = ``;\n\n @state()\n private _hasCorner = false;\n\n #elementBounds: DOMRect | undefined;\n #startSizeA = ``;\n #startSizeB = ``;\n #cornerStartX = 0;\n #cornerStartY = 0;\n #nestedSplitInitialSizeA = ``;\n\n #cornerZone: HTMLElement | undefined;\n #nestedSplit: SplitLayoutElement | undefined;\n #nestedSplitBounds: DOMRect | undefined;\n #nestedHandleBounds: DOMRect | undefined;\n #observer: MutationObserver | undefined;\n #pendingNestedUpdate: { sizeA: number; sizeB: number } | null = null;\n #collapsedAPointerAtCollapse: number | undefined;\n #collapsedBPointerAtCollapse: number | undefined;\n #hysteresisThreshold = 0.1;\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.#observer?.disconnect();\n }\n\n firstUpdated() {\n this.#setupNestedSplitObserver();\n }\n\n updated(changedProperties: Map<string, unknown>) {\n if (changedProperties.has(`sizeA`) || changedProperties.has(`sizeB`)\n || changedProperties.has(`collapsedA`) || changedProperties.has(`collapsedB`)) {\n this.#updateCornerPosition();\n }\n if (changedProperties.has(`sizeA`) || changedProperties.has(`sizeB`)) {\n this.#updateDataCollapsed();\n }\n }\n\n #updateDataCollapsed() {\n if (this.collapsedA) {\n this.setAttribute(`data-collapsed-a`, ``);\n } else {\n this.removeAttribute(`data-collapsed-a`);\n }\n if (this.collapsedB) {\n this.setAttribute(`data-collapsed-b`, ``);\n } else {\n this.removeAttribute(`data-collapsed-b`);\n }\n }\n\n #dispatchCollapsedEvent(panel: `A` | `B`, collapsed: boolean) {\n this.dispatchEvent(new CustomEvent(`ixfx-split-collapsed`, {\n detail: { panel, collapsed },\n bubbles: true,\n composed: true,\n }));\n }\n\n #setupNestedSplitObserver() {\n const slotA = this.shadowRoot?.querySelector(`slot[name=\"a\"]`) as HTMLSlotElement | undefined;\n if (!slotA)\n return;\n\n this.#observer = new MutationObserver(() => {\n this.#checkForNestedSplit();\n });\n\n this.#observer.observe(slotA, { characterData: true, childList: true, subtree: true });\n this.#checkForNestedSplit();\n }\n\n #checkForNestedSplit() {\n const slotA = this.shadowRoot?.querySelector(`slot[name=\"a\"]`) as HTMLSlotElement | undefined;\n if (!slotA)\n return;\n\n const assignedElements = slotA.assignedElements();\n\n const findNestedSplit = (elements: Element[]): SplitLayoutElement | undefined => {\n for (const el of elements) {\n if (el.tagName === `IXFX-SPLIT-LAYOUT`) {\n return el as SplitLayoutElement;\n }\n const nested = findNestedSplit(Array.from(el.children));\n if (nested)\n return nested;\n }\n return undefined;\n };\n\n const nestedSplit = findNestedSplit(assignedElements);\n\n if (nestedSplit) {\n this.#nestedSplit = nestedSplit;\n this._hasCorner = true;\n requestAnimationFrame(() => this.#updateCornerPosition());\n } else {\n this.#nestedSplit = undefined;\n this._hasCorner = false;\n }\n }\n\n #getNestedSplit(): SplitLayoutElement | undefined {\n if (this.#nestedSplit)\n return this.#nestedSplit;\n\n const slotA = this.shadowRoot?.querySelector(`slot[name=\"a\"]`) as HTMLSlotElement | undefined;\n if (!slotA)\n return undefined;\n const assignedElements = slotA.assignedElements();\n return assignedElements.find(\n el => el.tagName === `IXFX-SPLIT-LAYOUT`,\n ) as SplitLayoutElement | undefined;\n }\n\n #parseSizeAsFraction(size: string, total: number): number {\n if (size.endsWith(`px`)) {\n return Number.parseFloat(size.replace(`px`, ``)) / total;\n } else if (size.endsWith(`%`)) {\n return Number.parseFloat(size.replace(`%`, ``)) / 100;\n }\n return 0.5;\n }\n\n #parseSizeToPx(size: string, total: number): number | null {\n if (size.endsWith(`px`)) {\n return Number.parseFloat(size.replace(`px`, ``));\n } else if (size.endsWith(`%`)) {\n return (Number.parseFloat(size.replace(`%`, ``)) / 100) * total;\n }\n return null;\n }\n\n #applyConstraints(sizeA: string, sizeB: string, total: number): { sizeA: string; sizeB: string } {\n let fractionA = this.#parseSizeAsFraction(sizeA, total);\n let fractionB = this.#parseSizeAsFraction(sizeB, total);\n\n const minA = this.#minSizeToFraction(this.minSizeA, total);\n const minB = this.#minSizeToFraction(this.minSizeB, total);\n const maxA = this.#maxSizeToFraction(this.maxSizeA, total);\n const maxB = this.#maxSizeToFraction(this.maxSizeB, total);\n\n if (minA !== null || minB !== null) {\n const minSum = (minA ?? 0) + (minB ?? 0);\n if (minSum > 1) {\n const scale = 1 / minSum;\n if (minA !== null)\n minA !== null ? fractionA = minA * scale : fractionA = 0;\n if (minB !== null)\n minB !== null ? fractionB = minB * scale : fractionB = 0;\n }\n\n if (fractionA < (minA ?? 0))\n fractionA = minA ?? 0;\n if (fractionB < (minB ?? 0))\n fractionB = minB ?? 0;\n }\n\n if (maxA !== null) {\n if (fractionA > maxA)\n fractionA = maxA;\n }\n if (maxB !== null) {\n if (fractionB > maxB)\n fractionB = maxB;\n }\n\n fractionB = 1 - fractionA;\n\n const isPercentA = !this.sizeA.endsWith(`px`);\n const isPercentB = !this.sizeB.endsWith(`px`);\n\n if (isPercentA) {\n return { sizeA: `${fractionA * 100}%`, sizeB: `${fractionB * 100}%` };\n } else {\n return { sizeA: `${fractionA * total}px`, sizeB: `${fractionB * total}px` };\n }\n }\n\n #minSizeToFraction(minSize: string, total: number): number | null {\n if (minSize.length === 0)\n return null;\n const px = this.#parseSizeToPx(minSize, total);\n if (px !== null)\n return px / total;\n if (minSize.endsWith(`%`))\n return Number.parseFloat(minSize.replace(`%`, ``)) / 100;\n return null;\n }\n\n #maxSizeToFraction(maxSize: string, total: number): number | null {\n if (maxSize.length === 0)\n return null;\n const px = this.#parseSizeToPx(maxSize, total);\n if (px !== null)\n return px / total;\n if (maxSize.endsWith(`%`))\n return Number.parseFloat(maxSize.replace(`%`, ``)) / 100;\n return null;\n }\n\n #getIntersectionPoint(): { x: number; y: number } | null {\n const outerBounds = this.getBoundingClientRect();\n const zoneEl = this.getZone();\n if (!zoneEl)\n return null;\n\n const nestedSplit = this.#getNestedSplit();\n if (!nestedSplit)\n return null;\n\n const zoneBounds = zoneEl.getBoundingClientRect();\n\n const outerFraction = this.#parseSizeAsFraction(this.sizeA || `50%`, outerBounds.width);\n\n let x: number, y: number;\n\n if (this.layout === `vertical` && nestedSplit.layout === `horizontal`) {\n x = outerFraction * outerBounds.width;\n const nestedFraction = this.#parseSizeAsFraction(nestedSplit.sizeA || `50%`, outerBounds.height);\n y = nestedFraction * outerBounds.height;\n } else if (this.layout === `horizontal` && nestedSplit.layout === `vertical`) {\n const nestedFraction = this.#parseSizeAsFraction(nestedSplit.sizeA || `50%`, outerBounds.width);\n x = nestedFraction * outerBounds.width;\n y = outerFraction * outerBounds.height;\n } else {\n return null;\n }\n\n return { x, y };\n }\n\n #updateCornerPosition() {\n if (!this._hasCorner)\n return;\n\n const cornerZone = this.shadowRoot?.querySelector(`.corner-zone`) as HTMLElement | undefined;\n if (!cornerZone)\n return;\n\n const zoneEl = this.getZone();\n if (!zoneEl)\n return;\n\n const intersection = this.#getIntersectionPoint();\n if (!intersection) {\n cornerZone.style.display = `none`;\n return;\n }\n\n const cornerX = intersection.x - 6;\n const cornerY = intersection.y - 6;\n\n cornerZone.style.left = `${cornerX}px`;\n cornerZone.style.top = `${cornerY}px`;\n cornerZone.style.display = `block`;\n\n const nestedSplit = this.#getNestedSplit();\n if (nestedSplit) {\n if (this.layout === `vertical` && nestedSplit.layout === `horizontal`) {\n cornerZone.style.cursor = `nwse-resize`;\n } else if (this.layout === `horizontal` && nestedSplit.layout === `vertical`) {\n cornerZone.style.cursor = `nesw-resize`;\n }\n }\n }\n\n getZone(): HTMLElement | undefined {\n if (!this.shadowRoot)\n return;\n const el = this.shadowRoot.querySelector(`#zone`);\n if (!el)\n return undefined;\n return el as HTMLElement;\n }\n\n #onResizeHandleDown = (event: PointerEvent) => {\n event.preventDefault();\n const zoneEl = this.getZone();\n if (zoneEl) {\n zoneEl.classList.add(`user-resizing`);\n }\n this.#elementBounds = this.getBoundingClientRect();\n this.#startSizeA = this.sizeA;\n this.#startSizeB = this.sizeB;\n window.addEventListener(`pointerup`, this.#onResizeHandleUp);\n window.addEventListener(`pointermove`, this.#onResizeHandleMove);\n };\n\n #onResizeHandleUp = (event: PointerEvent) => {\n event.preventDefault();\n const zoneEl = this.getZone();\n if (zoneEl) {\n zoneEl.classList.remove(`user-resizing`);\n }\n window.removeEventListener(`pointerup`, this.#onResizeHandleUp);\n window.removeEventListener(`pointermove`, this.#onResizeHandleMove);\n };\n\n #onResizeHandleMove = (event: PointerEvent) => {\n const bounds = this.#elementBounds;\n if (!bounds)\n return;\n\n const threshold = 5;\n\n if (this.layout === `horizontal`) {\n const y = event.y - bounds.y;\n const relativeY = clamp(y / bounds.height);\n\n if (this.collapsible && this.collapsedA) {\n if (relativeY > (this.#collapsedAPointerAtCollapse ?? 0.05) + this.#hysteresisThreshold) {\n this.collapsedA = false;\n this.#dispatchCollapsedEvent(`A`, false);\n this.#collapsedAPointerAtCollapse = undefined;\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeY * 100}%`,\n `${(1 - relativeY) * 100}%`,\n bounds.height,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n } else if (this.collapsible && !this.collapsedA && relativeY < threshold / bounds.height) {\n this.collapsedA = true;\n this.#dispatchCollapsedEvent(`A`, true);\n this.sizeA = `0px`;\n this.sizeB = `100%`;\n this.#collapsedAPointerAtCollapse = relativeY;\n } else if (!this.collapsedA) {\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeY * 100}%`,\n `${(1 - relativeY) * 100}%`,\n bounds.height,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n\n if (this.collapsible && this.collapsedB) {\n if (relativeY < (this.#collapsedBPointerAtCollapse ?? 0.95) - this.#hysteresisThreshold) {\n this.collapsedB = false;\n this.#dispatchCollapsedEvent(`B`, false);\n this.#collapsedBPointerAtCollapse = undefined;\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeY * 100}%`,\n `${(1 - relativeY) * 100}%`,\n bounds.height,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n } else if (this.collapsible && !this.collapsedB && relativeY > (1 - threshold / bounds.height)) {\n this.collapsedB = true;\n this.#dispatchCollapsedEvent(`B`, true);\n this.sizeA = `100%`;\n this.sizeB = `0px`;\n this.#collapsedBPointerAtCollapse = relativeY;\n }\n } else {\n const x = event.x - bounds.x;\n const relativeX = clamp(x / bounds.width);\n\n if (this.collapsible && this.collapsedA) {\n if (relativeX > (this.#collapsedAPointerAtCollapse ?? 0.05) + this.#hysteresisThreshold) {\n this.collapsedA = false;\n this.#dispatchCollapsedEvent(`A`, false);\n this.#collapsedAPointerAtCollapse = undefined;\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeX * 100}%`,\n `${(1 - relativeX) * 100}%`,\n bounds.width,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n } else if (this.collapsible && !this.collapsedA && relativeX < threshold / bounds.width) {\n this.collapsedA = true;\n this.#dispatchCollapsedEvent(`A`, true);\n this.sizeA = `0px`;\n this.sizeB = `100%`;\n this.#collapsedAPointerAtCollapse = relativeX;\n } else if (!this.collapsedA) {\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeX * 100}%`,\n `${(1 - relativeX) * 100}%`,\n bounds.width,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n\n if (this.collapsible && this.collapsedB) {\n if (relativeX < (this.#collapsedBPointerAtCollapse ?? 0.95) - this.#hysteresisThreshold) {\n this.collapsedB = false;\n this.#dispatchCollapsedEvent(`B`, false);\n this.#collapsedBPointerAtCollapse = undefined;\n const { sizeA, sizeB } = this.#applyConstraints(\n `${relativeX * 100}%`,\n `${(1 - relativeX) * 100}%`,\n bounds.width,\n );\n this.sizeA = sizeA;\n this.sizeB = sizeB;\n }\n } else if (this.collapsible && !this.collapsedB && relativeX > (1 - threshold / bounds.width)) {\n this.collapsedB = true;\n this.#dispatchCollapsedEvent(`B`, true);\n this.sizeA = `100%`;\n this.sizeB = `0px`;\n this.#collapsedBPointerAtCollapse = relativeX;\n }\n }\n event.preventDefault();\n };\n\n #onCornerResizeDown = (event: PointerEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n const zoneEl = this.getZone();\n if (zoneEl) {\n zoneEl.classList.add(`user-resizing`);\n }\n\n this.#elementBounds = this.getBoundingClientRect();\n this.#cornerStartX = event.clientX;\n this.#cornerStartY = event.clientY;\n this.#startSizeA = this.sizeA;\n this.#startSizeB = this.sizeB;\n\n const nestedSplit = this.#getNestedSplit();\n if (nestedSplit) {\n this.#nestedSplitInitialSizeA = nestedSplit.sizeA;\n const nestedBounds = nestedSplit.getBoundingClientRect();\n const nestedHandle = nestedSplit.shadowRoot?.querySelector(`.resize-handle`) as HTMLElement;\n if (nestedHandle) {\n this.#nestedSplitBounds = nestedBounds;\n this.#nestedHandleBounds = nestedHandle.getBoundingClientRect();\n }\n const nestedZoneEl = nestedSplit.getZone();\n if (nestedZoneEl) {\n nestedZoneEl.classList.add(`user-resizing`);\n }\n }\n\n window.addEventListener(`pointerup`, this.#onCornerResizeUp);\n window.addEventListener(`pointermove`, this.#onCornerResizeMove);\n };\n\n #onCornerResizeUp = (event: PointerEvent) => {\n event.preventDefault();\n const zoneEl = this.getZone();\n if (zoneEl) {\n zoneEl.classList.remove(`user-resizing`);\n }\n const nestedSplit = this.#getNestedSplit();\n if (nestedSplit) {\n const nestedZoneEl = nestedSplit.getZone();\n if (nestedZoneEl) {\n nestedZoneEl.classList.remove(`user-resizing`);\n }\n }\n window.removeEventListener(`pointerup`, this.#onCornerResizeUp);\n window.removeEventListener(`pointermove`, this.#onCornerResizeMove);\n };\n\n #applyPendingNestedUpdate() {\n if (!this.#pendingNestedUpdate)\n return;\n const { sizeA, sizeB } = this.#pendingNestedUpdate;\n const nested = this.#getNestedSplit();\n if (nested) {\n nested.sizeA = `${sizeA * 100}%`;\n nested.sizeB = `${sizeB * 100}%`;\n }\n this.#pendingNestedUpdate = null;\n }\n\n #onCornerResizeMove = (event: PointerEvent) => {\n const outerBounds = this.#elementBounds;\n const zoneEl = this.getZone();\n const nestedSplit = this.#getNestedSplit();\n if (!outerBounds || !zoneEl || !nestedSplit)\n return;\n\n const zoneBounds = zoneEl.getBoundingClientRect();\n const cursorZoneLocalX = event.clientX - zoneBounds.left;\n const cursorZoneLocalY = event.clientY - zoneBounds.top;\n\n if (this.layout === `vertical` && nestedSplit.layout === `horizontal`) {\n let newOuterFraction = cursorZoneLocalX / outerBounds.width;\n const newNestedFraction = cursorZoneLocalY / outerBounds.height;\n\n const { sizeA: constrainedA, sizeB: constrainedB } = this.#applyConstraints(\n `${newOuterFraction * 100}%`,\n `${(1 - newOuterFraction) * 100}%`,\n outerBounds.width,\n );\n newOuterFraction = this.#parseSizeAsFraction(constrainedA, outerBounds.width);\n\n this.sizeA = constrainedA;\n this.sizeB = constrainedB;\n\n this.#pendingNestedUpdate = {\n sizeA: newNestedFraction,\n sizeB: 1 - newNestedFraction,\n };\n requestAnimationFrame(() => this.#applyPendingNestedUpdate());\n\n const cornerZone = this.shadowRoot?.querySelector(`.corner-zone`) as HTMLElement | undefined;\n if (cornerZone) {\n cornerZone.style.left = `${cursorZoneLocalX - 6}px`;\n cornerZone.style.top = `${cursorZoneLocalY - 6}px`;\n }\n } else if (this.layout === `horizontal` && nestedSplit.layout === `vertical`) {\n const newNestedFraction = cursorZoneLocalX / outerBounds.width;\n let newOuterFraction = cursorZoneLocalY / outerBounds.height;\n\n const { sizeA: constrainedA, sizeB: constrainedB } = this.#applyConstraints(\n `${newOuterFraction * 100}%`,\n `${(1 - newOuterFraction) * 100}%`,\n outerBounds.height,\n );\n newOuterFraction = this.#parseSizeAsFraction(constrainedA, outerBounds.height);\n\n this.sizeA = constrainedA;\n this.sizeB = constrainedB;\n\n this.#pendingNestedUpdate = {\n sizeA: newNestedFraction,\n sizeB: 1 - newNestedFraction,\n };\n requestAnimationFrame(() => this.#applyPendingNestedUpdate());\n\n const cornerZone = this.shadowRoot?.querySelector(`.corner-zone`) as HTMLElement | undefined;\n if (cornerZone) {\n cornerZone.style.left = `${cursorZoneLocalX - 6}px`;\n cornerZone.style.top = `${cursorZoneLocalY - 6}px`;\n }\n }\n\n event.preventDefault();\n };\n\n render() {\n const sizePrefix = this.layout === `vertical` ? `width` : `height`;\n let sizeA = this.sizeA;\n let sizeB = this.sizeB;\n\n if (this.collapsedA) {\n sizeA = `0px`;\n } else if (sizeA.length === 0 && sizeB.length === 0) {\n sizeB = sizeA = `50%`;\n } else if (sizeA.length === 0) {\n sizeA = `auto`;\n } else if (sizeB.length === 0) {\n sizeB = `auto`;\n }\n\n if (this.collapsedB) {\n sizeB = `0px`;\n }\n\n sizeA = `${sizePrefix}:${sizeA}`;\n sizeB = `${sizePrefix}:${sizeB}`;\n\n return html`\n <div id=\"zone\">\n <slot style=${sizeA} name=\"a\"></slot>\n ${this._hasCorner ? html`<div class=\"corner-zone\" @pointerdown=${this.#onCornerResizeDown}></div>` : ``}\n <div @pointerdown=${this.#onResizeHandleDown} class=\"resize-handle\"></div>\n <slot style=${sizeB} name=\"b\"></slot> \n </div>`;\n }\n\n static styles = css`\n :host {\n --handle-size: 2px;\n --handle-colour: var(--surface-5);\n --handle-hover-colour: var(--surface-6);\n --handle-active-colour: var(--accent);\n\n display: block;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n }\n * {\n box-sizing: border-box;\n }\n #zone {\n display: flex;\n height: 100%;\n position: relative;\n }\n slot {\n display: block;\n overflow: hidden;\n }\n :slotted(*) {\n width: 100%;\n height: 100%;\n }\n\n .resize-handle {\n background-color: var(--handle-colour);\n width: var(--handle-size);\n height: 100%;\n cursor: ew-resize;\n flex-shrink: 0;\n }\n #zone.user-resizing {\n slot {\n opacity: 0.5;\n }\n .resize-handle {\n background-color: var(--handle-active-colour);\n }\n }\n .resize-handle:hover {\n background-color: var(--handle-hover-colour);\n }\n\n .corner-zone {\n position: absolute;\n width: 12px;\n height: 12px;\n z-index: 10;\n border-radius: 50%;\n background: transparent;\n }\n .corner-zone:hover {\n background: transparent;\n }\n\n :host([layout='horizontal']) {\n #zone {\n flex-direction: column;\n }\n .resize-handle {\n background-color: silver;\n height: var(--handle-size);\n width: 100%;\n cursor: ns-resize;\n }\n .resize-handle:hover {\n background-color: var(--handle-hover-colour);\n }\n #zone.user-resizing .resize-handle {\n background-color: var(--handle-active-colour);\n }\n }\n\n :host([data-collapsed-a]) slot[name=\"a\"],\n :host([data-collapsed-b]) slot[name=\"b\"] {\n display: none;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ixfx-split-layout\": SplitLayoutElement;\n }\n}\n"],"mappings":"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"}
package/dist/swipe.d.ts CHANGED
@@ -9,8 +9,7 @@ interface SwipeElementEventMap {
9
9
  input: SwipeInputEvent;
10
10
  }
11
11
  interface SwipeElement {
12
- addEventListener<K extends keyof SwipeElementEventMap>(type: K, listener: (this: SwipeElement, event: SwipeElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions): void;
13
- addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
12
+ addEventListener: (<K extends keyof SwipeElementEventMap>(type: K, listener: (this: SwipeElement, event: SwipeElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions) => void) & ((type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions) => void);
14
13
  }
15
14
  declare global {
16
15
  interface HTMLElementTagNameMap {
@@ -1 +1 @@
1
- {"version":3,"file":"swipe.d.ts","names":[],"sources":["../src/swipe/swipe.ts"],"mappings":";;;KA0BY,gBAAA;EAAA,SAA8B,KAAK;AAAA;AAAA,KACnC,eAAA,GAAkB,WAAW,CAAC,gBAAA;AAAA,UAEzB,oBAAA;EACf,KAAA,EAAO,eAAe;AAAA;AAAA,UAGP,YAAA;EACf,gBAAA,iBAAiC,oBAAA,EAC/B,IAAA,EAAM,CAAA,EACN,QAAA,GAAW,IAAA,EAAM,YAAA,EAAc,KAAA,EAAO,oBAAA,CAAqB,CAAA,YAC3D,OAAA,aAAoB,uBAAA;EAEtB,gBAAA,CACE,IAAA,UACA,QAAA,EAAU,kCAAA,EACV,OAAA,aAAoB,uBAAA;AAAA;AAAA,QAIhB,MAAA;EAAA,UACI,qBAAA;IACR,YAAA,EAAc,YAAY;EAAA;AAAA;AAAA,cAKjB,YAAA,SAAqB,UAAA;EAAA;EACJ,UAAA;EACA,QAAA;EACA,UAAA;EACA,iBAAA;EAAA,QAEpB,OAAA;EAAA,QACA,SAAA;EAAA,QACA,UAAA;EAAA,QACA,eAAA;EAAA,QACA,WAAA;EAAA,QAEA,OAAA;EAAA,QACA,MAAA;EAAA,QACA,OAAA;EAAA,QAEA,UAAA;EAAA,QACA,cAAA;EAAA,QACA,gBAAA;EAAA,QACA,cAAA;EAAA,QACA,eAAA;EAyCC,iBAAA,CAAA;EAaA,oBAAA,CAAA;EAAA,QAUD,cAAA;EAAA,QAcA,cAAA;EAAA,OAoFQ,MAAA,EAAQ,cAAA;EA8Bf,MAAA,CAAA,GAAU,UAAA,QAAkB,IAAA;AAAA"}
1
+ {"version":3,"file":"swipe.d.ts","names":[],"sources":["../src/swipe/swipe.ts"],"mappings":";;;KA0BY,gBAAA;EAAA,SAA8B,KAAK;AAAA;AAAA,KACnC,eAAA,GAAkB,WAAW,CAAC,gBAAA;AAAA,UAEzB,oBAAA;EACf,KAAA,EAAO,eAAe;AAAA;AAAA,UAGP,YAAA;EACf,gBAAA,oBAAoC,oBAAA,EAClC,IAAA,EAAM,CAAA,EACN,QAAA,GAAW,IAAA,EAAM,YAAA,EAAc,KAAA,EAAO,oBAAA,CAAqB,CAAA,YAC3D,OAAA,aAAoB,uBAAA,eAEpB,IAAA,UACA,QAAA,EAAU,kCAAA,EACV,OAAA,aAAoB,uBAAA;AAAA;AAAA,QAIhB,MAAA;EAAA,UACI,qBAAA;IACR,YAAA,EAAc,YAAY;EAAA;AAAA;AAAA,cAKjB,YAAA,SAAqB,UAAA;EAAA;EACJ,UAAA;EACA,QAAA;EACA,UAAA;EACA,iBAAA;EAAA,QAEpB,OAAA;EAAA,QACA,SAAA;EAAA,QACA,UAAA;EAAA,QACA,eAAA;EAAA,QACA,WAAA;EAAA,QAEA,OAAA;EAAA,QACA,MAAA;EAAA,QACA,OAAA;EAAA,QAEA,UAAA;EAAA,QACA,cAAA;EAAA,QACA,gBAAA;EAAA,QACA,cAAA;EAAA,QACA,eAAA;EAyCC,iBAAA,CAAA;EAaA,oBAAA,CAAA;EAAA,QAUD,cAAA;EAAA,QAcA,cAAA;EAAA,OAoFQ,MAAA,EAAQ,cAAA;EA8Bf,MAAA,CAAA,GAAU,UAAA,QAAkB,IAAA;AAAA"}
package/dist/swipe.js CHANGED
@@ -1,5 +1,5 @@
1
- import { n as safeCustomElement, t as __decorate } from "./decorate-O4m1U4l3.js";
2
- import { t as prominenceStyles } from "./prominence-CreDBdCs.js";
1
+ import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
2
+ import { t as prominenceStyles } from "./prominence--ic9uWBl.js";
3
3
  import { LitElement, css, html, svg } from "lit";
4
4
  import { property } from "lit/decorators.js";
5
5
  //#region src/swipe/swipe.ts
package/dist/swipe.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"swipe.js","names":["#removeWindowListeners","#emitInput","#scheduleRetraction","#cancelAnimation","#onWindowPointerUp","#onWindowPointerCancel","#startRetraction","#renderBars","customElement"],"sources":["../src/swipe/swipe.ts"],"sourcesContent":["/**\n * <ixfx-swipe> — Touch-friendly swipe/nudge component.\n *\n * User taps and drags to generate a value in range [-1, 1].\n * A drag of full component width = ±1. Value is emitted only on pointerup.\n *\n * Properties\n * barSpacing – center-to-center pixel distance between bars (default 20)\n * barWidth – pixel width of each bar (default 14)\n * debounceMs – ms pause after release before retraction begins (default 200)\n * retractDurationMs – ms for the spring-back animation (default 400)\n *\n * CSS custom properties\n * --swipe-color-a – fill for even-indexed bars (default var(--surface-4))\n * --swipe-color-b – fill for odd-indexed bars (default var(--surface-5))\n * --swipe-border-color – border color (default var(--border))\n *\n * Events\n * input – CustomEvent<{ detail: { value: number } }>, bubbles + composed\n */\nimport type { CSSResultGroup } from 'lit';\nimport { css, html, LitElement, svg } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { prominenceStyles } from '../styles/prominence.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\nexport type SwipeInputDetail = { readonly value: number };\nexport type SwipeInputEvent = CustomEvent<SwipeInputDetail>;\n\nexport interface SwipeElementEventMap {\n input: SwipeInputEvent;\n}\n\nexport interface SwipeElement {\n addEventListener<K extends keyof SwipeElementEventMap>(\n type: K,\n listener: (this: SwipeElement, event: SwipeElementEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-swipe': SwipeElement;\n }\n}\n\n@customElement(`ixfx-swipe`)\nexport class SwipeElement extends LitElement {\n @property({ type: Number }) barSpacing = 20;\n @property({ type: Number }) barWidth = 14;\n @property({ type: Number }) debounceMs = 200;\n @property({ type: Number }) retractDurationMs = 400;\n\n private _startX = 0;\n private _currentX = 0;\n private _pointerId: number | null = null;\n private _componentWidth = 0;\n private _isDragging = false;\n\n private _offset = 0;\n private _width = 0;\n private _height = 0;\n\n private _animRafId: number | null = null;\n private _debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private _animStartOffset = 0;\n private _animStartTime: number | null = null;\n private _resizeObserver: ResizeObserver | null = null;\n\n #onWindowPointerUp = (e: PointerEvent): void => {\n if (e.pointerId !== this._pointerId)\n return;\n this.#removeWindowListeners();\n\n const rect = this.getBoundingClientRect();\n const inside = e.clientX >= rect.left && e.clientX <= rect.right\n && e.clientY >= rect.top && e.clientY <= rect.bottom;\n\n if (inside) {\n const deltaX = this._currentX - this._startX;\n const value = Math.max(-1, Math.min(1, deltaX / this._componentWidth));\n this.#emitInput(value);\n }\n\n this._isDragging = false;\n this._pointerId = null;\n this.#scheduleRetraction();\n };\n\n #onWindowPointerCancel = (e: PointerEvent): void => {\n if (e.pointerId !== this._pointerId)\n return;\n this.#removeWindowListeners();\n this._isDragging = false;\n this._pointerId = null;\n this.#scheduleRetraction();\n };\n\n #emitInput(value: number): void {\n this.dispatchEvent(\n new CustomEvent<SwipeInputDetail>(`input`, {\n detail: { value },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (!entry)\n return;\n this._width = entry.contentRect.width;\n this._height = entry.contentRect.height;\n this.requestUpdate();\n });\n this._resizeObserver.observe(this);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._resizeObserver?.disconnect();\n this._resizeObserver = null;\n this.#cancelAnimation();\n this.#removeWindowListeners();\n this._isDragging = false;\n this._pointerId = null;\n }\n\n private _onPointerDown = (e: PointerEvent): void => {\n e.preventDefault();\n this.#cancelAnimation();\n const target = e.target as HTMLElement;\n target.setPointerCapture(e.pointerId);\n this._pointerId = e.pointerId;\n this._startX = e.clientX;\n this._currentX = e.clientX;\n this._componentWidth = this.getBoundingClientRect().width;\n this._isDragging = true;\n window.addEventListener(`pointerup`, this.#onWindowPointerUp);\n window.addEventListener(`pointercancel`, this.#onWindowPointerCancel);\n };\n\n private _onPointerMove = (e: PointerEvent): void => {\n if (!this._isDragging || e.pointerId !== this._pointerId)\n return;\n this._currentX = e.clientX;\n const deltaX = this._currentX - this._startX;\n const ratio = Math.max(-1, Math.min(1, deltaX / this._componentWidth));\n this._offset = ratio * this._height * 0.5;\n this.requestUpdate();\n };\n\n #removeWindowListeners(): void {\n window.removeEventListener(`pointerup`, this.#onWindowPointerUp);\n window.removeEventListener(`pointercancel`, this.#onWindowPointerCancel);\n }\n\n #scheduleRetraction(): void {\n if (this._debounceTimer !== null)\n clearTimeout(this._debounceTimer);\n this._debounceTimer = setTimeout(() => {\n this._debounceTimer = null;\n this.#startRetraction();\n }, this.debounceMs);\n }\n\n #startRetraction(): void {\n this._animStartOffset = this._offset;\n this._animStartTime = null;\n\n const animate = (time: number): void => {\n if (this._animStartTime === null)\n this._animStartTime = time;\n const elapsed = time - this._animStartTime;\n const t = Math.min(elapsed / this.retractDurationMs, 1);\n const eased = 1 - (1 - t) ** 3;\n this._offset = this._animStartOffset * (1 - eased);\n this.requestUpdate();\n\n if (t < 1) {\n this._animRafId = requestAnimationFrame(animate);\n } else {\n this._offset = 0;\n this._animRafId = null;\n this.requestUpdate();\n }\n };\n\n this._animRafId = requestAnimationFrame(animate);\n }\n\n #cancelAnimation(): void {\n if (this._animRafId !== null) {\n cancelAnimationFrame(this._animRafId);\n this._animRafId = null;\n }\n if (this._debounceTimer !== null) {\n clearTimeout(this._debounceTimer);\n this._debounceTimer = null;\n }\n }\n\n #renderBars(): ReturnType<typeof svg> {\n const w = this._width;\n const h = this._height;\n const off = this._offset;\n const { barSpacing, barWidth } = this;\n if (w === 0 || h === 0)\n return svg``;\n\n const half = barWidth / 2;\n const mid = h / 2;\n const count = Math.ceil(w / barSpacing) + 1;\n\n return svg`${Array.from({ length: count }, (_, i) => {\n const cx = i * barSpacing;\n const x0 = cx - half;\n const x1 = cx + half;\n const colorVar = i % 2 === 0\n ? `var(--swipe-color-a, var(--surface-4))`\n : `var(--swipe-color-b, var(--surface-5))`;\n const d = `M${x0},0 L${x1},0 L${x1 + off},${mid} L${x1},${h} L${x0},${h} L${x0 + off},${mid}Z`;\n return svg`<path d=${d} style=\"fill:${colorVar}\"></path>`;\n })}`;\n }\n\n static override styles: CSSResultGroup = [prominenceStyles, css`\n :host {\n display: block;\n user-select: none;\n touch-action: none;\n width: 100%;\n height: 2.5rem;\n --swipe-border-color: var(--border);\n }\n\n .swipe-area {\n position: relative;\n width: 100%;\n height: 100%;\n cursor: grab;\n border: var(--swipe-border-color);\n overflow: hidden;\n }\n\n .swipe-area:active {\n cursor: grabbing;\n }\n\n svg {\n display: block;\n width: 100%;\n height: 100%;\n }\n `];\n\n override render(): ReturnType<typeof html> {\n return html`\n <div\n class=\"swipe-area\"\n @pointerdown=${this._onPointerDown}\n @pointermove=${this._onPointerMove}\n >\n <svg aria-hidden=\"true\">${this.#renderBars()}</svg>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"swipe.js","names":["#removeWindowListeners","#emitInput","#scheduleRetraction","#cancelAnimation","#onWindowPointerUp","#onWindowPointerCancel","#startRetraction","#renderBars","customElement"],"sources":["../src/swipe/swipe.ts"],"sourcesContent":["/**\n * <ixfx-swipe> — Touch-friendly swipe/nudge component.\n *\n * User taps and drags to generate a value in range [-1, 1].\n * A drag of full component width = ±1. Value is emitted only on pointerup.\n *\n * Properties\n * barSpacing – center-to-center pixel distance between bars (default 20)\n * barWidth – pixel width of each bar (default 14)\n * debounceMs – ms pause after release before retraction begins (default 200)\n * retractDurationMs – ms for the spring-back animation (default 400)\n *\n * CSS custom properties\n * --swipe-color-a – fill for even-indexed bars (default var(--surface-4))\n * --swipe-color-b – fill for odd-indexed bars (default var(--surface-5))\n * --swipe-border-color – border color (default var(--border))\n *\n * Events\n * input – CustomEvent<{ detail: { value: number } }>, bubbles + composed\n */\nimport type { CSSResultGroup } from 'lit';\nimport { css, html, LitElement, svg } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { prominenceStyles } from '../styles/prominence.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\nexport type SwipeInputDetail = { readonly value: number };\nexport type SwipeInputEvent = CustomEvent<SwipeInputDetail>;\n\nexport interface SwipeElementEventMap {\n input: SwipeInputEvent;\n}\n\nexport interface SwipeElement {\n addEventListener: (<K extends keyof SwipeElementEventMap>(\n type: K,\n listener: (this: SwipeElement, event: SwipeElementEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ) => void) & ((\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ) => void);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-swipe': SwipeElement;\n }\n}\n\n@customElement(`ixfx-swipe`)\nexport class SwipeElement extends LitElement {\n @property({ type: Number }) barSpacing = 20;\n @property({ type: Number }) barWidth = 14;\n @property({ type: Number }) debounceMs = 200;\n @property({ type: Number }) retractDurationMs = 400;\n\n private _startX = 0;\n private _currentX = 0;\n private _pointerId: number | null = null;\n private _componentWidth = 0;\n private _isDragging = false;\n\n private _offset = 0;\n private _width = 0;\n private _height = 0;\n\n private _animRafId: number | null = null;\n private _debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private _animStartOffset = 0;\n private _animStartTime: number | null = null;\n private _resizeObserver: ResizeObserver | null = null;\n\n #onWindowPointerUp = (e: PointerEvent): void => {\n if (e.pointerId !== this._pointerId)\n return;\n this.#removeWindowListeners();\n\n const rect = this.getBoundingClientRect();\n const inside = e.clientX >= rect.left && e.clientX <= rect.right\n && e.clientY >= rect.top && e.clientY <= rect.bottom;\n\n if (inside) {\n const deltaX = this._currentX - this._startX;\n const value = Math.max(-1, Math.min(1, deltaX / this._componentWidth));\n this.#emitInput(value);\n }\n\n this._isDragging = false;\n this._pointerId = null;\n this.#scheduleRetraction();\n };\n\n #onWindowPointerCancel = (e: PointerEvent): void => {\n if (e.pointerId !== this._pointerId)\n return;\n this.#removeWindowListeners();\n this._isDragging = false;\n this._pointerId = null;\n this.#scheduleRetraction();\n };\n\n #emitInput(value: number): void {\n this.dispatchEvent(\n new CustomEvent<SwipeInputDetail>(`input`, {\n detail: { value },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (!entry)\n return;\n this._width = entry.contentRect.width;\n this._height = entry.contentRect.height;\n this.requestUpdate();\n });\n this._resizeObserver.observe(this);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._resizeObserver?.disconnect();\n this._resizeObserver = null;\n this.#cancelAnimation();\n this.#removeWindowListeners();\n this._isDragging = false;\n this._pointerId = null;\n }\n\n private _onPointerDown = (e: PointerEvent): void => {\n e.preventDefault();\n this.#cancelAnimation();\n const target = e.target as HTMLElement;\n target.setPointerCapture(e.pointerId);\n this._pointerId = e.pointerId;\n this._startX = e.clientX;\n this._currentX = e.clientX;\n this._componentWidth = this.getBoundingClientRect().width;\n this._isDragging = true;\n window.addEventListener(`pointerup`, this.#onWindowPointerUp);\n window.addEventListener(`pointercancel`, this.#onWindowPointerCancel);\n };\n\n private _onPointerMove = (e: PointerEvent): void => {\n if (!this._isDragging || e.pointerId !== this._pointerId)\n return;\n this._currentX = e.clientX;\n const deltaX = this._currentX - this._startX;\n const ratio = Math.max(-1, Math.min(1, deltaX / this._componentWidth));\n this._offset = ratio * this._height * 0.5;\n this.requestUpdate();\n };\n\n #removeWindowListeners(): void {\n window.removeEventListener(`pointerup`, this.#onWindowPointerUp);\n window.removeEventListener(`pointercancel`, this.#onWindowPointerCancel);\n }\n\n #scheduleRetraction(): void {\n if (this._debounceTimer !== null)\n clearTimeout(this._debounceTimer);\n this._debounceTimer = setTimeout(() => {\n this._debounceTimer = null;\n this.#startRetraction();\n }, this.debounceMs);\n }\n\n #startRetraction(): void {\n this._animStartOffset = this._offset;\n this._animStartTime = null;\n\n const animate = (time: number): void => {\n if (this._animStartTime === null)\n this._animStartTime = time;\n const elapsed = time - this._animStartTime;\n const t = Math.min(elapsed / this.retractDurationMs, 1);\n const eased = 1 - (1 - t) ** 3;\n this._offset = this._animStartOffset * (1 - eased);\n this.requestUpdate();\n\n if (t < 1) {\n this._animRafId = requestAnimationFrame(animate);\n } else {\n this._offset = 0;\n this._animRafId = null;\n this.requestUpdate();\n }\n };\n\n this._animRafId = requestAnimationFrame(animate);\n }\n\n #cancelAnimation(): void {\n if (this._animRafId !== null) {\n cancelAnimationFrame(this._animRafId);\n this._animRafId = null;\n }\n if (this._debounceTimer !== null) {\n clearTimeout(this._debounceTimer);\n this._debounceTimer = null;\n }\n }\n\n #renderBars(): ReturnType<typeof svg> {\n const w = this._width;\n const h = this._height;\n const off = this._offset;\n const { barSpacing, barWidth } = this;\n if (w === 0 || h === 0)\n return svg``;\n\n const half = barWidth / 2;\n const mid = h / 2;\n const count = Math.ceil(w / barSpacing) + 1;\n\n return svg`${Array.from({ length: count }, (_, i) => {\n const cx = i * barSpacing;\n const x0 = cx - half;\n const x1 = cx + half;\n const colorVar = i % 2 === 0\n ? `var(--swipe-color-a, var(--surface-4))`\n : `var(--swipe-color-b, var(--surface-5))`;\n const d = `M${x0},0 L${x1},0 L${x1 + off},${mid} L${x1},${h} L${x0},${h} L${x0 + off},${mid}Z`;\n return svg`<path d=${d} style=\"fill:${colorVar}\"></path>`;\n })}`;\n }\n\n static override styles: CSSResultGroup = [prominenceStyles, css`\n :host {\n display: block;\n user-select: none;\n touch-action: none;\n width: 100%;\n height: 2.5rem;\n --swipe-border-color: var(--border);\n }\n\n .swipe-area {\n position: relative;\n width: 100%;\n height: 100%;\n cursor: grab;\n border: var(--swipe-border-color);\n overflow: hidden;\n }\n\n .swipe-area:active {\n cursor: grabbing;\n }\n\n svg {\n display: block;\n width: 100%;\n height: 100%;\n }\n `];\n\n override render(): ReturnType<typeof html> {\n return html`\n <div\n class=\"swipe-area\"\n @pointerdown=${this._onPointerDown}\n @pointermove=${this._onPointerMove}\n >\n <svg aria-hidden=\"true\">${this.#renderBars()}</svg>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
package/dist/tabs.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as safeCustomElement, t as __decorate } from "./decorate-O4m1U4l3.js";
1
+ import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
2
2
  import { LitElement, css, html } from "lit";
3
3
  import { property } from "lit/decorators.js";
4
4
  //#region src/tabs/tab-list.ts
@@ -68,7 +68,7 @@ let TabListElement = class TabListElement extends LitElement {
68
68
  }
69
69
  updated(changedProperties) {
70
70
  super.updated(changedProperties);
71
- this.classList.toggle("scrollable", this.scrollable);
71
+ this.classList.toggle(`scrollable`, this.scrollable);
72
72
  }
73
73
  #syncIndicatorColors() {
74
74
  for (const item of this.#items) {
package/dist/tabs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.js","names":["#items","#syncIndicatorColors","#isVertical","#selectPrevious","#selectNext","#containerClass","#onKeyUp","#onSlotClick","#onSlotChange","#isSelected","customElement"],"sources":["../src/tabs/tab-list.ts"],"sourcesContent":["import type { TabListItemElement } from \"./tab-list-item.js\";\nimport type { PropertyValues } from \"lit\";\nimport { css, html, LitElement } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { safeCustomElement as customElement } from \"../util/custom-elements.js\";\n\n/**\n * Events\n * 'change' - new tab selected { previous:string, selected:string, for:string }\n */\nexport type TabListChangeDetail = {\n readonly previous: string | undefined;\n readonly selected: string;\n readonly for: string;\n};\n\nexport type TabListChangeEvent = CustomEvent<TabListChangeDetail>;\n\n@customElement(`ixfx-tab-list`)\nexport class TabListElement extends LitElement {\n @property({ type: String })\n orientation: `horizontal` | `vertical-stack` | `vertical-side` = `horizontal`;\n\n @property({ type: Boolean })\n flip = false;\n\n @property({ type: Boolean })\n scrollable = false;\n\n #items: TabListItemElement[] = [];\n\n get #isVertical(): boolean {\n return this.orientation === `vertical-stack` || this.orientation === `vertical-side`;\n }\n\n get #containerClass(): string {\n return this.scrollable ? `${this.orientation} scrollable` : this.orientation;\n }\n\n override render() {\n return html`\n <div \n tabindex=0 \n @keyup=${this.#onKeyUp} \n @click=${this.#onSlotClick} \n id=\"container\" \n class=${this.#containerClass}\n >\n <slot @slotchange=${this.#onSlotChange}></slot>\n </div>`;\n }\n\n #onSlotChange = () => {\n this.updateComplete.then(() => {\n this.#items = (this.shadowRoot?.querySelector(`slot`) as HTMLSlotElement)\n ?.assignedElements({ flatten: true }) as TabListItemElement[] ?? [];\n this.#syncIndicatorColors();\n });\n };\n\n override firstUpdated() {\n this.updateComplete.then(() => {\n if (this.#items.length > 0) {\n this.#syncIndicatorColors();\n }\n });\n }\n\n override updated(changedProperties: PropertyValues): void {\n super.updated(changedProperties);\n this.classList.toggle('scrollable', this.scrollable);\n }\n\n #syncIndicatorColors() {\n for (const item of this.#items) {\n item.style.setProperty(`--indicator-color-bottom`, `transparent`);\n item.style.setProperty(`--indicator-color-top`, `transparent`);\n item.style.setProperty(`--indicator-color-left`, `transparent`);\n item.style.setProperty(`--indicator-color-right`, `transparent`);\n\n if (item.hasAttribute(`selected`)) {\n if (this.orientation === `horizontal` && !this.flip) {\n item.style.setProperty(`--indicator-color-bottom`, `var(--accent)`);\n } else if (this.orientation === `horizontal` && this.flip) {\n item.style.setProperty(`--indicator-color-top`, `var(--accent)`);\n } else if (this.#isVertical && !this.flip) {\n item.style.setProperty(`--indicator-color-right`, `var(--accent)`);\n } else if (this.#isVertical && this.flip) {\n item.style.setProperty(`--indicator-color-left`, `var(--accent)`);\n }\n }\n }\n }\n\n #onKeyUp = (event: KeyboardEvent) => {\n const key = event.key;\n if (this.#isVertical) {\n if (key === `ArrowUp`) {\n this.#selectPrevious();\n } else if (key === `ArrowDown`) {\n this.#selectNext();\n }\n } else {\n if (key === `ArrowRight`) {\n this.#selectNext();\n } else if (key === `ArrowLeft`) {\n this.#selectPrevious();\n }\n }\n };\n\n getSelectedElement() {\n for (const el of this.#items) {\n if (this.#isSelected(el))\n return el;\n }\n }\n\n #isSelected(el: HTMLElement) {\n const v = el.getAttribute(`selected`);\n if (v === null)\n return false;\n return (el.hasAttribute(`selected`));\n }\n\n selectElement(el: HTMLElement) {\n const existing = this.getSelectedElement();\n if (existing) {\n existing.removeAttribute(`selected`);\n existing.style.setProperty(`--indicator-color-bottom`, `transparent`);\n existing.style.setProperty(`--indicator-color-top`, `transparent`);\n existing.style.setProperty(`--indicator-color-left`, `transparent`);\n existing.style.setProperty(`--indicator-color-right`, `transparent`);\n }\n\n el.setAttribute(`selected`, ``);\n\n if (this.orientation === `horizontal` && !this.flip) {\n el.style.setProperty(`--indicator-color-bottom`, `var(--accent)`);\n } else if (this.orientation === `horizontal` && this.flip) {\n el.style.setProperty(`--indicator-color-top`, `var(--accent)`);\n } else if (this.#isVertical && !this.flip) {\n el.style.setProperty(`--indicator-color-right`, `var(--accent)`);\n } else if (this.#isVertical && this.flip) {\n el.style.setProperty(`--indicator-color-left`, `var(--accent)`);\n }\n }\n\n #selectNext() {\n let found = false;\n for (const el of this.#items) {\n if (this.#isSelected(el) && !found) {\n found = true;\n } else if (found) {\n this.selectElement(el);\n break;\n }\n }\n }\n\n #selectPrevious() {\n let prev: HTMLElement | undefined;\n for (const el of this.#items) {\n if (this.#isSelected(el) && prev) {\n this.selectElement(prev);\n } else {\n prev = el;\n }\n }\n }\n\n #onSlotClick = (event: MouseEvent) => {\n this.focus();\n const t = (event.target as HTMLElement).closest(`ixfx-tab-list-item`);\n if (!t)\n return;\n const previous = this.getSelectedElement();\n this.selectElement(t);\n\n const forId = t.getAttribute(`for`);\n const previousId = previous?.id;\n this.dispatchEvent(new CustomEvent<TabListChangeDetail>(`change`, {\n bubbles: true,\n detail: {\n previous: previousId,\n selected: t.id,\n for: forId ?? ``,\n },\n }));\n };\n\n static styles = css`\n :host {\n display: inline-block;\n --activated-colour: var(--accent);\n --colour: var(--surface-4);\n --scroll-max-height: 200px;\n --allow-overflow: hidden;\n }\n :host(.scrollable) {\n max-height: var(--scroll-max-height);\n }\n text {\n user-select:none;\n }\n #container {\n display:flex;\n }\n #container.horizontal {\n flex-direction: row;\n overflow: hidden;\n }\n #container.horizontal.scrollable {\n overflow-x: auto;\n --allow-overflow: visible;\n }\n #container.horizontal.scrollable ::slotted(ixfx-tab-list-item) {\n flex-shrink: 0;\n }\n #container.vertical-stack {\n flex-direction: column;\n }\n #container.vertical-stack.flip {\n flex-direction: column-reverse;\n }\n #container.vertical-stack.scrollable {\n overflow-y: auto;\n max-height: var(--scroll-max-height);\n --allow-overflow: visible;\n }\n #container.vertical-side {\n flex-direction: column;\n }\n #container.vertical-side.flip {\n flex-direction: column-reverse;\n }\n #container.vertical-side.scrollable {\n overflow-y: auto;\n max-height: var(--scroll-max-height);\n --allow-overflow: visible;\n }\n\n ::slotted(ixfx-tab-list-item) {\n flex: 1 1 auto;\n min-width: 0;\n }\n\n #container.vertical-side ::slotted(ixfx-tab-list-item) {\n writing-mode: vertical-lr;\n text-orientation: mixed;\n }\n #container.vertical-side.flip ::slotted(ixfx-tab-list-item) {\n writing-mode: vertical-rl;\n text-orientation: mixed;\n }\n\n ::slotted(.activated) {\n --colour: var(--activated-colour);\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ixfx-tab-list\": TabListElement;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tabs.js","names":["#items","#syncIndicatorColors","#isVertical","#selectPrevious","#selectNext","#containerClass","#onKeyUp","#onSlotClick","#onSlotChange","#isSelected","customElement"],"sources":["../src/tabs/tab-list.ts"],"sourcesContent":["import type { PropertyValues } from \"lit\";\nimport type { TabListItemElement } from \"./tab-list-item.js\";\nimport { css, html, LitElement } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { safeCustomElement as customElement } from \"../util/custom-elements.js\";\n\n/**\n * Events\n * 'change' - new tab selected { previous:string, selected:string, for:string }\n */\nexport type TabListChangeDetail = {\n readonly previous: string | undefined;\n readonly selected: string;\n readonly for: string;\n};\n\nexport type TabListChangeEvent = CustomEvent<TabListChangeDetail>;\n\n@customElement(`ixfx-tab-list`)\nexport class TabListElement extends LitElement {\n @property({ type: String })\n orientation: `horizontal` | `vertical-stack` | `vertical-side` = `horizontal`;\n\n @property({ type: Boolean })\n flip = false;\n\n @property({ type: Boolean })\n scrollable = false;\n\n #items: TabListItemElement[] = [];\n\n get #isVertical(): boolean {\n return this.orientation === `vertical-stack` || this.orientation === `vertical-side`;\n }\n\n get #containerClass(): string {\n return this.scrollable ? `${this.orientation} scrollable` : this.orientation;\n }\n\n override render() {\n return html`\n <div \n tabindex=0 \n @keyup=${this.#onKeyUp} \n @click=${this.#onSlotClick} \n id=\"container\" \n class=${this.#containerClass}\n >\n <slot @slotchange=${this.#onSlotChange}></slot>\n </div>`;\n }\n\n #onSlotChange = () => {\n this.updateComplete.then(() => {\n this.#items = (this.shadowRoot?.querySelector(`slot`) as HTMLSlotElement)\n ?.assignedElements({ flatten: true }) as TabListItemElement[] ?? [];\n this.#syncIndicatorColors();\n });\n };\n\n override firstUpdated() {\n this.updateComplete.then(() => {\n if (this.#items.length > 0) {\n this.#syncIndicatorColors();\n }\n });\n }\n\n override updated(changedProperties: PropertyValues): void {\n super.updated(changedProperties);\n this.classList.toggle(`scrollable`, this.scrollable);\n }\n\n #syncIndicatorColors() {\n for (const item of this.#items) {\n item.style.setProperty(`--indicator-color-bottom`, `transparent`);\n item.style.setProperty(`--indicator-color-top`, `transparent`);\n item.style.setProperty(`--indicator-color-left`, `transparent`);\n item.style.setProperty(`--indicator-color-right`, `transparent`);\n\n if (item.hasAttribute(`selected`)) {\n if (this.orientation === `horizontal` && !this.flip) {\n item.style.setProperty(`--indicator-color-bottom`, `var(--accent)`);\n } else if (this.orientation === `horizontal` && this.flip) {\n item.style.setProperty(`--indicator-color-top`, `var(--accent)`);\n } else if (this.#isVertical && !this.flip) {\n item.style.setProperty(`--indicator-color-right`, `var(--accent)`);\n } else if (this.#isVertical && this.flip) {\n item.style.setProperty(`--indicator-color-left`, `var(--accent)`);\n }\n }\n }\n }\n\n #onKeyUp = (event: KeyboardEvent) => {\n const key = event.key;\n if (this.#isVertical) {\n if (key === `ArrowUp`) {\n this.#selectPrevious();\n } else if (key === `ArrowDown`) {\n this.#selectNext();\n }\n } else {\n if (key === `ArrowRight`) {\n this.#selectNext();\n } else if (key === `ArrowLeft`) {\n this.#selectPrevious();\n }\n }\n };\n\n getSelectedElement() {\n for (const el of this.#items) {\n if (this.#isSelected(el))\n return el;\n }\n }\n\n #isSelected(el: HTMLElement) {\n const v = el.getAttribute(`selected`);\n if (v === null)\n return false;\n return (el.hasAttribute(`selected`));\n }\n\n selectElement(el: HTMLElement) {\n const existing = this.getSelectedElement();\n if (existing) {\n existing.removeAttribute(`selected`);\n existing.style.setProperty(`--indicator-color-bottom`, `transparent`);\n existing.style.setProperty(`--indicator-color-top`, `transparent`);\n existing.style.setProperty(`--indicator-color-left`, `transparent`);\n existing.style.setProperty(`--indicator-color-right`, `transparent`);\n }\n\n el.setAttribute(`selected`, ``);\n\n if (this.orientation === `horizontal` && !this.flip) {\n el.style.setProperty(`--indicator-color-bottom`, `var(--accent)`);\n } else if (this.orientation === `horizontal` && this.flip) {\n el.style.setProperty(`--indicator-color-top`, `var(--accent)`);\n } else if (this.#isVertical && !this.flip) {\n el.style.setProperty(`--indicator-color-right`, `var(--accent)`);\n } else if (this.#isVertical && this.flip) {\n el.style.setProperty(`--indicator-color-left`, `var(--accent)`);\n }\n }\n\n #selectNext() {\n let found = false;\n for (const el of this.#items) {\n if (this.#isSelected(el) && !found) {\n found = true;\n } else if (found) {\n this.selectElement(el);\n break;\n }\n }\n }\n\n #selectPrevious() {\n let prev: HTMLElement | undefined;\n for (const el of this.#items) {\n if (this.#isSelected(el) && prev) {\n this.selectElement(prev);\n } else {\n prev = el;\n }\n }\n }\n\n #onSlotClick = (event: MouseEvent) => {\n this.focus();\n const t = (event.target as HTMLElement).closest(`ixfx-tab-list-item`);\n if (!t)\n return;\n const previous = this.getSelectedElement();\n this.selectElement(t);\n\n const forId = t.getAttribute(`for`);\n const previousId = previous?.id;\n this.dispatchEvent(new CustomEvent<TabListChangeDetail>(`change`, {\n bubbles: true,\n detail: {\n previous: previousId,\n selected: t.id,\n for: forId ?? ``,\n },\n }));\n };\n\n static styles = css`\n :host {\n display: inline-block;\n --activated-colour: var(--accent);\n --colour: var(--surface-4);\n --scroll-max-height: 200px;\n --allow-overflow: hidden;\n }\n :host(.scrollable) {\n max-height: var(--scroll-max-height);\n }\n text {\n user-select:none;\n }\n #container {\n display:flex;\n }\n #container.horizontal {\n flex-direction: row;\n overflow: hidden;\n }\n #container.horizontal.scrollable {\n overflow-x: auto;\n --allow-overflow: visible;\n }\n #container.horizontal.scrollable ::slotted(ixfx-tab-list-item) {\n flex-shrink: 0;\n }\n #container.vertical-stack {\n flex-direction: column;\n }\n #container.vertical-stack.flip {\n flex-direction: column-reverse;\n }\n #container.vertical-stack.scrollable {\n overflow-y: auto;\n max-height: var(--scroll-max-height);\n --allow-overflow: visible;\n }\n #container.vertical-side {\n flex-direction: column;\n }\n #container.vertical-side.flip {\n flex-direction: column-reverse;\n }\n #container.vertical-side.scrollable {\n overflow-y: auto;\n max-height: var(--scroll-max-height);\n --allow-overflow: visible;\n }\n\n ::slotted(ixfx-tab-list-item) {\n flex: 1 1 auto;\n min-width: 0;\n }\n\n #container.vertical-side ::slotted(ixfx-tab-list-item) {\n writing-mode: vertical-lr;\n text-orientation: mixed;\n }\n #container.vertical-side.flip ::slotted(ixfx-tab-list-item) {\n writing-mode: vertical-rl;\n text-orientation: mixed;\n }\n\n ::slotted(.activated) {\n --colour: var(--activated-colour);\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ixfx-tab-list\": TabListElement;\n }\n}\n"],"mappings":"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"}