@ixfx/components 0.2.3 → 0.2.5
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.
- package/LICENSE +1 -1
- package/bundle/chunk-pbuEa-1d.js +13 -0
- package/bundle/index.d.ts +4702 -569
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +34929 -2800
- package/bundle/index.js.map +1 -1
- package/bundle/style.css +133 -0
- package/dist/ac-text.d.ts +97 -0
- package/dist/ac-text.d.ts.map +1 -0
- package/dist/ac-text.js +484 -0
- package/dist/ac-text.js.map +1 -0
- package/dist/button-DgKUzE5o.js +121 -0
- package/dist/button-DgKUzE5o.js.map +1 -0
- package/dist/button.d.ts +21 -0
- package/dist/button.d.ts.map +1 -0
- package/dist/button.js +3 -0
- package/dist/checkbox.d.ts +34 -0
- package/dist/checkbox.d.ts.map +1 -0
- package/dist/checkbox.js +251 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/chunk-pbuEa-1d.js +13 -0
- package/dist/colour-C3MQIjFJ-BJV-QC-3.js +4138 -0
- package/dist/colour-C3MQIjFJ-BJV-QC-3.js.map +1 -0
- package/dist/colour-picker-Bw-AZoWx.js +922 -0
- package/dist/colour-picker-Bw-AZoWx.js.map +1 -0
- package/dist/colour-picker.d.ts +2 -0
- package/dist/colour-picker.js +2 -0
- package/dist/crumbs.d.ts +92 -0
- package/dist/crumbs.d.ts.map +1 -0
- package/dist/crumbs.js +789 -0
- package/dist/crumbs.js.map +1 -0
- package/dist/data-display.d.ts +24 -12
- package/dist/data-display.d.ts.map +1 -1
- package/dist/data-display.js +96 -105
- package/dist/data-display.js.map +1 -1
- package/dist/decorate-BZbkqIhA.js +9 -0
- package/dist/defaults-FEZaGiYZ.js +38 -0
- package/dist/defaults-FEZaGiYZ.js.map +1 -0
- package/dist/dist-By5URG0Y.js +1290 -0
- package/dist/dist-By5URG0Y.js.map +1 -0
- package/dist/dist-D7kJgnSE.js +1039 -0
- package/dist/dist-D7kJgnSE.js.map +1 -0
- package/dist/editable-label.d.ts +71 -0
- package/dist/editable-label.d.ts.map +1 -0
- package/dist/editable-label.js +279 -0
- package/dist/editable-label.js.map +1 -0
- package/dist/hex-editor-Gib1Grg2.d.ts +131 -0
- package/dist/hex-editor-Gib1Grg2.d.ts.map +1 -0
- package/dist/hex-editor-Wd6ZtZA2.js +1147 -0
- package/dist/hex-editor-Wd6ZtZA2.js.map +1 -0
- package/dist/hex.d.ts +2 -0
- package/dist/hex.js +2 -0
- package/dist/highlight-CAjwQ4GE.js +50 -0
- package/dist/highlight-CAjwQ4GE.js.map +1 -0
- package/dist/icon-BR5aTIiP.js +100 -0
- package/dist/icon-BR5aTIiP.js.map +1 -0
- package/dist/icon-DQKdfR7U.d.ts +36 -0
- package/dist/icon-DQKdfR7U.d.ts.map +1 -0
- package/dist/icons.d.ts +3 -0
- package/dist/icons.js +9 -0
- package/dist/icons.js.map +1 -0
- package/dist/incr-search-BjCNClnC.js +311 -0
- package/dist/incr-search-BjCNClnC.js.map +1 -0
- package/dist/incr-search.d.ts +2 -0
- package/dist/incr-search.js +3 -0
- package/dist/index-B1hNR7Z9.d.ts +36 -0
- package/dist/index-B1hNR7Z9.d.ts.map +1 -0
- package/dist/index-C5dK8RZa.d.ts +23 -0
- package/dist/index-C5dK8RZa.d.ts.map +1 -0
- package/dist/index-C9iBN908.d.ts +160 -0
- package/dist/index-C9iBN908.d.ts.map +1 -0
- package/dist/index-CPVcTTXo.d.ts +396 -0
- package/dist/index-CPVcTTXo.d.ts.map +1 -0
- package/dist/index-CQxanqXF.d.ts +183 -0
- package/dist/index-CQxanqXF.d.ts.map +1 -0
- package/dist/index-CpbBI3n7.d.ts +1239 -0
- package/dist/index-CpbBI3n7.d.ts.map +1 -0
- package/dist/index.d.ts +422 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5729 -14
- package/dist/index.js.map +1 -1
- package/dist/interaction-CQDQJf2Q.js +1 -0
- package/dist/keyboard-De_vOHLg.js +20 -0
- package/dist/keyboard-De_vOHLg.js.map +1 -0
- package/dist/labelled-input-base-DS6-6C0r.js +155 -0
- package/dist/labelled-input-base-DS6-6C0r.js.map +1 -0
- package/dist/labelled-input-base-DnRh4reU.d.ts +43 -0
- package/dist/labelled-input-base-DnRh4reU.d.ts.map +1 -0
- package/dist/labelled-radial-input.d.ts +34 -0
- package/dist/labelled-radial-input.d.ts.map +1 -0
- package/dist/labelled-radial-input.js +188 -0
- package/dist/labelled-radial-input.js.map +1 -0
- package/dist/labelled-range-input.d.ts +2 -0
- package/dist/labelled-range-input.js +132 -0
- package/dist/labelled-range-input.js.map +1 -0
- package/dist/led.d.ts +25 -0
- package/dist/led.d.ts.map +1 -0
- package/dist/led.js +92 -0
- package/dist/led.js.map +1 -0
- package/dist/menu-BV6UFx_z.js +813 -0
- package/dist/menu-BV6UFx_z.js.map +1 -0
- package/dist/menu-item-Cikacp4F.d.ts +128 -0
- package/dist/menu-item-Cikacp4F.d.ts.map +1 -0
- package/dist/menu-item-DEzL_Yjk.js +766 -0
- package/dist/menu-item-DEzL_Yjk.js.map +1 -0
- package/dist/menu.d.ts +3 -0
- package/dist/menu.js +3 -0
- package/dist/miller.d.ts +324 -0
- package/dist/miller.d.ts.map +1 -0
- package/dist/miller.js +1343 -0
- package/dist/miller.js.map +1 -0
- package/dist/narrowed-text.d.ts +72 -0
- package/dist/narrowed-text.d.ts.map +1 -0
- package/dist/narrowed-text.js +571 -0
- package/dist/narrowed-text.js.map +1 -0
- package/dist/panel.d.ts +43 -0
- package/dist/panel.d.ts.map +1 -0
- package/dist/panel.js +408 -0
- package/dist/panel.js.map +1 -0
- package/dist/plots.d.ts +2 -0
- package/dist/plots.js +2 -0
- package/dist/polar-pad.d.ts +67 -0
- package/dist/polar-pad.d.ts.map +1 -0
- package/dist/polar-pad.js +537 -0
- package/dist/polar-pad.js.map +1 -0
- package/dist/popup-Ddx9LCzY.js +24 -0
- package/dist/popup-Ddx9LCzY.js.map +1 -0
- package/dist/prominence-CreDBdCs.js +98 -0
- package/dist/prominence-CreDBdCs.js.map +1 -0
- package/dist/radial-input-CNJ8asY2.js +849 -0
- package/dist/radial-input-CNJ8asY2.js.map +1 -0
- package/dist/radial-input-xSTd4kEz.d.ts +70 -0
- package/dist/radial-input-xSTd4kEz.d.ts.map +1 -0
- package/dist/radial-input.d.ts +2 -0
- package/dist/radial-input.js +2 -0
- package/dist/range-input.d.ts +43 -0
- package/dist/range-input.d.ts.map +1 -0
- package/dist/range-input.js +459 -0
- package/dist/range-input.js.map +1 -0
- package/dist/range.d.ts +28 -0
- package/dist/range.d.ts.map +1 -0
- package/dist/range.js +136 -0
- package/dist/range.js.map +1 -0
- package/dist/registry-CZEB1YI9.js +21 -0
- package/dist/registry-CZEB1YI9.js.map +1 -0
- package/dist/selecthorizontal.d.ts +13 -8
- package/dist/selecthorizontal.d.ts.map +1 -1
- package/dist/selecthorizontal.js +21 -25
- package/dist/selecthorizontal.js.map +1 -1
- package/dist/snap-container.d.ts +50 -0
- package/dist/snap-container.d.ts.map +1 -0
- package/dist/snap-container.js +297 -0
- package/dist/snap-container.js.map +1 -0
- package/dist/split-layout.d.ts +56 -0
- package/dist/split-layout.d.ts.map +1 -0
- package/dist/split-layout.js +545 -0
- package/dist/split-layout.js.map +1 -0
- package/dist/style.css +133 -0
- package/dist/swipe.d.ts +48 -0
- package/dist/swipe.d.ts.map +1 -0
- package/dist/swipe.js +204 -0
- package/dist/swipe.js.map +1 -0
- package/dist/tab-list-CFF7uSYH.d.ts +66 -0
- package/dist/tab-list-CFF7uSYH.d.ts.map +1 -0
- package/dist/tabs.d.ts +2 -0
- package/dist/tabs.js +203 -0
- package/dist/tabs.js.map +1 -0
- package/dist/tickled-controller-Cq1Va0rR.d.ts +218 -0
- package/dist/tickled-controller-Cq1Va0rR.d.ts.map +1 -0
- package/dist/tickled-styles-Bg3QbcrD.js +327 -0
- package/dist/tickled-styles-Bg3QbcrD.js.map +1 -0
- package/dist/timeline-DBWJsSjd.js +1748 -0
- package/dist/timeline-DBWJsSjd.js.map +1 -0
- package/dist/timeline.d.ts +2 -0
- package/dist/timeline.js +2 -0
- package/dist/tooltip-DMxmBNky.js +104 -0
- package/dist/tooltip-DMxmBNky.js.map +1 -0
- package/dist/tooltip-kfUBWYVB.d.ts +26 -0
- package/dist/tooltip-kfUBWYVB.d.ts.map +1 -0
- package/dist/tree-component-CQpoPo4s.d.ts +326 -0
- package/dist/tree-component-CQpoPo4s.d.ts.map +1 -0
- package/dist/tree-data-model-DGvRVOFY.js +190 -0
- package/dist/tree-data-model-DGvRVOFY.js.map +1 -0
- package/dist/tree.d.ts +100 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +1144 -0
- package/dist/tree.js.map +1 -0
- package/dist/types-BKaqnpwx.d.ts +8 -0
- package/dist/types-BKaqnpwx.d.ts.map +1 -0
- package/dist/xy-axis-BANbgrI5.js +6243 -0
- package/dist/xy-axis-BANbgrI5.js.map +1 -0
- package/dist/xy-axis-CIFok7MF.d.ts +141 -0
- package/dist/xy-axis-CIFok7MF.d.ts.map +1 -0
- package/dist/xy-pad.d.ts +81 -0
- package/dist/xy-pad.d.ts.map +1 -0
- package/dist/xy-pad.js +435 -0
- package/dist/xy-pad.js.map +1 -0
- package/package.json +48 -39
- package/README.md +0 -14
- package/dist/charts/frequency-histogram-plot.d.ts +0 -33
- package/dist/charts/frequency-histogram-plot.d.ts.map +0 -1
- package/dist/charts/frequency-histogram-plot.js +0 -54
- package/dist/charts/frequency-histogram-plot.js.map +0 -1
- package/dist/charts/histogram-vis.d.ts +0 -57
- package/dist/charts/histogram-vis.d.ts.map +0 -1
- package/dist/charts/histogram-vis.js +0 -222
- package/dist/charts/histogram-vis.js.map +0 -1
- package/dist/charts/plot.d.ts +0 -199
- package/dist/charts/plot.d.ts.map +0 -1
- package/dist/charts/plot.js +0 -914
- package/dist/charts/plot.js.map +0 -1
- package/dist/crumb-nav.d.ts +0 -41
- package/dist/crumb-nav.d.ts.map +0 -1
- package/dist/crumb-nav.js +0 -198
- package/dist/crumb-nav.js.map +0 -1
- package/dist/crumb-navigation.d.ts +0 -30
- package/dist/crumb-navigation.d.ts.map +0 -1
- package/dist/crumb-navigation.js +0 -307
- package/dist/crumb-navigation.js.map +0 -1
- package/dist/dial.d.ts +0 -89
- package/dist/dial.d.ts.map +0 -1
- package/dist/dial.js +0 -506
- package/dist/dial.js.map +0 -1
- package/dist/my-element.d.ts +0 -14
- package/dist/my-element.d.ts.map +0 -1
- package/dist/my-element.js +0 -44
- package/dist/my-element.js.map +0 -1
- package/dist/split-layout/split-layout.d.ts +0 -35
- package/dist/split-layout/split-layout.d.ts.map +0 -1
- package/dist/split-layout/split-layout.js +0 -220
- package/dist/split-layout/split-layout.js.map +0 -1
- package/dist/svg-edit-label.d.ts +0 -2
- package/dist/svg-edit-label.d.ts.map +0 -1
- package/dist/svg-edit-label.js +0 -110
- package/dist/svg-edit-label.js.map +0 -1
- package/dist/tabs/tab-layout-item.d.ts +0 -10
- package/dist/tabs/tab-layout-item.d.ts.map +0 -1
- package/dist/tabs/tab-layout-item.js +0 -20
- package/dist/tabs/tab-layout-item.js.map +0 -1
- package/dist/tabs/tab-layout.d.ts +0 -10
- package/dist/tabs/tab-layout.d.ts.map +0 -1
- package/dist/tabs/tab-layout.js +0 -25
- package/dist/tabs/tab-layout.js.map +0 -1
- package/dist/tabs/tab-list-item.d.ts +0 -18
- package/dist/tabs/tab-list-item.d.ts.map +0 -1
- package/dist/tabs/tab-list-item.js +0 -63
- package/dist/tabs/tab-list-item.js.map +0 -1
- package/dist/tabs/tab-list.d.ts +0 -21
- package/dist/tabs/tab-list.d.ts.map +0 -1
- package/dist/tabs/tab-list.js +0 -148
- package/dist/tabs/tab-list.js.map +0 -1
- package/dist/tabs/tab-panel.d.ts +0 -11
- package/dist/tabs/tab-panel.d.ts.map +0 -1
- package/dist/tabs/tab-panel.js +0 -30
- package/dist/tabs/tab-panel.js.map +0 -1
- package/dist/tabs/tab-panels.d.ts +0 -30
- package/dist/tabs/tab-panels.d.ts.map +0 -1
- package/dist/tabs/tab-panels.js +0 -80
- package/dist/tabs/tab-panels.js.map +0 -1
- package/dist/util/circle-arc.d.ts +0 -34
- package/dist/util/circle-arc.d.ts.map +0 -1
- package/dist/util/circle-arc.js +0 -77
- package/dist/util/circle-arc.js.map +0 -1
- package/dist/util/compare.d.ts +0 -53
- package/dist/util/compare.d.ts.map +0 -1
- package/dist/util/compare.js +0 -91
- package/dist/util/compare.js.map +0 -1
- package/dist/util/content-editable.d.ts +0 -2
- package/dist/util/content-editable.d.ts.map +0 -1
- package/dist/util/content-editable.js +0 -13
- package/dist/util/content-editable.js.map +0 -1
- package/dist/util/drag-controller.d.ts +0 -13
- package/dist/util/drag-controller.d.ts.map +0 -1
- package/dist/util/drag-controller.js +0 -21
- package/dist/util/drag-controller.js.map +0 -1
- package/dist/util/key-value.d.ts +0 -5
- package/dist/util/key-value.d.ts.map +0 -1
- package/dist/util/key-value.js +0 -30
- package/dist/util/key-value.js.map +0 -1
- package/dist/util/primitive-types.d.ts +0 -6
- package/dist/util/primitive-types.d.ts.map +0 -1
- package/dist/util/primitive-types.js +0 -2
- package/dist/util/primitive-types.js.map +0 -1
- package/dist/util/svg-editable-text.d.ts +0 -22
- package/dist/util/svg-editable-text.d.ts.map +0 -1
- package/dist/util/svg-editable-text.js +0 -121
- package/dist/util/svg-editable-text.js.map +0 -1
- package/dist/util/time.d.ts +0 -2
- package/dist/util/time.d.ts.map +0 -1
- package/dist/util/time.js +0 -2
- package/dist/util/time.js.map +0 -1
|
@@ -0,0 +1,849 @@
|
|
|
1
|
+
import { t as __decorate } from "./decorate-BZbkqIhA.js";
|
|
2
|
+
import { t as prominenceStyles } from "./prominence-CreDBdCs.js";
|
|
3
|
+
import { t as resolveStep } from "./keyboard-De_vOHLg.js";
|
|
4
|
+
import { LitElement, css, html, svg } from "lit";
|
|
5
|
+
import { customElement, property } from "lit/decorators.js";
|
|
6
|
+
//#region src/radial-input/svg-utils.ts
|
|
7
|
+
const PI2 = Math.PI * 2;
|
|
8
|
+
const MIDPOINT_ANGLE = -Math.PI / 2;
|
|
9
|
+
/**
|
|
10
|
+
* Convert polar coordinates (angle in radians, radius) to SVG Cartesian coordinates
|
|
11
|
+
* @param angle - Angle in radians (0 = right/east, increases clockwise in SVG)
|
|
12
|
+
* @param radius - Distance from center
|
|
13
|
+
* @param center - Center point (default: {x: 50, y: 50})
|
|
14
|
+
* @returns Point in SVG coordinates
|
|
15
|
+
*/
|
|
16
|
+
function polarToCartesian(angle, radius, center = {
|
|
17
|
+
x: 50,
|
|
18
|
+
y: 50
|
|
19
|
+
}) {
|
|
20
|
+
return {
|
|
21
|
+
x: center.x + Math.cos(angle) * radius,
|
|
22
|
+
y: center.y + Math.sin(angle) * radius
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Calculate start and end angles for a flattened circle
|
|
27
|
+
* @param flatten - How much of the circle to hide (0..1): 0 = full circle, 0.5 = half circle, 1 = no arc
|
|
28
|
+
* @returns Start and end angles in radians
|
|
29
|
+
*/
|
|
30
|
+
function getFlattenedCircleAngles(flatten) {
|
|
31
|
+
const halfArc = PI2 * (1 - flatten) / 2;
|
|
32
|
+
const topAngle = -Math.PI / 2;
|
|
33
|
+
const startAngle = topAngle - halfArc;
|
|
34
|
+
const endAngle = topAngle + halfArc;
|
|
35
|
+
return {
|
|
36
|
+
startAngle,
|
|
37
|
+
endAngle,
|
|
38
|
+
totalArc: endAngle - startAngle
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Map a value (0..1) to an angle based on value mode
|
|
43
|
+
* @param relativeValue - Value in 0..1 range
|
|
44
|
+
* @param valueMode - How to interpret the value
|
|
45
|
+
* @param flatten - Circle flattening amount (0..1)
|
|
46
|
+
* @returns Angle in radians
|
|
47
|
+
*/
|
|
48
|
+
function valueToAngle(relativeValue, valueMode, flatten) {
|
|
49
|
+
const { startAngle, endAngle, totalArc } = getFlattenedCircleAngles(flatten);
|
|
50
|
+
switch (valueMode) {
|
|
51
|
+
case "range": return startAngle + relativeValue * totalArc;
|
|
52
|
+
case "bipolar": if (relativeValue <= .5) return startAngle + relativeValue / .5 * (MIDPOINT_ANGLE - startAngle);
|
|
53
|
+
else return MIDPOINT_ANGLE + (relativeValue - .5) / .5 * (endAngle - MIDPOINT_ANGLE);
|
|
54
|
+
case "unipolar": return MIDPOINT_ANGLE;
|
|
55
|
+
default: return startAngle;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get start and end angles for a value arc
|
|
60
|
+
* @param relativeValue - Value in 0..1 range
|
|
61
|
+
* @param valueMode - How to interpret the value
|
|
62
|
+
* @param flatten - Circle flattening amount (0..1)
|
|
63
|
+
* @returns Start and end angles for the arc
|
|
64
|
+
*/
|
|
65
|
+
function getValueArcAngles(relativeValue, valueMode, flatten) {
|
|
66
|
+
const { startAngle, endAngle, totalArc } = getFlattenedCircleAngles(flatten);
|
|
67
|
+
switch (valueMode) {
|
|
68
|
+
case "range": return {
|
|
69
|
+
startAngle,
|
|
70
|
+
endAngle: startAngle + relativeValue * totalArc
|
|
71
|
+
};
|
|
72
|
+
case "bipolar": if (relativeValue < .5) return {
|
|
73
|
+
startAngle: startAngle + relativeValue / .5 * (MIDPOINT_ANGLE - startAngle),
|
|
74
|
+
endAngle: MIDPOINT_ANGLE
|
|
75
|
+
};
|
|
76
|
+
else if (relativeValue > .5) return {
|
|
77
|
+
startAngle: MIDPOINT_ANGLE,
|
|
78
|
+
endAngle: MIDPOINT_ANGLE + (relativeValue - .5) / .5 * (endAngle - MIDPOINT_ANGLE)
|
|
79
|
+
};
|
|
80
|
+
else return {
|
|
81
|
+
startAngle: MIDPOINT_ANGLE,
|
|
82
|
+
endAngle: MIDPOINT_ANGLE
|
|
83
|
+
};
|
|
84
|
+
case "unipolar": {
|
|
85
|
+
const spreadAmount = relativeValue * totalArc / 2;
|
|
86
|
+
return {
|
|
87
|
+
startAngle: MIDPOINT_ANGLE - spreadAmount,
|
|
88
|
+
endAngle: MIDPOINT_ANGLE + spreadAmount
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
default: return {
|
|
92
|
+
startAngle,
|
|
93
|
+
endAngle: startAngle
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get start and end angles for an anchored arc
|
|
99
|
+
* Centered on current value position, extends equally in both directions
|
|
100
|
+
* @param relativeValue - Current value position (0..1)
|
|
101
|
+
* @param laneValue - Width of the arc (0..1, where 1 = full range)
|
|
102
|
+
* @param valueMode - How to interpret the value
|
|
103
|
+
* @param flatten - Circle flattening amount (0..1)
|
|
104
|
+
* @returns Start and end angles for the arc
|
|
105
|
+
*/
|
|
106
|
+
function getAnchoredArcAngles(relativeValue, laneValue, valueMode, flatten) {
|
|
107
|
+
const { startAngle, endAngle, totalArc } = getFlattenedCircleAngles(flatten);
|
|
108
|
+
const centerAngle = valueToAngle(relativeValue, valueMode, flatten);
|
|
109
|
+
const halfWidth = laneValue * totalArc / 2;
|
|
110
|
+
let arcStart = centerAngle - halfWidth;
|
|
111
|
+
let arcEnd = centerAngle + halfWidth;
|
|
112
|
+
if (arcStart < startAngle) arcStart = startAngle;
|
|
113
|
+
if (arcEnd > endAngle) arcEnd = endAngle;
|
|
114
|
+
if (arcStart >= arcEnd) return {
|
|
115
|
+
startAngle: centerAngle,
|
|
116
|
+
endAngle: centerAngle
|
|
117
|
+
};
|
|
118
|
+
return {
|
|
119
|
+
startAngle: arcStart,
|
|
120
|
+
endAngle: arcEnd
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Generate SVG path for an arc
|
|
125
|
+
* @param startAngle - Start angle in radians
|
|
126
|
+
* @param endAngle - End angle in radians
|
|
127
|
+
* @param radius - Arc radius
|
|
128
|
+
* @param center - Center point
|
|
129
|
+
* @returns SVG path data string
|
|
130
|
+
*/
|
|
131
|
+
function generateArcPath(startAngle, endAngle, radius, center = {
|
|
132
|
+
x: 50,
|
|
133
|
+
y: 50
|
|
134
|
+
}) {
|
|
135
|
+
if (startAngle === endAngle) return "";
|
|
136
|
+
let arcLength = endAngle - startAngle;
|
|
137
|
+
if (arcLength < 0) arcLength += PI2;
|
|
138
|
+
if (arcLength >= PI2 - .001) {
|
|
139
|
+
const adjustedEnd = startAngle + PI2 - .001;
|
|
140
|
+
const start = polarToCartesian(startAngle, radius, center);
|
|
141
|
+
const end = polarToCartesian(adjustedEnd, radius, center);
|
|
142
|
+
return `M ${start.x},${start.y} A ${radius},${radius} 0 1 1 ${end.x},${end.y}`;
|
|
143
|
+
}
|
|
144
|
+
const start = polarToCartesian(startAngle, radius, center);
|
|
145
|
+
const end = polarToCartesian(endAngle, radius, center);
|
|
146
|
+
const largeArcFlag = arcLength > Math.PI ? 1 : 0;
|
|
147
|
+
return `M ${start.x},${start.y} A ${radius},${radius} 0 ${largeArcFlag} 1 ${end.x},${end.y}`;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Generate SVG path for a full flattened circle border
|
|
151
|
+
* @param radius - Circle radius
|
|
152
|
+
* @param flatten - Flattening amount (0..1)
|
|
153
|
+
* @param center - Center point
|
|
154
|
+
* @returns SVG path data string
|
|
155
|
+
*/
|
|
156
|
+
function generateCircleBorderPath(radius, flatten, center = {
|
|
157
|
+
x: 50,
|
|
158
|
+
y: 50
|
|
159
|
+
}) {
|
|
160
|
+
const { startAngle, endAngle } = getFlattenedCircleAngles(flatten);
|
|
161
|
+
return generateArcPath(startAngle, endAngle, radius, center);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Generate SVG path data for a filled wedge (pie-slice) sector
|
|
165
|
+
* @param startAngle - Start angle in radians
|
|
166
|
+
* @param endAngle - End angle in radians
|
|
167
|
+
* @param radius - Wedge radius (same as dial radius)
|
|
168
|
+
* @param center - Center point
|
|
169
|
+
* @param clockwise - Whether to draw arc clockwise (true) or counterclockwise (false)
|
|
170
|
+
* @returns SVG path data string for filled wedge
|
|
171
|
+
*/
|
|
172
|
+
function generateWedgePath(startAngle, endAngle, radius, center = {
|
|
173
|
+
x: 50,
|
|
174
|
+
y: 50
|
|
175
|
+
}, clockwise = true) {
|
|
176
|
+
if (startAngle === endAngle) return "";
|
|
177
|
+
let arcLength = endAngle - startAngle;
|
|
178
|
+
if (arcLength < 0) arcLength += PI2;
|
|
179
|
+
if (arcLength >= PI2 - .001) {
|
|
180
|
+
const start = polarToCartesian(startAngle, radius, center);
|
|
181
|
+
const adjEnd = polarToCartesian(startAngle + PI2 - .001, radius, center);
|
|
182
|
+
const largeArcFlag = 1;
|
|
183
|
+
const sweepFlag = clockwise ? 1 : 0;
|
|
184
|
+
return `M ${center.x},${center.y} L ${start.x},${start.y} A ${radius},${radius} 0 ${largeArcFlag} ${sweepFlag} ${adjEnd.x},${adjEnd.y} Z`;
|
|
185
|
+
}
|
|
186
|
+
let actualStartAngle = startAngle;
|
|
187
|
+
let actualEndAngle = endAngle;
|
|
188
|
+
let actualClockwise = clockwise;
|
|
189
|
+
if (!clockwise && arcLength > Math.PI) {
|
|
190
|
+
actualStartAngle = endAngle;
|
|
191
|
+
actualEndAngle = startAngle;
|
|
192
|
+
actualClockwise = true;
|
|
193
|
+
arcLength = PI2 - arcLength;
|
|
194
|
+
}
|
|
195
|
+
const start = polarToCartesian(actualStartAngle, radius, center);
|
|
196
|
+
const end = polarToCartesian(actualEndAngle, radius, center);
|
|
197
|
+
const largeArcFlag = arcLength > Math.PI ? 1 : 0;
|
|
198
|
+
const sweepFlag = actualClockwise ? 1 : 0;
|
|
199
|
+
return `M ${center.x},${center.y} L ${start.x},${start.y} A ${radius},${radius} 0 ${largeArcFlag} ${sweepFlag} ${end.x},${end.y} Z`;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get wedge angles based on value mode
|
|
203
|
+
* @param relativeValue - Value in 0..1 range
|
|
204
|
+
* @param valueMode - How to interpret the value
|
|
205
|
+
* @param flatten - Circle flattening amount (0..1)
|
|
206
|
+
* @returns Object with startAngle, endAngle, and clockwise flag
|
|
207
|
+
*/
|
|
208
|
+
function getWedgeAngles(relativeValue, valueMode, flatten) {
|
|
209
|
+
const { startAngle, endAngle, totalArc } = getFlattenedCircleAngles(flatten);
|
|
210
|
+
const valueAngle = valueToAngle(relativeValue, valueMode, flatten);
|
|
211
|
+
switch (valueMode) {
|
|
212
|
+
case "range": return {
|
|
213
|
+
startAngle,
|
|
214
|
+
endAngle: valueAngle,
|
|
215
|
+
clockwise: true
|
|
216
|
+
};
|
|
217
|
+
case "bipolar": if (relativeValue < .5) return {
|
|
218
|
+
startAngle: MIDPOINT_ANGLE,
|
|
219
|
+
endAngle: valueAngle,
|
|
220
|
+
clockwise: false
|
|
221
|
+
};
|
|
222
|
+
else return {
|
|
223
|
+
startAngle: MIDPOINT_ANGLE,
|
|
224
|
+
endAngle: valueAngle,
|
|
225
|
+
clockwise: true
|
|
226
|
+
};
|
|
227
|
+
case "unipolar": {
|
|
228
|
+
const halfSpread = relativeValue * totalArc / 2;
|
|
229
|
+
return {
|
|
230
|
+
startAngle: MIDPOINT_ANGLE - halfSpread,
|
|
231
|
+
endAngle: MIDPOINT_ANGLE + halfSpread,
|
|
232
|
+
clockwise: true
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
default: return {
|
|
236
|
+
startAngle,
|
|
237
|
+
endAngle: startAngle,
|
|
238
|
+
clockwise: true
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Get position for a marker (needle or dot) at a given value
|
|
244
|
+
* @param relativeValue - Value in 0..1 range
|
|
245
|
+
* @param valueMode - How to interpret the value
|
|
246
|
+
* @param flatten - Circle flattening amount (0..1)
|
|
247
|
+
* @param radius - Circle radius
|
|
248
|
+
* @param center - Center point
|
|
249
|
+
* @returns Angle in radians and position point
|
|
250
|
+
*/
|
|
251
|
+
function getMarkerPosition(relativeValue, valueMode, flatten, radius, center = {
|
|
252
|
+
x: 50,
|
|
253
|
+
y: 50
|
|
254
|
+
}) {
|
|
255
|
+
const angle = valueToAngle(relativeValue, valueMode, flatten);
|
|
256
|
+
return {
|
|
257
|
+
angle,
|
|
258
|
+
position: polarToCartesian(angle, radius, center)
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Get position for midpoint marker (used in bipolar/unipolar modes)
|
|
263
|
+
* @param radius - Circle radius
|
|
264
|
+
* @param center - Center point
|
|
265
|
+
* @returns Position at top-center of circle
|
|
266
|
+
*/
|
|
267
|
+
function getMidpointPosition(radius, center = {
|
|
268
|
+
x: 50,
|
|
269
|
+
y: 50
|
|
270
|
+
}) {
|
|
271
|
+
return {
|
|
272
|
+
angle: MIDPOINT_ANGLE,
|
|
273
|
+
position: polarToCartesian(MIDPOINT_ANGLE, radius, center)
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Clamp a value between min and max
|
|
278
|
+
*/
|
|
279
|
+
function clamp(value, min, max) {
|
|
280
|
+
return Math.min(Math.max(value, min), max);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Scale a value from one range to another
|
|
284
|
+
*/
|
|
285
|
+
function scale(value, fromMin, fromMax, toMin, toMax) {
|
|
286
|
+
return toMin + (value - fromMin) / (fromMax - fromMin) * (toMax - toMin);
|
|
287
|
+
}
|
|
288
|
+
//#endregion
|
|
289
|
+
//#region src/radial-input/radial-input.ts
|
|
290
|
+
const CENTER = {
|
|
291
|
+
x: 50,
|
|
292
|
+
y: 50
|
|
293
|
+
};
|
|
294
|
+
let RadialInputElement = class RadialInputElement extends LitElement {
|
|
295
|
+
#_radius;
|
|
296
|
+
get radius() {
|
|
297
|
+
return this.#_radius;
|
|
298
|
+
}
|
|
299
|
+
set radius(v) {
|
|
300
|
+
this.#_radius = clamp(v, 10, 50);
|
|
301
|
+
}
|
|
302
|
+
#lanes;
|
|
303
|
+
#dragging;
|
|
304
|
+
#dragStartY;
|
|
305
|
+
#valueAtDragStart;
|
|
306
|
+
#changeDebounceTimer;
|
|
307
|
+
#isUserInteraction;
|
|
308
|
+
constructor() {
|
|
309
|
+
super();
|
|
310
|
+
this.#_radius = 45;
|
|
311
|
+
this.value = 0;
|
|
312
|
+
this.min = 0;
|
|
313
|
+
this.max = 100;
|
|
314
|
+
this.step = void 0;
|
|
315
|
+
this.valueMode = `range`;
|
|
316
|
+
this.flatten = .3;
|
|
317
|
+
this.markerStyle = `needle`;
|
|
318
|
+
this.wedge = false;
|
|
319
|
+
this.disabled = false;
|
|
320
|
+
this.#lanes = /* @__PURE__ */ new Map();
|
|
321
|
+
this.#dragging = false;
|
|
322
|
+
this.#dragStartY = 0;
|
|
323
|
+
this.#valueAtDragStart = 0;
|
|
324
|
+
this.#isUserInteraction = false;
|
|
325
|
+
this.#onPointerDown = (event) => {
|
|
326
|
+
if (this.disabled) return;
|
|
327
|
+
event.preventDefault();
|
|
328
|
+
const svg = this.renderRoot.querySelector(`svg`);
|
|
329
|
+
svg?.focus();
|
|
330
|
+
this.#dragging = true;
|
|
331
|
+
this.#dragStartY = event.clientY;
|
|
332
|
+
this.#valueAtDragStart = this.value;
|
|
333
|
+
this.toggleAttribute(`dragging`, true);
|
|
334
|
+
if (svg) svg.setPointerCapture(event.pointerId);
|
|
335
|
+
window.addEventListener(`pointermove`, this.#onPointerMove);
|
|
336
|
+
window.addEventListener(`pointerup`, this.#onPointerUp);
|
|
337
|
+
window.addEventListener(`pointercancel`, this.#onPointerUp);
|
|
338
|
+
};
|
|
339
|
+
this.#onPointerMove = (event) => {
|
|
340
|
+
if (!this.#dragging) return;
|
|
341
|
+
event.preventDefault();
|
|
342
|
+
const effectiveSensitivity = this.clientHeight * 2 * (event.shiftKey ? 10 : 1);
|
|
343
|
+
const deltaValue = (this.#dragStartY - event.clientY) / effectiveSensitivity * (this.max - this.min);
|
|
344
|
+
const relativeValue = scale(this.#valueAtDragStart + deltaValue, this.min, this.max, 0, 1);
|
|
345
|
+
this.#setValueFromRelative(clamp(relativeValue, 0, 1), true);
|
|
346
|
+
};
|
|
347
|
+
this.#onPointerUp = () => {
|
|
348
|
+
this.#dragging = false;
|
|
349
|
+
this.toggleAttribute(`dragging`, false);
|
|
350
|
+
const svg = this.renderRoot.querySelector(`svg`);
|
|
351
|
+
if (svg && `hasPointerCapture` in svg && typeof svg.hasPointerCapture === `function`) {
|
|
352
|
+
if (svg.hasPointerCapture(1)) svg.releasePointerCapture(1);
|
|
353
|
+
}
|
|
354
|
+
window.removeEventListener(`pointermove`, this.#onPointerMove);
|
|
355
|
+
window.removeEventListener(`pointerup`, this.#onPointerUp);
|
|
356
|
+
window.removeEventListener(`pointercancel`, this.#onPointerUp);
|
|
357
|
+
};
|
|
358
|
+
this.#onKeyDown = (event) => {
|
|
359
|
+
if (this.disabled) return;
|
|
360
|
+
const shiftDivisor = event.shiftKey ? 10 : 1;
|
|
361
|
+
const range = this.max - this.min;
|
|
362
|
+
const effectiveStep = resolveStep(range, this.stops, this.step) / shiftDivisor;
|
|
363
|
+
let handled = false;
|
|
364
|
+
switch (event.key) {
|
|
365
|
+
case `ArrowUp`:
|
|
366
|
+
case `ArrowRight`:
|
|
367
|
+
this.#setValueFromRelative(this.#getRelativeValue() + effectiveStep / range, true);
|
|
368
|
+
handled = true;
|
|
369
|
+
break;
|
|
370
|
+
case `ArrowDown`:
|
|
371
|
+
case `ArrowLeft`:
|
|
372
|
+
this.#setValueFromRelative(this.#getRelativeValue() - effectiveStep / range, true);
|
|
373
|
+
handled = true;
|
|
374
|
+
break;
|
|
375
|
+
case `Home`:
|
|
376
|
+
this.#setValueFromRelative(0, true);
|
|
377
|
+
handled = true;
|
|
378
|
+
break;
|
|
379
|
+
case `End`:
|
|
380
|
+
this.#setValueFromRelative(1, true);
|
|
381
|
+
handled = true;
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
if (handled) event.preventDefault();
|
|
385
|
+
};
|
|
386
|
+
this.#lanes.set(`track`, {
|
|
387
|
+
key: `track`,
|
|
388
|
+
value: 1,
|
|
389
|
+
type: `fixed`,
|
|
390
|
+
offset: 0,
|
|
391
|
+
width: .16
|
|
392
|
+
});
|
|
393
|
+
this.#lanes.set(`value`, {
|
|
394
|
+
key: `value`,
|
|
395
|
+
value: 0,
|
|
396
|
+
type: `value`,
|
|
397
|
+
offset: 0,
|
|
398
|
+
width: .24
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
addLane(key, options) {
|
|
402
|
+
const relativeValue = this.#getRelativeValue();
|
|
403
|
+
this.#lanes.set(key, {
|
|
404
|
+
key,
|
|
405
|
+
value: options?.value ?? relativeValue,
|
|
406
|
+
type: options?.type ?? `value`,
|
|
407
|
+
offset: options?.offset ?? 0,
|
|
408
|
+
width: options?.width ?? .1
|
|
409
|
+
});
|
|
410
|
+
this.requestUpdate();
|
|
411
|
+
}
|
|
412
|
+
setLaneValue(key, value) {
|
|
413
|
+
const lane = this.#lanes.get(key);
|
|
414
|
+
if (lane) {
|
|
415
|
+
lane.value = clamp(value, 0, 1);
|
|
416
|
+
this.requestUpdate();
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
removeLane(key) {
|
|
420
|
+
this.#lanes.delete(key);
|
|
421
|
+
this.requestUpdate();
|
|
422
|
+
}
|
|
423
|
+
getLanes() {
|
|
424
|
+
return new Map(this.#lanes);
|
|
425
|
+
}
|
|
426
|
+
getLane(key) {
|
|
427
|
+
return this.#lanes.get(key);
|
|
428
|
+
}
|
|
429
|
+
#getRelativeValue() {
|
|
430
|
+
return scale(this.value, this.min, this.max, 0, 1);
|
|
431
|
+
}
|
|
432
|
+
#getEffectiveMarkerStyle() {
|
|
433
|
+
if (this.valueMode === `unipolar` && this.markerStyle === `needle`) return `none`;
|
|
434
|
+
return this.markerStyle;
|
|
435
|
+
}
|
|
436
|
+
#quantise(value) {
|
|
437
|
+
if (this.stops && this.stops > 1) {
|
|
438
|
+
const step = (this.max - this.min) / this.stops;
|
|
439
|
+
return Math.round((value - this.min) / step) * step + this.min;
|
|
440
|
+
}
|
|
441
|
+
return value;
|
|
442
|
+
}
|
|
443
|
+
#setValueFromRelative(relativeValue, isUserInteraction = false) {
|
|
444
|
+
const newValue = scale(relativeValue, 0, 1, this.min, this.max);
|
|
445
|
+
const clampedValue = this.#quantise(clamp(newValue, this.min, this.max));
|
|
446
|
+
if (clampedValue === this.value) return;
|
|
447
|
+
const previousValue = this.value;
|
|
448
|
+
this.value = clampedValue;
|
|
449
|
+
this.#isUserInteraction = isUserInteraction;
|
|
450
|
+
const valueLane = this.#lanes.get(`value`);
|
|
451
|
+
if (valueLane && valueLane.type === `value`) valueLane.value = this.#getRelativeValue();
|
|
452
|
+
if (this.hasAttribute(`data-tooltip-live`)) {
|
|
453
|
+
const percentage = Math.round(this.#getRelativeValue() * 100);
|
|
454
|
+
this.setAttribute(`data-tooltip`, `${percentage}%`);
|
|
455
|
+
}
|
|
456
|
+
if (isUserInteraction) {
|
|
457
|
+
this.dispatchEvent(new CustomEvent(`input`, {
|
|
458
|
+
detail: {
|
|
459
|
+
value: this.value,
|
|
460
|
+
valueRelative: this.#getRelativeValue()
|
|
461
|
+
},
|
|
462
|
+
bubbles: true,
|
|
463
|
+
composed: true
|
|
464
|
+
}));
|
|
465
|
+
this.#scheduleChangeEvent(previousValue);
|
|
466
|
+
} else this.#fireChangeEvent(previousValue);
|
|
467
|
+
}
|
|
468
|
+
#scheduleChangeEvent(previousValue) {
|
|
469
|
+
if (this.#changeDebounceTimer !== void 0) clearTimeout(this.#changeDebounceTimer);
|
|
470
|
+
this.#changeDebounceTimer = window.setTimeout(() => {
|
|
471
|
+
this.#fireChangeEvent(previousValue);
|
|
472
|
+
this.#changeDebounceTimer = void 0;
|
|
473
|
+
}, 150);
|
|
474
|
+
}
|
|
475
|
+
#fireChangeEvent(previousValue) {
|
|
476
|
+
this.dispatchEvent(new CustomEvent(`change`, {
|
|
477
|
+
detail: {
|
|
478
|
+
value: this.value,
|
|
479
|
+
valueRelative: this.#getRelativeValue(),
|
|
480
|
+
previousValue
|
|
481
|
+
},
|
|
482
|
+
bubbles: true,
|
|
483
|
+
composed: true
|
|
484
|
+
}));
|
|
485
|
+
}
|
|
486
|
+
#onPointerDown;
|
|
487
|
+
#onPointerMove;
|
|
488
|
+
#onPointerUp;
|
|
489
|
+
#onKeyDown;
|
|
490
|
+
#renderCircleBorder() {
|
|
491
|
+
const path = generateCircleBorderPath(this.radius, this.flatten, CENTER);
|
|
492
|
+
const borderWidth = this.#getCssVar(`--dial-border-width`, 2);
|
|
493
|
+
return svg`<path class="dial-border" d="${path}" fill="none" stroke="${getComputedStyle(this).getPropertyValue(`--dial-border-color`).trim() || `var(--surface-4)`}" stroke-width="${borderWidth}" stroke-linecap="round" vector-effect="non-scaling-stroke" />`;
|
|
494
|
+
}
|
|
495
|
+
#renderCircleFill() {
|
|
496
|
+
return svg`<path class="dial-fill" d="${generateCircleBorderPath(this.radius, this.flatten, CENTER)}" fill="${getComputedStyle(this).getPropertyValue(`--dial-fill`).trim() || `transparent`}" />`;
|
|
497
|
+
}
|
|
498
|
+
#renderWedge() {
|
|
499
|
+
const { startAngle, endAngle, clockwise } = getWedgeAngles(this.#getRelativeValue(), this.valueMode, this.flatten);
|
|
500
|
+
const path = generateWedgePath(startAngle, endAngle, this.radius, CENTER, clockwise);
|
|
501
|
+
if (!path) return svg``;
|
|
502
|
+
return svg`<path class="wedge" d="${path}" />`;
|
|
503
|
+
}
|
|
504
|
+
#renderLane(lane) {
|
|
505
|
+
let arcPath = ``;
|
|
506
|
+
if (lane.type === `fixed`) arcPath = generateCircleBorderPath(this.radius - lane.offset * this.radius, this.flatten, CENTER);
|
|
507
|
+
else if (lane.type === `anchored`) {
|
|
508
|
+
const { startAngle, endAngle } = getAnchoredArcAngles(this.#getRelativeValue(), lane.value, this.valueMode, this.flatten);
|
|
509
|
+
arcPath = generateArcPath(startAngle, endAngle, this.radius - lane.offset * this.radius, CENTER);
|
|
510
|
+
} else {
|
|
511
|
+
const { startAngle, endAngle } = getValueArcAngles(lane.value, this.valueMode, this.flatten);
|
|
512
|
+
arcPath = generateArcPath(startAngle, endAngle, this.radius - lane.offset * this.radius, CENTER);
|
|
513
|
+
}
|
|
514
|
+
if (!arcPath) return svg``;
|
|
515
|
+
return svg`
|
|
516
|
+
<path
|
|
517
|
+
class="lane"
|
|
518
|
+
data-lane-key="${lane.key}"
|
|
519
|
+
part="lane lane-${lane.key}"
|
|
520
|
+
d="${arcPath}"
|
|
521
|
+
style="
|
|
522
|
+
stroke-width: calc(var(--lane-${lane.key}-width, var(--lane-width)) * ${this.radius}%);
|
|
523
|
+
stroke-linecap: round;
|
|
524
|
+
"
|
|
525
|
+
/>
|
|
526
|
+
`;
|
|
527
|
+
}
|
|
528
|
+
#getNeedlePath(angle, length, offset) {
|
|
529
|
+
const startRadius = offset * this.radius;
|
|
530
|
+
const endRadius = length * this.radius;
|
|
531
|
+
const start = {
|
|
532
|
+
x: CENTER.x + Math.cos(angle) * startRadius,
|
|
533
|
+
y: CENTER.y + Math.sin(angle) * startRadius
|
|
534
|
+
};
|
|
535
|
+
const end = {
|
|
536
|
+
x: CENTER.x + Math.cos(angle) * endRadius,
|
|
537
|
+
y: CENTER.y + Math.sin(angle) * endRadius
|
|
538
|
+
};
|
|
539
|
+
return `M ${start.x} ${start.y} L ${end.x} ${end.y}`;
|
|
540
|
+
}
|
|
541
|
+
#renderValueMarker(needlePath) {
|
|
542
|
+
const { angle, position } = getMarkerPosition(this.#getRelativeValue(), this.valueMode, this.flatten, this.radius, CENTER);
|
|
543
|
+
const markerOffset = this.#getCssVar(`--marker-offset`, 1);
|
|
544
|
+
const markerBorderWidth = this.#getCssVar(`--marker-border-width`, 0);
|
|
545
|
+
const effectiveStyle = this.#getEffectiveMarkerStyle();
|
|
546
|
+
if (effectiveStyle === `dot`) {
|
|
547
|
+
const r = this.#getCssVar(`--marker-thickness`, .15) * this.radius;
|
|
548
|
+
const dotX = CENTER.x + (position.x - CENTER.x) * markerOffset;
|
|
549
|
+
const dotY = CENTER.y + (position.y - CENTER.y) * markerOffset;
|
|
550
|
+
if (markerBorderWidth > 0) return svg`
|
|
551
|
+
<g class="value-marker" part="value-marker">
|
|
552
|
+
<use href="#dot-path" class="marker-border" />
|
|
553
|
+
<use href="#dot-path" class="marker-fill" />
|
|
554
|
+
</g>
|
|
555
|
+
`;
|
|
556
|
+
return svg`
|
|
557
|
+
<g class="value-marker" part="value-marker">
|
|
558
|
+
<circle cx="${dotX}" cy="${dotY}" r="${r}" />
|
|
559
|
+
</g>
|
|
560
|
+
`;
|
|
561
|
+
} else if (effectiveStyle === `needle`) {
|
|
562
|
+
if (markerBorderWidth > 0 && needlePath) return svg`
|
|
563
|
+
<g class="value-marker" part="value-marker">
|
|
564
|
+
<use href="#needle-path" class="marker-border" />
|
|
565
|
+
<use href="#needle-path" class="marker-fill" />
|
|
566
|
+
</g>
|
|
567
|
+
`;
|
|
568
|
+
const length = this.#getCssVar(`--marker-length`, .8);
|
|
569
|
+
const offset = this.#getCssVar(`--marker-offset`, .2);
|
|
570
|
+
return svg`
|
|
571
|
+
<g class="value-marker" part="value-marker">
|
|
572
|
+
<path d="${this.#getNeedlePath(angle, length, offset)}" />
|
|
573
|
+
</g>
|
|
574
|
+
`;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
#renderMidpointMarker() {
|
|
578
|
+
if (this.valueMode !== `bipolar` && this.valueMode !== `unipolar`) return svg``;
|
|
579
|
+
const { position } = getMidpointPosition(this.radius, CENTER);
|
|
580
|
+
if (this.markerStyle === `dot`) {
|
|
581
|
+
const size = this.#getCssVar(`--midpoint-thickness`, .08);
|
|
582
|
+
return svg`
|
|
583
|
+
<g class="midpoint-marker" part="midpoint-marker">
|
|
584
|
+
<circle
|
|
585
|
+
cx="${position.x}"
|
|
586
|
+
cy="${position.y}"
|
|
587
|
+
r="${size * this.radius}"
|
|
588
|
+
/>
|
|
589
|
+
</g>
|
|
590
|
+
`;
|
|
591
|
+
} else {
|
|
592
|
+
const length = this.#getCssVar(`--midpoint-length`, .15);
|
|
593
|
+
const offset = this.#getCssVar(`--midpoint-offset`, .85);
|
|
594
|
+
const angle = -Math.PI / 2;
|
|
595
|
+
const startRadius = offset * this.radius;
|
|
596
|
+
const endRadius = (offset + length) * this.radius;
|
|
597
|
+
const start = {
|
|
598
|
+
x: CENTER.x + Math.cos(angle) * startRadius,
|
|
599
|
+
y: CENTER.y + Math.sin(angle) * startRadius
|
|
600
|
+
};
|
|
601
|
+
const end = {
|
|
602
|
+
x: CENTER.x + Math.cos(angle) * endRadius,
|
|
603
|
+
y: CENTER.y + Math.sin(angle) * endRadius
|
|
604
|
+
};
|
|
605
|
+
return svg`
|
|
606
|
+
<g class="midpoint-marker" part="midpoint-marker">
|
|
607
|
+
<line
|
|
608
|
+
x1="${start.x}"
|
|
609
|
+
y1="${start.y}"
|
|
610
|
+
x2="${end.x}"
|
|
611
|
+
y2="${end.y}"
|
|
612
|
+
/>
|
|
613
|
+
</g>
|
|
614
|
+
`;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
#getCssVar(name, defaultValue) {
|
|
618
|
+
const style = getComputedStyle(this);
|
|
619
|
+
const val = style.getPropertyValue(name).trim();
|
|
620
|
+
if (!val) return defaultValue;
|
|
621
|
+
if (val.includes(`calc(`)) {
|
|
622
|
+
const valueRelative = style.getPropertyValue(`--value-relative`).trim();
|
|
623
|
+
if (!valueRelative) {
|
|
624
|
+
const parsed = Number.parseFloat(val.replace(/[^0-9.-]/g, ``));
|
|
625
|
+
return Number.isNaN(parsed) ? defaultValue : parsed;
|
|
626
|
+
}
|
|
627
|
+
const evalStr = val.replace(/var\(--value-relative\)/g, valueRelative);
|
|
628
|
+
try {
|
|
629
|
+
const result = new Function(`return ${evalStr.replace(/calc\s*\(([^)]+)\)/g, `$1`)}`)();
|
|
630
|
+
return typeof result === `number` && !Number.isNaN(result) ? result : defaultValue;
|
|
631
|
+
} catch (e) {
|
|
632
|
+
const parsed = Number.parseFloat(val.replace(/[^0-9.-]/g, ``));
|
|
633
|
+
return Number.isNaN(parsed) ? defaultValue : parsed;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
const parsed = Number.parseFloat(val);
|
|
637
|
+
return Number.isNaN(parsed) ? defaultValue : parsed;
|
|
638
|
+
}
|
|
639
|
+
willUpdate(changed) {
|
|
640
|
+
super.willUpdate(changed);
|
|
641
|
+
if (changed.has(`value`) || !this.hasUpdated) {
|
|
642
|
+
const valueLane = this.#lanes.get(`value`);
|
|
643
|
+
if (valueLane && valueLane.type === `value`) valueLane.value = this.#getRelativeValue();
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
render() {
|
|
647
|
+
const lanes = Array.from(this.#lanes.values());
|
|
648
|
+
const { angle, position } = getMarkerPosition(this.#getRelativeValue(), this.valueMode, this.flatten, this.radius, CENTER);
|
|
649
|
+
const needleLength = this.#getCssVar(`--marker-length`, .8);
|
|
650
|
+
const needleOffset = this.#getCssVar(`--marker-offset`, .2);
|
|
651
|
+
const markerBorderWidth = this.#getCssVar(`--marker-border-width`, 0);
|
|
652
|
+
const needlePath = markerBorderWidth > 0 ? this.#getNeedlePath(angle, needleLength, needleOffset) : void 0;
|
|
653
|
+
const dotR = this.#getCssVar(`--marker-thickness`, .15) * this.radius;
|
|
654
|
+
const defs = [];
|
|
655
|
+
if (needlePath) defs.push(svg`<path id="needle-path" d="${needlePath}" />`);
|
|
656
|
+
if (markerBorderWidth > 0) defs.push(svg`<circle id="dot-path" cx="${position.x}" cy="${position.y}" r="${dotR}" />`);
|
|
657
|
+
return html`
|
|
658
|
+
<svg
|
|
659
|
+
viewBox="0 0 100 100"
|
|
660
|
+
preserveAspectRatio="xMidYMid meet"
|
|
661
|
+
tabindex="${this.disabled ? -1 : 0}"
|
|
662
|
+
@pointerdown="${this.#onPointerDown}"
|
|
663
|
+
@keydown="${this.#onKeyDown}"
|
|
664
|
+
style="cursor: ${this.#dragging ? `ns-resize` : `grab`}"
|
|
665
|
+
>
|
|
666
|
+
${defs.length > 0 ? svg`<defs>${defs}</defs>` : ``}
|
|
667
|
+
${this.#renderCircleFill()}
|
|
668
|
+
${this.wedge ? this.#renderWedge() : ``}
|
|
669
|
+
${this.#renderCircleBorder()}
|
|
670
|
+
${lanes.map((lane) => this.#renderLane(lane))}
|
|
671
|
+
${this.#renderMidpointMarker()}
|
|
672
|
+
${this.#renderValueMarker(needlePath)}
|
|
673
|
+
</svg>
|
|
674
|
+
`;
|
|
675
|
+
}
|
|
676
|
+
updated(changed) {
|
|
677
|
+
super.updated(changed);
|
|
678
|
+
if (changed.has(`radius`)) this.style.setProperty(`--radius`, `${this.radius}%`);
|
|
679
|
+
this.style.setProperty(`--value-relative`, this.#getRelativeValue().toString());
|
|
680
|
+
if (changed.has(`flatten`)) {
|
|
681
|
+
const markerThickness = this.#getCssVar(`--marker-thickness`, .15);
|
|
682
|
+
const radius = this.#getCssVar(`--radius`, 45);
|
|
683
|
+
const markerPadding = Math.round(markerThickness * radius) + 5;
|
|
684
|
+
const viewBoxHeight = Math.round(100 * (1 - this.flatten)) + markerPadding;
|
|
685
|
+
this.style.setProperty(`--dial-height`, `${viewBoxHeight}px`);
|
|
686
|
+
const svg = this.renderRoot.querySelector(`svg`);
|
|
687
|
+
if (svg) svg.setAttribute(`viewBox`, `0 0 100 ${viewBoxHeight}`);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
disconnectedCallback() {
|
|
691
|
+
super.disconnectedCallback();
|
|
692
|
+
if (this.#changeDebounceTimer !== void 0) clearTimeout(this.#changeDebounceTimer);
|
|
693
|
+
this.#onPointerUp();
|
|
694
|
+
}
|
|
695
|
+
firstUpdated() {
|
|
696
|
+
const markerThickness = this.#getCssVar(`--marker-thickness`, .15);
|
|
697
|
+
const radius = this.#getCssVar(`--radius`, 45);
|
|
698
|
+
const markerPadding = Math.round(markerThickness * radius);
|
|
699
|
+
const viewBoxHeight = Math.round(100 * (1 - this.flatten)) + markerPadding;
|
|
700
|
+
this.style.setProperty(`--dial-height`, `${viewBoxHeight}px`);
|
|
701
|
+
const svg = this.renderRoot.querySelector(`svg`);
|
|
702
|
+
if (svg) svg.setAttribute(`viewBox`, `0 0 100 ${viewBoxHeight}`);
|
|
703
|
+
}
|
|
704
|
+
static {
|
|
705
|
+
this.styles = [prominenceStyles, css`
|
|
706
|
+
:host {
|
|
707
|
+
display: inline-block;
|
|
708
|
+
width: 100px;
|
|
709
|
+
height: var(--dial-height, 100px);
|
|
710
|
+
touch-action: none;
|
|
711
|
+
user-select: none;
|
|
712
|
+
tabindex: 0;
|
|
713
|
+
|
|
714
|
+
/* Dynamic value - set by JS */
|
|
715
|
+
--value-relative: 0;
|
|
716
|
+
|
|
717
|
+
/* Lane widths (used in stroke-width calculations) */
|
|
718
|
+
--lane-width: 0.16;
|
|
719
|
+
--lane-track-width: 0.08;
|
|
720
|
+
--lane-value-width: 0.12;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
:host([disabled]) {
|
|
724
|
+
cursor: not-allowed;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
svg {
|
|
728
|
+
width: 100%;
|
|
729
|
+
height: 100%;
|
|
730
|
+
outline: none;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
svg:active {
|
|
734
|
+
cursor: grabbing;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
svg:focus-visible {
|
|
738
|
+
outline: var(--radial-input-svg-focus-outline, 2px solid var(--accent));
|
|
739
|
+
outline-offset: var(--radial-input-svg-focus-outline-offset, 2px);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.dial-border {
|
|
743
|
+
fill: none;
|
|
744
|
+
stroke: var(--dial-border-color, var(--surface-4));
|
|
745
|
+
stroke-width: var(--dial-border-width, 2px);
|
|
746
|
+
stroke-linecap: round;
|
|
747
|
+
vector-effect: non-scaling-stroke;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
.dial-fill {
|
|
751
|
+
fill: var(--dial-fill, transparent);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
.wedge {
|
|
755
|
+
fill: var(--wedge-fill, var(--accent));
|
|
756
|
+
fill-opacity: var(--wedge-fill-opacity, 0.25);
|
|
757
|
+
stroke: var(--wedge-border-color, var(--accent));
|
|
758
|
+
stroke-width: var(--wedge-border-width, 0);
|
|
759
|
+
stroke-opacity: var(--wedge-border-opacity, 1);
|
|
760
|
+
vector-effect: non-scaling-stroke;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
.lane {
|
|
764
|
+
fill: none;
|
|
765
|
+
stroke-linecap: round;
|
|
766
|
+
stroke-dasharray: var(--lane-dasharray, none);
|
|
767
|
+
stroke-dashoffset: var(--lane-dashoffset, 0);
|
|
768
|
+
vector-effect: non-scaling-stroke;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
.lane[data-lane-key='track'] {
|
|
772
|
+
stroke: var(--lane-track-color, var(--surface-4));
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
.lane[data-lane-key='value'] {
|
|
776
|
+
stroke: var(--lane-value-color, var(--accent));
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
.lane:not([data-lane-key='track']):not([data-lane-key='value']) {
|
|
780
|
+
stroke: var(--lane-color, var(--accent));
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
.value-marker path,
|
|
784
|
+
.value-marker .marker-fill {
|
|
785
|
+
stroke: var(--marker-color, var(--accent));
|
|
786
|
+
stroke-width: calc(var(--marker-thickness, 0.15) * var(--radius, 45%));
|
|
787
|
+
stroke-linecap: round;
|
|
788
|
+
stroke-dasharray: var(--marker-dasharray, none);
|
|
789
|
+
stroke-dashoffset: var(--marker-dashoffset, 0);
|
|
790
|
+
vector-effect: non-scaling-stroke;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
.value-marker .marker-border {
|
|
794
|
+
stroke: var(--marker-border-color, transparent);
|
|
795
|
+
stroke-width: calc((var(--marker-thickness, 0.15) + var(--marker-border-width, 0) * 2) * var(--radius, 45%));
|
|
796
|
+
stroke-linecap: round;
|
|
797
|
+
vector-effect: non-scaling-stroke;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
.value-marker .marker-border {
|
|
801
|
+
fill: none;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.value-marker .marker-fill,
|
|
805
|
+
.value-marker circle {
|
|
806
|
+
fill: var(--marker-color, var(--accent));
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
.midpoint-marker line {
|
|
810
|
+
stroke: var(--midpoint-color, var(--surface-muted-text));
|
|
811
|
+
stroke-width: var(--midpoint-thickness, 1px);
|
|
812
|
+
stroke-linecap: round;
|
|
813
|
+
vector-effect: non-scaling-stroke;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
.midpoint-marker circle {
|
|
817
|
+
fill: var(--midpoint-color, var(--surface-muted-text));
|
|
818
|
+
stroke: var(--midpoint-border-color, transparent);
|
|
819
|
+
stroke-width: var(--midpoint-border-width, 0);
|
|
820
|
+
vector-effect: non-scaling-stroke;
|
|
821
|
+
}
|
|
822
|
+
`];
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
__decorate([property({ type: Number })], RadialInputElement.prototype, "radius", null);
|
|
826
|
+
__decorate([property({ type: Number })], RadialInputElement.prototype, "value", void 0);
|
|
827
|
+
__decorate([property({ type: Number })], RadialInputElement.prototype, "min", void 0);
|
|
828
|
+
__decorate([property({ type: Number })], RadialInputElement.prototype, "max", void 0);
|
|
829
|
+
__decorate([property({ type: Number })], RadialInputElement.prototype, "step", void 0);
|
|
830
|
+
__decorate([property({ type: Number })], RadialInputElement.prototype, "stops", void 0);
|
|
831
|
+
__decorate([property({
|
|
832
|
+
type: String,
|
|
833
|
+
attribute: `value-mode`
|
|
834
|
+
})], RadialInputElement.prototype, "valueMode", void 0);
|
|
835
|
+
__decorate([property({ type: Number })], RadialInputElement.prototype, "flatten", void 0);
|
|
836
|
+
__decorate([property({
|
|
837
|
+
type: String,
|
|
838
|
+
attribute: `marker-style`
|
|
839
|
+
})], RadialInputElement.prototype, "markerStyle", void 0);
|
|
840
|
+
__decorate([property({ type: Boolean })], RadialInputElement.prototype, "wedge", void 0);
|
|
841
|
+
__decorate([property({
|
|
842
|
+
type: Boolean,
|
|
843
|
+
reflect: true
|
|
844
|
+
})], RadialInputElement.prototype, "disabled", void 0);
|
|
845
|
+
RadialInputElement = __decorate([customElement(`ixfx-radial-input`)], RadialInputElement);
|
|
846
|
+
//#endregion
|
|
847
|
+
export { RadialInputElement as t };
|
|
848
|
+
|
|
849
|
+
//# sourceMappingURL=radial-input-CNJ8asY2.js.map
|