@techfides/ui-library-core 0.5.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.
- package/LICENSE +21 -0
- package/README.md +10 -0
- package/dist/aria.d.ts +4 -0
- package/dist/aria.js +12 -0
- package/dist/charts/animation.js +12 -0
- package/dist/charts/bars.d.ts +21 -0
- package/dist/charts/bars.js +59 -0
- package/dist/charts/groupedBars.d.ts +19 -0
- package/dist/charts/groupedBars.js +80 -0
- package/dist/charts/paint.js +24 -0
- package/dist/charts/spark.d.ts +16 -0
- package/dist/charts/spark.js +157 -0
- package/dist/charts/tooltip.js +39 -0
- package/dist/cookie.d.ts +8 -0
- package/dist/cookie.js +31 -0
- package/dist/czech.d.ts +5 -0
- package/dist/czech.js +98 -0
- package/dist/field.d.ts +11 -0
- package/dist/field.js +14 -0
- package/dist/hotkey.d.ts +2 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +15 -0
- package/dist/indicator.d.ts +10 -0
- package/dist/indicator.js +28 -0
- package/dist/measure.d.ts +4 -0
- package/dist/measure.js +12 -0
- package/dist/tally.d.ts +16 -0
- package/dist/tally.js +73 -0
- package/dist/tokens.d.ts +5 -0
- package/dist/tokens.js +15 -0
- package/dist/toneIcons.d.ts +6 -0
- package/dist/toneIcons.js +9 -0
- package/dist/travel.d.ts +14 -0
- package/dist/travel.js +37 -0
- package/dist/words.d.ts +115 -0
- package/dist/words.js +94 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TechFides
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# @techfides/ui-library-core
|
|
2
|
+
|
|
3
|
+
The framework-free logic of the TechFides UI library: the words every component says on its own
|
|
4
|
+
behalf and the languages that translate them, the number tally that counts a figure up, the
|
|
5
|
+
chart option builders, field state, and the DOM maths shared by every binding.
|
|
6
|
+
|
|
7
|
+
You do not install this directly. `@techfides/ui-library-vue` depends on it and brings it along;
|
|
8
|
+
a future React binding will do the same, so the two bindings cannot disagree on behaviour.
|
|
9
|
+
|
|
10
|
+
ESM only, Node 24 or newer. MIT.
|
package/dist/aria.d.ts
ADDED
package/dist/aria.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/charts/animation.ts
|
|
2
|
+
const CHART_EASING = "cubicOut";
|
|
3
|
+
const chartAnimation = (durationMs) => ({
|
|
4
|
+
animation: true,
|
|
5
|
+
animationDuration: durationMs,
|
|
6
|
+
animationDurationUpdate: durationMs,
|
|
7
|
+
animationEasing: CHART_EASING,
|
|
8
|
+
animationEasingUpdate: CHART_EASING
|
|
9
|
+
});
|
|
10
|
+
const chartStagger = (stepMs) => (index) => index * stepMs;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { CHART_EASING, chartAnimation, chartStagger };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { EChartsOption } from "echarts";
|
|
2
|
+
//#region src/charts/bars.d.ts
|
|
3
|
+
interface BarsAccent {
|
|
4
|
+
hi: string;
|
|
5
|
+
surface: string;
|
|
6
|
+
}
|
|
7
|
+
interface BarsPoint {
|
|
8
|
+
label: string;
|
|
9
|
+
value: number | null;
|
|
10
|
+
}
|
|
11
|
+
interface BarsOptionInput {
|
|
12
|
+
accent: BarsAccent;
|
|
13
|
+
durationMs: number;
|
|
14
|
+
labelColor: string;
|
|
15
|
+
radius: number;
|
|
16
|
+
stateDurationMs: number;
|
|
17
|
+
values: readonly BarsPoint[];
|
|
18
|
+
}
|
|
19
|
+
declare const barsOption: (input: BarsOptionInput) => EChartsOption;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { type BarsAccent, type BarsOptionInput, type BarsPoint, barsOption };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { CHART_EASING, chartAnimation, chartStagger } from "./animation.js";
|
|
2
|
+
import { verticalGradient } from "./paint.js";
|
|
3
|
+
import { chartTooltip, formatCallbackValue } from "./tooltip.js";
|
|
4
|
+
//#region src/charts/bars.ts
|
|
5
|
+
const GRID = {
|
|
6
|
+
bottom: 22,
|
|
7
|
+
left: 4,
|
|
8
|
+
right: 4,
|
|
9
|
+
top: 8
|
|
10
|
+
};
|
|
11
|
+
const BAR_CATEGORY_GAP = "35%";
|
|
12
|
+
const LABEL_FONT_SIZE = 11;
|
|
13
|
+
const STAGGER_MS = 40;
|
|
14
|
+
const EMPTY_LENGTH = 0;
|
|
15
|
+
const FIRST_INDEX = 0;
|
|
16
|
+
const barPointFormatter = (params) => {
|
|
17
|
+
const point = params[FIRST_INDEX];
|
|
18
|
+
if (!point) return "";
|
|
19
|
+
return `${point.name}: ${formatCallbackValue(point.value)}`;
|
|
20
|
+
};
|
|
21
|
+
const barsOption = (input) => {
|
|
22
|
+
if (input.values.length === EMPTY_LENGTH) return { series: [] };
|
|
23
|
+
return {
|
|
24
|
+
...chartAnimation(input.durationMs),
|
|
25
|
+
grid: GRID,
|
|
26
|
+
series: [{
|
|
27
|
+
animationDelay: chartStagger(STAGGER_MS),
|
|
28
|
+
barCategoryGap: BAR_CATEGORY_GAP,
|
|
29
|
+
data: input.values.map((point) => point.value),
|
|
30
|
+
emphasis: { disabled: true },
|
|
31
|
+
itemStyle: {
|
|
32
|
+
borderRadius: input.radius,
|
|
33
|
+
color: verticalGradient(input.accent.hi, input.accent.surface)
|
|
34
|
+
},
|
|
35
|
+
stateAnimation: {
|
|
36
|
+
duration: input.stateDurationMs,
|
|
37
|
+
easing: CHART_EASING
|
|
38
|
+
},
|
|
39
|
+
type: "bar"
|
|
40
|
+
}],
|
|
41
|
+
tooltip: chartTooltip(barPointFormatter),
|
|
42
|
+
xAxis: {
|
|
43
|
+
axisLabel: {
|
|
44
|
+
color: input.labelColor,
|
|
45
|
+
fontSize: LABEL_FONT_SIZE
|
|
46
|
+
},
|
|
47
|
+
axisLine: { show: false },
|
|
48
|
+
axisTick: { show: false },
|
|
49
|
+
data: input.values.map((point) => point.label),
|
|
50
|
+
type: "category"
|
|
51
|
+
},
|
|
52
|
+
yAxis: {
|
|
53
|
+
show: false,
|
|
54
|
+
type: "value"
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { barsOption };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { EChartsOption } from "echarts";
|
|
2
|
+
//#region src/charts/groupedBars.d.ts
|
|
3
|
+
interface GroupedBarsSeries {
|
|
4
|
+
color: string;
|
|
5
|
+
name: string;
|
|
6
|
+
values: readonly (number | null)[];
|
|
7
|
+
}
|
|
8
|
+
interface GroupedBarsOptionInput {
|
|
9
|
+
categories: readonly string[];
|
|
10
|
+
durationMs: number;
|
|
11
|
+
labelColor: string;
|
|
12
|
+
radius: number;
|
|
13
|
+
series: readonly GroupedBarsSeries[];
|
|
14
|
+
stateDurationMs: number;
|
|
15
|
+
valueFormat?: (value: number) => string;
|
|
16
|
+
}
|
|
17
|
+
declare const groupedBarsOption: (input: GroupedBarsOptionInput) => EChartsOption;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { type GroupedBarsOptionInput, type GroupedBarsSeries, groupedBarsOption };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { CHART_EASING, chartAnimation } from "./animation.js";
|
|
2
|
+
import { chartTooltip, formatCallbackValue } from "./tooltip.js";
|
|
3
|
+
//#region src/charts/groupedBars.ts
|
|
4
|
+
const GRID = {
|
|
5
|
+
bottom: 22,
|
|
6
|
+
left: 4,
|
|
7
|
+
right: 4,
|
|
8
|
+
top: 8
|
|
9
|
+
};
|
|
10
|
+
const BAR_CATEGORY_GAP = "35%";
|
|
11
|
+
const LABEL_FONT_SIZE = 11;
|
|
12
|
+
const EMPTY_LENGTH = 0;
|
|
13
|
+
const FIRST_INDEX = 0;
|
|
14
|
+
const DOT_CLASS = "inline-block size-2 flex-none rounded-tf-pill";
|
|
15
|
+
const ROW_CLASS = "flex items-center justify-between gap-3";
|
|
16
|
+
const NAME_CLASS = "flex items-center gap-1.5";
|
|
17
|
+
const VALUE_CLASS = "font-semibold tabular-nums";
|
|
18
|
+
const formatValue = (value, valueFormat) => {
|
|
19
|
+
if (typeof value === "number") return valueFormat(value);
|
|
20
|
+
return formatCallbackValue(value);
|
|
21
|
+
};
|
|
22
|
+
const NO_COLOR = "";
|
|
23
|
+
const colorOf = (point) => {
|
|
24
|
+
if (typeof point.color === "string") return point.color;
|
|
25
|
+
return NO_COLOR;
|
|
26
|
+
};
|
|
27
|
+
const groupedBarRow = (point, valueFormat) => {
|
|
28
|
+
const color = colorOf(point);
|
|
29
|
+
const name = formatCallbackValue(point.seriesName);
|
|
30
|
+
return `<div class="${ROW_CLASS}"><span class="${NAME_CLASS}"><span aria-hidden="true" class="${DOT_CLASS}" style="background:${color}"></span>${name}</span><span class="${VALUE_CLASS}">${formatValue(point.value, valueFormat)}</span></div>`;
|
|
31
|
+
};
|
|
32
|
+
const groupedBarsFormatter = (valueFormat) => (params) => {
|
|
33
|
+
const first = params[FIRST_INDEX];
|
|
34
|
+
if (!first) return "";
|
|
35
|
+
return `<div class="flex flex-col gap-1"><span class="font-semibold">${formatCallbackValue(first.name)}</span>${params.map((point) => groupedBarRow(point, valueFormat)).join("")}</div>`;
|
|
36
|
+
};
|
|
37
|
+
const IDENTITY_FORMAT = String;
|
|
38
|
+
const AXIS_SHADOW_COLOR = "rgb(255 255 255 / 9%)";
|
|
39
|
+
const groupedBarsOption = (input) => {
|
|
40
|
+
if (input.categories.length === EMPTY_LENGTH) return { series: [] };
|
|
41
|
+
const valueFormat = input.valueFormat ?? IDENTITY_FORMAT;
|
|
42
|
+
return {
|
|
43
|
+
...chartAnimation(input.durationMs),
|
|
44
|
+
grid: GRID,
|
|
45
|
+
series: input.series.map((series) => ({
|
|
46
|
+
barCategoryGap: BAR_CATEGORY_GAP,
|
|
47
|
+
data: [...series.values],
|
|
48
|
+
itemStyle: {
|
|
49
|
+
borderRadius: input.radius,
|
|
50
|
+
color: series.color
|
|
51
|
+
},
|
|
52
|
+
name: series.name,
|
|
53
|
+
stateAnimation: {
|
|
54
|
+
duration: input.stateDurationMs,
|
|
55
|
+
easing: CHART_EASING
|
|
56
|
+
},
|
|
57
|
+
type: "bar"
|
|
58
|
+
})),
|
|
59
|
+
tooltip: chartTooltip(groupedBarsFormatter(valueFormat), "axis", {
|
|
60
|
+
shadowStyle: { color: AXIS_SHADOW_COLOR },
|
|
61
|
+
type: "shadow"
|
|
62
|
+
}),
|
|
63
|
+
xAxis: {
|
|
64
|
+
axisLabel: {
|
|
65
|
+
color: input.labelColor,
|
|
66
|
+
fontSize: LABEL_FONT_SIZE
|
|
67
|
+
},
|
|
68
|
+
axisLine: { show: false },
|
|
69
|
+
axisTick: { show: false },
|
|
70
|
+
data: [...input.categories],
|
|
71
|
+
type: "category"
|
|
72
|
+
},
|
|
73
|
+
yAxis: {
|
|
74
|
+
show: false,
|
|
75
|
+
type: "value"
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
export { groupedBarsOption };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/charts/paint.ts
|
|
2
|
+
const TOP = 0;
|
|
3
|
+
const BOTTOM = 1;
|
|
4
|
+
const LEFT = 0;
|
|
5
|
+
const START = 0;
|
|
6
|
+
const END = 1;
|
|
7
|
+
const verticalGradient = (from, to) => ({
|
|
8
|
+
colorStops: [{
|
|
9
|
+
color: from,
|
|
10
|
+
offset: START
|
|
11
|
+
}, {
|
|
12
|
+
color: to,
|
|
13
|
+
offset: END
|
|
14
|
+
}],
|
|
15
|
+
global: false,
|
|
16
|
+
type: "linear",
|
|
17
|
+
x: LEFT,
|
|
18
|
+
x2: LEFT,
|
|
19
|
+
y: TOP,
|
|
20
|
+
y2: BOTTOM
|
|
21
|
+
});
|
|
22
|
+
const TRANSPARENT = "rgba(0, 0, 0, 0)";
|
|
23
|
+
//#endregion
|
|
24
|
+
export { TRANSPARENT, verticalGradient };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BarsAccent } from "./bars.js";
|
|
2
|
+
import { EChartsOption } from "echarts";
|
|
3
|
+
import { StatSparkShape } from "@techfides/ui-library-design";
|
|
4
|
+
//#region src/charts/spark.d.ts
|
|
5
|
+
type SparkAccent = BarsAccent;
|
|
6
|
+
interface SparkOptionInput {
|
|
7
|
+
accent: SparkAccent;
|
|
8
|
+
durationMs: number;
|
|
9
|
+
stateDurationMs: number;
|
|
10
|
+
radius: number;
|
|
11
|
+
shape: StatSparkShape;
|
|
12
|
+
values: readonly number[];
|
|
13
|
+
}
|
|
14
|
+
declare const sparkOption: (input: SparkOptionInput) => EChartsOption;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { type SparkAccent, type SparkOptionInput, sparkOption };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { CHART_EASING, chartAnimation, chartStagger } from "./animation.js";
|
|
2
|
+
import { TRANSPARENT, verticalGradient } from "./paint.js";
|
|
3
|
+
import { chartTooltip } from "./tooltip.js";
|
|
4
|
+
//#region src/charts/spark.ts
|
|
5
|
+
const LINE_WIDTH = 2;
|
|
6
|
+
const MARKER_SIZE = 5;
|
|
7
|
+
const MIN_SPAN = 1;
|
|
8
|
+
const EMPTY_LENGTH = 0;
|
|
9
|
+
const LAST_INDEX_OFFSET = 1;
|
|
10
|
+
const NO_GAP = 0;
|
|
11
|
+
const LINE_BOUNDARY_GAP = [NO_GAP, NO_GAP];
|
|
12
|
+
const LINE_GRID = {
|
|
13
|
+
bottom: 4,
|
|
14
|
+
left: 4,
|
|
15
|
+
right: 4,
|
|
16
|
+
top: 4
|
|
17
|
+
};
|
|
18
|
+
const BAR_GRID = {
|
|
19
|
+
bottom: 0,
|
|
20
|
+
left: 0,
|
|
21
|
+
right: 0,
|
|
22
|
+
top: 0
|
|
23
|
+
};
|
|
24
|
+
const BAR_CATEGORY_GAP = "25%";
|
|
25
|
+
const MIN_HEIGHT_RATIO = .15;
|
|
26
|
+
const BAR_AXIS_MAX = 1;
|
|
27
|
+
const BAR_AXIS_MIN = 0;
|
|
28
|
+
const AREA_OPACITY = .32;
|
|
29
|
+
const STAGGER_MS = 30;
|
|
30
|
+
const lastIndexOf = (values) => values.length - LAST_INDEX_OFFSET;
|
|
31
|
+
const NO_VALUE = 0;
|
|
32
|
+
const FIRST_INDEX = 0;
|
|
33
|
+
const pointFormatter = (values) => (params) => {
|
|
34
|
+
const point = params[FIRST_INDEX];
|
|
35
|
+
if (!point || typeof point.dataIndex !== "number") return String(NO_VALUE);
|
|
36
|
+
return String(values[point.dataIndex] ?? NO_VALUE);
|
|
37
|
+
};
|
|
38
|
+
const yRange = (values) => {
|
|
39
|
+
const min = Math.min(...values);
|
|
40
|
+
const max = Math.max(...values);
|
|
41
|
+
if (max === min) return {
|
|
42
|
+
max: min + MIN_SPAN,
|
|
43
|
+
min
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
max,
|
|
47
|
+
min
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
const lineOption = (input) => {
|
|
51
|
+
const last = lastIndexOf(input.values);
|
|
52
|
+
const range = yRange(input.values);
|
|
53
|
+
const lastValue = input.values[last] ?? range.min;
|
|
54
|
+
return {
|
|
55
|
+
...chartAnimation(input.durationMs),
|
|
56
|
+
grid: LINE_GRID,
|
|
57
|
+
series: [{
|
|
58
|
+
areaStyle: {
|
|
59
|
+
color: verticalGradient(input.accent.hi, TRANSPARENT),
|
|
60
|
+
opacity: AREA_OPACITY
|
|
61
|
+
},
|
|
62
|
+
data: input.values.map((value, index) => [index, value]),
|
|
63
|
+
emphasis: { disabled: true },
|
|
64
|
+
lineStyle: {
|
|
65
|
+
cap: "round",
|
|
66
|
+
color: input.accent.surface,
|
|
67
|
+
join: "round",
|
|
68
|
+
width: LINE_WIDTH
|
|
69
|
+
},
|
|
70
|
+
markPoint: {
|
|
71
|
+
animation: true,
|
|
72
|
+
data: [{
|
|
73
|
+
coord: [last, lastValue],
|
|
74
|
+
name: ""
|
|
75
|
+
}],
|
|
76
|
+
itemStyle: { color: input.accent.hi },
|
|
77
|
+
label: { show: false },
|
|
78
|
+
symbol: "circle",
|
|
79
|
+
symbolSize: MARKER_SIZE
|
|
80
|
+
},
|
|
81
|
+
showSymbol: false,
|
|
82
|
+
stateAnimation: {
|
|
83
|
+
duration: input.stateDurationMs,
|
|
84
|
+
easing: CHART_EASING
|
|
85
|
+
},
|
|
86
|
+
symbolSize: MARKER_SIZE,
|
|
87
|
+
type: "line"
|
|
88
|
+
}],
|
|
89
|
+
tooltip: chartTooltip(pointFormatter(input.values), "axis"),
|
|
90
|
+
xAxis: {
|
|
91
|
+
boundaryGap: LINE_BOUNDARY_GAP,
|
|
92
|
+
max: last,
|
|
93
|
+
min: 0,
|
|
94
|
+
show: false,
|
|
95
|
+
type: "value"
|
|
96
|
+
},
|
|
97
|
+
yAxis: {
|
|
98
|
+
max: range.max,
|
|
99
|
+
min: range.min,
|
|
100
|
+
show: false,
|
|
101
|
+
type: "value"
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
const barHeightRatio = (value, range) => {
|
|
106
|
+
const ratio = (value - range.min) / (range.max - range.min);
|
|
107
|
+
return Math.max(ratio, MIN_HEIGHT_RATIO);
|
|
108
|
+
};
|
|
109
|
+
const barOption = (input) => {
|
|
110
|
+
const last = lastIndexOf(input.values);
|
|
111
|
+
const range = yRange(input.values);
|
|
112
|
+
return {
|
|
113
|
+
...chartAnimation(input.durationMs),
|
|
114
|
+
grid: BAR_GRID,
|
|
115
|
+
series: [{
|
|
116
|
+
animationDelay: chartStagger(STAGGER_MS),
|
|
117
|
+
barCategoryGap: BAR_CATEGORY_GAP,
|
|
118
|
+
data: input.values.map((value, index) => {
|
|
119
|
+
const height = barHeightRatio(value, range);
|
|
120
|
+
if (index === last) return {
|
|
121
|
+
itemStyle: { color: input.accent.hi },
|
|
122
|
+
value: height
|
|
123
|
+
};
|
|
124
|
+
return height;
|
|
125
|
+
}),
|
|
126
|
+
emphasis: { disabled: true },
|
|
127
|
+
itemStyle: {
|
|
128
|
+
borderRadius: input.radius,
|
|
129
|
+
color: verticalGradient(input.accent.hi, input.accent.surface)
|
|
130
|
+
},
|
|
131
|
+
stateAnimation: {
|
|
132
|
+
duration: input.stateDurationMs,
|
|
133
|
+
easing: CHART_EASING
|
|
134
|
+
},
|
|
135
|
+
type: "bar"
|
|
136
|
+
}],
|
|
137
|
+
tooltip: chartTooltip(pointFormatter(input.values)),
|
|
138
|
+
xAxis: {
|
|
139
|
+
data: input.values.map((_value, index) => String(index)),
|
|
140
|
+
show: false,
|
|
141
|
+
type: "category"
|
|
142
|
+
},
|
|
143
|
+
yAxis: {
|
|
144
|
+
max: BAR_AXIS_MAX,
|
|
145
|
+
min: BAR_AXIS_MIN,
|
|
146
|
+
show: false,
|
|
147
|
+
type: "value"
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
const sparkOption = (input) => {
|
|
152
|
+
if (input.values.length === EMPTY_LENGTH) return { series: [] };
|
|
153
|
+
if (input.shape === "bars") return barOption(input);
|
|
154
|
+
return lineOption(input);
|
|
155
|
+
};
|
|
156
|
+
//#endregion
|
|
157
|
+
export { sparkOption };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//#region src/charts/tooltip.ts
|
|
2
|
+
const TOOLTIP_CLASS = ["tf-edge-sweep tf-edge-plain rounded-tf-inline bg-tf-glass px-2 py-1", "font-tf-body text-tf-caption-sm text-tf-fg shadow-tf-float backdrop-blur-tf-glass"].join(" ");
|
|
3
|
+
const NO_CHROME_CSS = "box-shadow: none; pointer-events: none;";
|
|
4
|
+
const NO_CONTENT = "";
|
|
5
|
+
const SNAP_TO_CURSOR = 0;
|
|
6
|
+
const EMPTY_LENGTH = 0;
|
|
7
|
+
const DEFAULT_AXIS_POINTER = { type: "none" };
|
|
8
|
+
const appendToBody = () => document.body;
|
|
9
|
+
const formatCallbackValue = (value) => {
|
|
10
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
11
|
+
return NO_CONTENT;
|
|
12
|
+
};
|
|
13
|
+
const asParams = (raw) => {
|
|
14
|
+
if (Array.isArray(raw)) return raw;
|
|
15
|
+
return [raw];
|
|
16
|
+
};
|
|
17
|
+
const chartTooltip = (formatter, trigger = "item", axisPointer = DEFAULT_AXIS_POINTER) => {
|
|
18
|
+
const base = {
|
|
19
|
+
appendTo: appendToBody,
|
|
20
|
+
backgroundColor: "transparent",
|
|
21
|
+
borderWidth: 0,
|
|
22
|
+
extraCssText: NO_CHROME_CSS,
|
|
23
|
+
formatter: (raw) => {
|
|
24
|
+
const params = asParams(raw);
|
|
25
|
+
if (params.length === EMPTY_LENGTH) return NO_CONTENT;
|
|
26
|
+
return `<div class="${TOOLTIP_CLASS}">${formatter(params)}</div>`;
|
|
27
|
+
},
|
|
28
|
+
padding: 0,
|
|
29
|
+
transitionDuration: SNAP_TO_CURSOR,
|
|
30
|
+
trigger
|
|
31
|
+
};
|
|
32
|
+
if (trigger === "axis") return {
|
|
33
|
+
...base,
|
|
34
|
+
axisPointer
|
|
35
|
+
};
|
|
36
|
+
return base;
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { chartTooltip, formatCallbackValue };
|
package/dist/cookie.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/cookie.d.ts
|
|
2
|
+
declare const SIDEBAR_COOKIE = "tf-sidebar";
|
|
3
|
+
declare const cookieValue: (name: string) => string;
|
|
4
|
+
declare const rememberCookie: (name: string, value: string) => void;
|
|
5
|
+
declare const sidebarCookieValue: (collapsed: boolean) => string;
|
|
6
|
+
declare const sidebarCollapsedFrom: (value: string, fallback: boolean) => boolean;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { SIDEBAR_COOKIE, cookieValue, rememberCookie, sidebarCollapsedFrom, sidebarCookieValue };
|
package/dist/cookie.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/cookie.ts
|
|
2
|
+
const PATH = "path=/";
|
|
3
|
+
const SAME_SITE = "SameSite=Lax";
|
|
4
|
+
const WEEK_SECONDS = 604800;
|
|
5
|
+
const AFTER_NAME = 1;
|
|
6
|
+
const SIDEBAR_COOKIE = "tf-sidebar";
|
|
7
|
+
const NOTHING = "";
|
|
8
|
+
const inBrowser = () => typeof document !== "undefined";
|
|
9
|
+
const cookieValue = (name) => {
|
|
10
|
+
if (!inBrowser()) return NOTHING;
|
|
11
|
+
const found = document.cookie.split("; ").find((one) => one.startsWith(`${name}=`));
|
|
12
|
+
if (typeof found !== "string") return NOTHING;
|
|
13
|
+
return found.slice(name.length + AFTER_NAME);
|
|
14
|
+
};
|
|
15
|
+
const rememberCookie = (name, value) => {
|
|
16
|
+
if (!inBrowser()) return;
|
|
17
|
+
document.cookie = `${name}=${value}; ${PATH}; max-age=${String(WEEK_SECONDS)}; ${SAME_SITE}`;
|
|
18
|
+
};
|
|
19
|
+
const SIDEBAR_RAIL = "1";
|
|
20
|
+
const SIDEBAR_OPEN = "0";
|
|
21
|
+
const sidebarCookieValue = (collapsed) => {
|
|
22
|
+
if (collapsed) return SIDEBAR_RAIL;
|
|
23
|
+
return SIDEBAR_OPEN;
|
|
24
|
+
};
|
|
25
|
+
const sidebarCollapsedFrom = (value, fallback) => {
|
|
26
|
+
if (value === SIDEBAR_RAIL) return true;
|
|
27
|
+
if (value === SIDEBAR_OPEN) return false;
|
|
28
|
+
return fallback;
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
export { SIDEBAR_COOKIE, cookieValue, rememberCookie, sidebarCollapsedFrom, sidebarCookieValue };
|
package/dist/czech.d.ts
ADDED
package/dist/czech.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
//#region src/czech.ts
|
|
2
|
+
const SINGLE = 1;
|
|
3
|
+
const FEW_FIRST = 2;
|
|
4
|
+
const FEW_LAST = 4;
|
|
5
|
+
const results = (count, written) => {
|
|
6
|
+
if (count === SINGLE) return "1 výsledek";
|
|
7
|
+
if (count >= FEW_FIRST && count <= FEW_LAST) return `${written} výsledky`;
|
|
8
|
+
return `${written} výsledků`;
|
|
9
|
+
};
|
|
10
|
+
const czech = {
|
|
11
|
+
locale: "cs-CZ",
|
|
12
|
+
words: {
|
|
13
|
+
datePicker: {
|
|
14
|
+
calendar: "Kalendář",
|
|
15
|
+
choose: (day) => `Vybrat ${day}`,
|
|
16
|
+
chosen: (day) => `Vybráno, ${day}`,
|
|
17
|
+
clear: "Smazat data",
|
|
18
|
+
close: "Zavřít kalendář",
|
|
19
|
+
nextDecade: "Další dekáda",
|
|
20
|
+
nextMonth: "Další měsíc",
|
|
21
|
+
nextYear: "Další rok",
|
|
22
|
+
open: "Otevřít kalendář",
|
|
23
|
+
patternDay: "dd",
|
|
24
|
+
patternMonth: "mm",
|
|
25
|
+
patternYear: "rrrr",
|
|
26
|
+
pickMonth: "Vyberte měsíc",
|
|
27
|
+
pickYear: "Vyberte rok",
|
|
28
|
+
preset: (span) => `Vybrat ${span}`,
|
|
29
|
+
previousDecade: "Předchozí dekáda",
|
|
30
|
+
previousMonth: "Předchozí měsíc",
|
|
31
|
+
previousYear: "Předchozí rok",
|
|
32
|
+
rangeFrom: (day) => `Začít rozsah na ${day}`,
|
|
33
|
+
rangeTo: (day) => `Ukončit rozsah na ${day}`,
|
|
34
|
+
showDays: "Zobrazit dny",
|
|
35
|
+
showMonths: "Zobrazit měsíce",
|
|
36
|
+
showYears: "Zobrazit roky",
|
|
37
|
+
unavailable: (day) => `Nedostupné, ${day}`,
|
|
38
|
+
week: "Týd.",
|
|
39
|
+
weekNumber: (week) => `${week}. týden`
|
|
40
|
+
},
|
|
41
|
+
dialog: { close: "Zavřít" },
|
|
42
|
+
listbox: { empty: "Není z čeho vybírat" },
|
|
43
|
+
queue: { label: "Fronta" },
|
|
44
|
+
search: {
|
|
45
|
+
dismiss: "Esc zavře",
|
|
46
|
+
nothing: "Tomu nic neodpovídá",
|
|
47
|
+
results
|
|
48
|
+
},
|
|
49
|
+
select: { clear: "Zrušit výběr" },
|
|
50
|
+
sidebar: {
|
|
51
|
+
collapse: "Sbalit panel",
|
|
52
|
+
expand: "Rozbalit panel",
|
|
53
|
+
openMenu: "Otevřít menu"
|
|
54
|
+
},
|
|
55
|
+
stat: {
|
|
56
|
+
change: "Změna",
|
|
57
|
+
fell: "dolů",
|
|
58
|
+
rose: "nahoru"
|
|
59
|
+
},
|
|
60
|
+
table: {
|
|
61
|
+
actions: "Akce",
|
|
62
|
+
anything: "Cokoli",
|
|
63
|
+
clear: "Zrušit",
|
|
64
|
+
clearAll: "Zrušit filtry",
|
|
65
|
+
clearFilter: (column) => `Zrušit filtr na ${column}`,
|
|
66
|
+
clearSelection: "Zrušit označení",
|
|
67
|
+
done: "Hotovo",
|
|
68
|
+
emptyHint: "Až tu něco bude, uvidíte to zde.",
|
|
69
|
+
emptyTitle: "Zatím tu nic není",
|
|
70
|
+
expandRow: (row) => `Zobrazit více o řádku ${row}`,
|
|
71
|
+
filterBy: (column) => `Filtrovat ${column}`,
|
|
72
|
+
filterPick: (column) => `Vyberte z ${column}`,
|
|
73
|
+
filterRange: (column) => `Rozsah ${column}`,
|
|
74
|
+
filterSearch: (column) => `Hledat v ${column}`,
|
|
75
|
+
from: "Od",
|
|
76
|
+
nextPage: "Další stránka",
|
|
77
|
+
noRows: "Žádné řádky",
|
|
78
|
+
nothingHint: "Zrušte jednu z podmínek, nebo smažte hledání.",
|
|
79
|
+
nothingTitle: "Těmto filtrům nic neodpovídá",
|
|
80
|
+
pages: "Stránky",
|
|
81
|
+
previousPage: "Předchozí stránka",
|
|
82
|
+
rowsPerPage: "Řádků na stránku",
|
|
83
|
+
selectAll: "Označit řádky na této stránce",
|
|
84
|
+
selectRow: (row) => `Označit řádek ${row}`,
|
|
85
|
+
selected: (_count, written) => `${written} označeno`,
|
|
86
|
+
shown: (from, to, total) => `${from}–${to} z ${total}`,
|
|
87
|
+
sortAscending: (column) => `Řadit ${column} od nejmenšího`,
|
|
88
|
+
sortBy: (column) => `Řadit podle ${column}`,
|
|
89
|
+
sortClear: (column) => `Přestat řadit podle ${column}`,
|
|
90
|
+
sortDescending: (column) => `Řadit ${column} od největšího`,
|
|
91
|
+
to: "Do"
|
|
92
|
+
},
|
|
93
|
+
tail: { empty: "Žádné řádky logu" },
|
|
94
|
+
userMenu: { account: "účet" }
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
//#endregion
|
|
98
|
+
export { czech };
|
package/dist/field.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/field.d.ts
|
|
2
|
+
interface FieldFlags {
|
|
3
|
+
disabled: boolean;
|
|
4
|
+
invalid: boolean;
|
|
5
|
+
readOnly: boolean;
|
|
6
|
+
required: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare const fieldStateOf: ({ disabled, invalid, readOnly, required }: FieldFlags) => Record<string, boolean>;
|
|
9
|
+
declare const heldOf: ({ readOnly }: Pick<FieldFlags, "readOnly">) => Record<string, string>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { fieldStateOf, heldOf };
|
package/dist/field.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/field.ts
|
|
2
|
+
const fieldStateOf = ({ disabled, invalid, readOnly, required }) => {
|
|
3
|
+
const state = { invalid };
|
|
4
|
+
if (disabled) state.disabled = true;
|
|
5
|
+
if (readOnly) state.readOnly = true;
|
|
6
|
+
if (required) state.required = true;
|
|
7
|
+
return state;
|
|
8
|
+
};
|
|
9
|
+
const heldOf = ({ readOnly }) => {
|
|
10
|
+
if (readOnly) return { "data-readonly": "true" };
|
|
11
|
+
return {};
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { fieldStateOf, heldOf };
|
package/dist/hotkey.d.ts
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { regionOf } from "./aria.js";
|
|
2
|
+
import { BarsAccent, BarsOptionInput, BarsPoint, barsOption } from "./charts/bars.js";
|
|
3
|
+
import { GroupedBarsOptionInput, GroupedBarsSeries, groupedBarsOption } from "./charts/groupedBars.js";
|
|
4
|
+
import { SparkAccent, SparkOptionInput, sparkOption } from "./charts/spark.js";
|
|
5
|
+
import { SIDEBAR_COOKIE, cookieValue, rememberCookie, sidebarCollapsedFrom, sidebarCookieValue } from "./cookie.js";
|
|
6
|
+
import { DatePickerWords, DialogWords, Language, SearchWords, SelectWords, SidebarWords, StatWords, TableWords, TailWords, UserMenuWords, Words, english } from "./words.js";
|
|
7
|
+
import { czech } from "./czech.js";
|
|
8
|
+
import { fieldStateOf, heldOf } from "./field.js";
|
|
9
|
+
import { Hotkey } from "./hotkey.js";
|
|
10
|
+
import { IndicatorSpot, NOWHERE_AT_ALL, indicatorSpotIn, indicatorStyle } from "./indicator.js";
|
|
11
|
+
import { paintedLength } from "./measure.js";
|
|
12
|
+
import { Tally, WHOLE, tallyAt, tallyOf } from "./tally.js";
|
|
13
|
+
import { readDuration, readToken } from "./tokens.js";
|
|
14
|
+
import { TONE_ICON_NAME, ToneIconName } from "./toneIcons.js";
|
|
15
|
+
import { NOWHERE, NOWHERE_NEAR, Spot, highlightedIn, listOf, spotIn, stateOf, travelStyle } from "./travel.js";
|
|
16
|
+
export { type BarsAccent, type BarsOptionInput, type BarsPoint, type DatePickerWords, type DialogWords, type GroupedBarsOptionInput, type GroupedBarsSeries, type Hotkey, type IndicatorSpot, type Language, NOWHERE, NOWHERE_AT_ALL, NOWHERE_NEAR, SIDEBAR_COOKIE, type SearchWords, type SelectWords, type SidebarWords, type SparkAccent, type SparkOptionInput, type Spot, type StatWords, TONE_ICON_NAME, type TableWords, type TailWords, type Tally, type ToneIconName, type UserMenuWords, WHOLE, type Words, barsOption, cookieValue, czech, english, fieldStateOf, groupedBarsOption, heldOf, highlightedIn, indicatorSpotIn, indicatorStyle, listOf, paintedLength, readDuration, readToken, regionOf, rememberCookie, sidebarCollapsedFrom, sidebarCookieValue, sparkOption, spotIn, stateOf, tallyAt, tallyOf, travelStyle };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { regionOf } from "./aria.js";
|
|
2
|
+
import { barsOption } from "./charts/bars.js";
|
|
3
|
+
import { groupedBarsOption } from "./charts/groupedBars.js";
|
|
4
|
+
import { sparkOption } from "./charts/spark.js";
|
|
5
|
+
import { SIDEBAR_COOKIE, cookieValue, rememberCookie, sidebarCollapsedFrom, sidebarCookieValue } from "./cookie.js";
|
|
6
|
+
import { czech } from "./czech.js";
|
|
7
|
+
import { fieldStateOf, heldOf } from "./field.js";
|
|
8
|
+
import { NOWHERE_AT_ALL, indicatorSpotIn, indicatorStyle } from "./indicator.js";
|
|
9
|
+
import { paintedLength } from "./measure.js";
|
|
10
|
+
import { WHOLE, tallyAt, tallyOf } from "./tally.js";
|
|
11
|
+
import { readDuration, readToken } from "./tokens.js";
|
|
12
|
+
import { TONE_ICON_NAME } from "./toneIcons.js";
|
|
13
|
+
import { NOWHERE, NOWHERE_NEAR, highlightedIn, listOf, spotIn, stateOf, travelStyle } from "./travel.js";
|
|
14
|
+
import { english } from "./words.js";
|
|
15
|
+
export { NOWHERE, NOWHERE_AT_ALL, NOWHERE_NEAR, SIDEBAR_COOKIE, TONE_ICON_NAME, WHOLE, barsOption, cookieValue, czech, english, fieldStateOf, groupedBarsOption, heldOf, highlightedIn, indicatorSpotIn, indicatorStyle, listOf, paintedLength, readDuration, readToken, regionOf, rememberCookie, sidebarCollapsedFrom, sidebarCookieValue, sparkOption, spotIn, stateOf, tallyAt, tallyOf, travelStyle };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/indicator.d.ts
|
|
2
|
+
interface IndicatorSpot {
|
|
3
|
+
left: number;
|
|
4
|
+
width: number;
|
|
5
|
+
}
|
|
6
|
+
declare const NOWHERE_AT_ALL: IndicatorSpot;
|
|
7
|
+
declare const indicatorSpotIn: (host: HTMLElement | null) => IndicatorSpot;
|
|
8
|
+
declare const indicatorStyle: (spot: IndicatorSpot) => Record<string, string>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { type IndicatorSpot, NOWHERE_AT_ALL, indicatorSpotIn, indicatorStyle };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/indicator.ts
|
|
2
|
+
const NOWHERE = 0;
|
|
3
|
+
const HIDDEN = "0";
|
|
4
|
+
const SHOWN = "1";
|
|
5
|
+
const NOWHERE_AT_ALL = {
|
|
6
|
+
left: NOWHERE,
|
|
7
|
+
width: NOWHERE
|
|
8
|
+
};
|
|
9
|
+
const indicatorSpotIn = (host) => {
|
|
10
|
+
if (!host) return NOWHERE_AT_ALL;
|
|
11
|
+
const chosen = host.querySelector("[data-selected]");
|
|
12
|
+
if (!chosen) return NOWHERE_AT_ALL;
|
|
13
|
+
return {
|
|
14
|
+
left: chosen.offsetLeft,
|
|
15
|
+
width: chosen.offsetWidth
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
const shownAt = (width) => {
|
|
19
|
+
if (width === NOWHERE) return HIDDEN;
|
|
20
|
+
return SHOWN;
|
|
21
|
+
};
|
|
22
|
+
const indicatorStyle = (spot) => ({
|
|
23
|
+
"--left": `${String(spot.left)}px`,
|
|
24
|
+
"--width": `${String(spot.width)}px`,
|
|
25
|
+
opacity: shownAt(spot.width)
|
|
26
|
+
});
|
|
27
|
+
//#endregion
|
|
28
|
+
export { NOWHERE_AT_ALL, indicatorSpotIn, indicatorStyle };
|
package/dist/measure.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/measure.ts
|
|
2
|
+
const paintedLength = (length) => {
|
|
3
|
+
const probe = document.createElement("span");
|
|
4
|
+
probe.style.position = "absolute";
|
|
5
|
+
probe.style.height = length;
|
|
6
|
+
document.body.append(probe);
|
|
7
|
+
const painted = probe.getBoundingClientRect().height;
|
|
8
|
+
probe.remove();
|
|
9
|
+
return painted;
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { paintedLength };
|
package/dist/tally.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/tally.d.ts
|
|
2
|
+
declare const WHOLE = 1;
|
|
3
|
+
interface Tally {
|
|
4
|
+
counts: boolean;
|
|
5
|
+
group: string;
|
|
6
|
+
head: string;
|
|
7
|
+
places: number;
|
|
8
|
+
point: string;
|
|
9
|
+
tail: string;
|
|
10
|
+
target: number;
|
|
11
|
+
whole: string;
|
|
12
|
+
}
|
|
13
|
+
declare const tallyOf: (value: string) => Tally;
|
|
14
|
+
declare const tallyAt: (tally: Tally, part: number) => string;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { type Tally, WHOLE, tallyAt, tallyOf };
|
package/dist/tally.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
//#region src/tally.ts
|
|
2
|
+
const RUN = /\d(?:[\S\s]*\d)?/u;
|
|
3
|
+
const MARKS = /\D/gu;
|
|
4
|
+
const LAST = -1;
|
|
5
|
+
const ONCE = 1;
|
|
6
|
+
const ONE = 1;
|
|
7
|
+
const NONE = 0;
|
|
8
|
+
const WHOLE = 1;
|
|
9
|
+
const GROUP_SIZE = 3;
|
|
10
|
+
const DECIMAL_MAX = 2;
|
|
11
|
+
const marksIn = (run) => run.match(MARKS) ?? [];
|
|
12
|
+
const pointOf = (run) => {
|
|
13
|
+
const marks = marksIn(run);
|
|
14
|
+
const last = marks.at(LAST) ?? "";
|
|
15
|
+
if (last === "" || marks.filter((mark) => mark === last).length > ONCE) return "";
|
|
16
|
+
if (run.length - run.lastIndexOf(last) - ONE > DECIMAL_MAX) return "";
|
|
17
|
+
return last;
|
|
18
|
+
};
|
|
19
|
+
const groupOf = (run, point) => marksIn(run).filter((mark) => mark !== point).at(LAST) ?? "";
|
|
20
|
+
const NOT_DIGITS = /[^\d]/gu;
|
|
21
|
+
const targetOf = (run, point) => {
|
|
22
|
+
if (point === "") return Number(run.replace(NOT_DIGITS, ""));
|
|
23
|
+
const [body = "", fraction = ""] = run.split(point);
|
|
24
|
+
return Number(`${body.replace(NOT_DIGITS, "")}.${fraction.replace(NOT_DIGITS, "")}`);
|
|
25
|
+
};
|
|
26
|
+
const placesOf = (run, point) => {
|
|
27
|
+
if (point === "") return NONE;
|
|
28
|
+
return run.length - run.lastIndexOf(point) - ONE;
|
|
29
|
+
};
|
|
30
|
+
const RESTS = {
|
|
31
|
+
counts: false,
|
|
32
|
+
group: "",
|
|
33
|
+
head: "",
|
|
34
|
+
places: NONE,
|
|
35
|
+
point: "",
|
|
36
|
+
tail: "",
|
|
37
|
+
target: NONE,
|
|
38
|
+
whole: ""
|
|
39
|
+
};
|
|
40
|
+
const tallyOf = (value) => {
|
|
41
|
+
const found = RUN.exec(value);
|
|
42
|
+
if (!found) return {
|
|
43
|
+
...RESTS,
|
|
44
|
+
whole: value
|
|
45
|
+
};
|
|
46
|
+
const [run] = found;
|
|
47
|
+
const point = pointOf(run);
|
|
48
|
+
return {
|
|
49
|
+
counts: true,
|
|
50
|
+
group: groupOf(run, point),
|
|
51
|
+
head: value.slice(NONE, found.index),
|
|
52
|
+
places: placesOf(run, point),
|
|
53
|
+
point,
|
|
54
|
+
tail: value.slice(found.index + run.length),
|
|
55
|
+
target: targetOf(run, point),
|
|
56
|
+
whole: value
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
const grouped = (body, group) => {
|
|
60
|
+
if (group === "") return body;
|
|
61
|
+
const parts = [];
|
|
62
|
+
for (let edge = body.length; edge > NONE; edge -= GROUP_SIZE) parts.unshift(body.slice(Math.max(edge - GROUP_SIZE, NONE), edge));
|
|
63
|
+
return parts.join(group);
|
|
64
|
+
};
|
|
65
|
+
const tallyAt = (tally, part) => {
|
|
66
|
+
if (!tally.counts || part >= 1) return tally.whole;
|
|
67
|
+
const [body = "", fraction = ""] = (tally.target * part).toFixed(tally.places).split(".");
|
|
68
|
+
const shown = grouped(body, tally.group);
|
|
69
|
+
if (tally.point === "") return `${tally.head}${shown}${tally.tail}`;
|
|
70
|
+
return `${tally.head}${shown}${tally.point}${fraction}${tally.tail}`;
|
|
71
|
+
};
|
|
72
|
+
//#endregion
|
|
73
|
+
export { WHOLE, tallyAt, tallyOf };
|
package/dist/tokens.d.ts
ADDED
package/dist/tokens.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/tokens.ts
|
|
2
|
+
const MS = "ms";
|
|
3
|
+
const NOTHING = "";
|
|
4
|
+
const NO_DURATION = 0;
|
|
5
|
+
const readToken = (name) => {
|
|
6
|
+
if (typeof document === "undefined") return NOTHING;
|
|
7
|
+
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
8
|
+
};
|
|
9
|
+
const readDuration = (name) => {
|
|
10
|
+
const value = readToken(name);
|
|
11
|
+
if (value === NOTHING) return NO_DURATION;
|
|
12
|
+
return Number(value.replace(MS, ""));
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { readDuration, readToken };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Tone } from "@techfides/ui-library-design";
|
|
2
|
+
//#region src/toneIcons.d.ts
|
|
3
|
+
type ToneIconName = 'circle-alert' | 'circle-check' | 'info' | 'triangle-alert';
|
|
4
|
+
declare const TONE_ICON_NAME: Record<Exclude<Tone, 'accent'>, ToneIconName>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { TONE_ICON_NAME, type ToneIconName };
|
package/dist/travel.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/travel.d.ts
|
|
2
|
+
declare const NOWHERE = "";
|
|
3
|
+
interface Spot {
|
|
4
|
+
down: number;
|
|
5
|
+
tall: number;
|
|
6
|
+
}
|
|
7
|
+
declare const NOWHERE_NEAR: Spot;
|
|
8
|
+
declare const spotIn: (host: HTMLElement, value: string) => Spot;
|
|
9
|
+
declare const listOf: (mark: HTMLElement | null) => HTMLElement | false;
|
|
10
|
+
declare const highlightedIn: (list: HTMLElement) => string;
|
|
11
|
+
declare const stateOf: (lit: string, travelling: boolean) => Record<string, string>;
|
|
12
|
+
declare const travelStyle: (spot: Spot) => Record<string, string>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { NOWHERE, NOWHERE_NEAR, type Spot, highlightedIn, listOf, spotIn, stateOf, travelStyle };
|
package/dist/travel.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//#region src/travel.ts
|
|
2
|
+
const NOTHING = 0;
|
|
3
|
+
const NOWHERE = "";
|
|
4
|
+
const NOWHERE_NEAR = {
|
|
5
|
+
down: NOTHING,
|
|
6
|
+
tall: NOTHING
|
|
7
|
+
};
|
|
8
|
+
const spotIn = (host, value) => {
|
|
9
|
+
for (const row of host.querySelectorAll("[data-part=\"item\"]")) if (row.dataset.value === value) return {
|
|
10
|
+
down: row.offsetTop,
|
|
11
|
+
tall: row.offsetHeight
|
|
12
|
+
};
|
|
13
|
+
return NOWHERE_NEAR;
|
|
14
|
+
};
|
|
15
|
+
const listOf = (mark) => {
|
|
16
|
+
if (!mark) return false;
|
|
17
|
+
const list = mark.parentElement;
|
|
18
|
+
if (!list) return false;
|
|
19
|
+
return list;
|
|
20
|
+
};
|
|
21
|
+
const highlightedIn = (list) => {
|
|
22
|
+
const already = list.querySelector("[data-highlighted]");
|
|
23
|
+
if (!already) return "";
|
|
24
|
+
return already.dataset.value ?? "";
|
|
25
|
+
};
|
|
26
|
+
const stateOf = (lit, travelling) => {
|
|
27
|
+
const state = {};
|
|
28
|
+
if (lit !== "") state["data-lit"] = "";
|
|
29
|
+
if (!travelling) state["data-placing"] = "";
|
|
30
|
+
return state;
|
|
31
|
+
};
|
|
32
|
+
const travelStyle = (spot) => ({
|
|
33
|
+
"--tf-travel-height": `${String(spot.tall)}px`,
|
|
34
|
+
translate: `0 ${String(spot.down)}px`
|
|
35
|
+
});
|
|
36
|
+
//#endregion
|
|
37
|
+
export { NOWHERE, NOWHERE_NEAR, highlightedIn, listOf, spotIn, stateOf, travelStyle };
|
package/dist/words.d.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
//#region src/words.d.ts
|
|
2
|
+
interface TableWords {
|
|
3
|
+
actions: string;
|
|
4
|
+
anything: string;
|
|
5
|
+
clear: string;
|
|
6
|
+
clearAll: string;
|
|
7
|
+
clearFilter: (column: string) => string;
|
|
8
|
+
clearSelection: string;
|
|
9
|
+
done: string;
|
|
10
|
+
emptyHint: string;
|
|
11
|
+
emptyTitle: string;
|
|
12
|
+
expandRow: (row: string) => string;
|
|
13
|
+
filterBy: (column: string) => string;
|
|
14
|
+
filterPick: (column: string) => string;
|
|
15
|
+
filterRange: (column: string) => string;
|
|
16
|
+
filterSearch: (column: string) => string;
|
|
17
|
+
from: string;
|
|
18
|
+
nextPage: string;
|
|
19
|
+
noRows: string;
|
|
20
|
+
pages: string;
|
|
21
|
+
nothingHint: string;
|
|
22
|
+
nothingTitle: string;
|
|
23
|
+
previousPage: string;
|
|
24
|
+
rowsPerPage: string;
|
|
25
|
+
selectAll: string;
|
|
26
|
+
selectRow: (row: string) => string;
|
|
27
|
+
selected: (count: number, written: string) => string;
|
|
28
|
+
shown: (from: string, to: string, total: string) => string;
|
|
29
|
+
sortAscending: (column: string) => string;
|
|
30
|
+
sortBy: (column: string) => string;
|
|
31
|
+
sortClear: (column: string) => string;
|
|
32
|
+
sortDescending: (column: string) => string;
|
|
33
|
+
to: string;
|
|
34
|
+
}
|
|
35
|
+
interface DatePickerWords {
|
|
36
|
+
calendar: string;
|
|
37
|
+
choose: (day: string) => string;
|
|
38
|
+
chosen: (day: string) => string;
|
|
39
|
+
clear: string;
|
|
40
|
+
close: string;
|
|
41
|
+
nextDecade: string;
|
|
42
|
+
nextMonth: string;
|
|
43
|
+
nextYear: string;
|
|
44
|
+
open: string;
|
|
45
|
+
patternDay: string;
|
|
46
|
+
patternMonth: string;
|
|
47
|
+
patternYear: string;
|
|
48
|
+
pickMonth: string;
|
|
49
|
+
pickYear: string;
|
|
50
|
+
preset: (span: string) => string;
|
|
51
|
+
previousDecade: string;
|
|
52
|
+
previousMonth: string;
|
|
53
|
+
previousYear: string;
|
|
54
|
+
rangeFrom: (day: string) => string;
|
|
55
|
+
rangeTo: (day: string) => string;
|
|
56
|
+
showDays: string;
|
|
57
|
+
showMonths: string;
|
|
58
|
+
showYears: string;
|
|
59
|
+
unavailable: (day: string) => string;
|
|
60
|
+
week: string;
|
|
61
|
+
weekNumber: (week: string) => string;
|
|
62
|
+
}
|
|
63
|
+
interface DialogWords {
|
|
64
|
+
close: string;
|
|
65
|
+
}
|
|
66
|
+
interface SidebarWords {
|
|
67
|
+
collapse: string;
|
|
68
|
+
expand: string;
|
|
69
|
+
openMenu: string;
|
|
70
|
+
}
|
|
71
|
+
interface StatWords {
|
|
72
|
+
change: string;
|
|
73
|
+
fell: string;
|
|
74
|
+
rose: string;
|
|
75
|
+
}
|
|
76
|
+
interface SearchWords {
|
|
77
|
+
dismiss: string;
|
|
78
|
+
nothing: string;
|
|
79
|
+
results: (count: number, written: string) => string;
|
|
80
|
+
}
|
|
81
|
+
interface ListboxWords {
|
|
82
|
+
empty: string;
|
|
83
|
+
}
|
|
84
|
+
interface QueueWords {
|
|
85
|
+
label: string;
|
|
86
|
+
}
|
|
87
|
+
interface SelectWords {
|
|
88
|
+
clear: string;
|
|
89
|
+
}
|
|
90
|
+
interface TailWords {
|
|
91
|
+
empty: string;
|
|
92
|
+
}
|
|
93
|
+
interface UserMenuWords {
|
|
94
|
+
account: string;
|
|
95
|
+
}
|
|
96
|
+
interface Words {
|
|
97
|
+
datePicker: DatePickerWords;
|
|
98
|
+
dialog: DialogWords;
|
|
99
|
+
listbox: ListboxWords;
|
|
100
|
+
queue: QueueWords;
|
|
101
|
+
search: SearchWords;
|
|
102
|
+
select: SelectWords;
|
|
103
|
+
sidebar: SidebarWords;
|
|
104
|
+
stat: StatWords;
|
|
105
|
+
table: TableWords;
|
|
106
|
+
tail: TailWords;
|
|
107
|
+
userMenu: UserMenuWords;
|
|
108
|
+
}
|
|
109
|
+
interface Language {
|
|
110
|
+
locale?: string;
|
|
111
|
+
words: Words;
|
|
112
|
+
}
|
|
113
|
+
declare const english: Language;
|
|
114
|
+
//#endregion
|
|
115
|
+
export { type DatePickerWords, type DialogWords, type Language, type SearchWords, type SelectWords, type SidebarWords, type StatWords, type TableWords, type TailWords, type UserMenuWords, type Words, english };
|
package/dist/words.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
//#region src/words.ts
|
|
2
|
+
const SINGLE = 1;
|
|
3
|
+
const english = {
|
|
4
|
+
locale: "en-US",
|
|
5
|
+
words: {
|
|
6
|
+
datePicker: {
|
|
7
|
+
calendar: "Calendar",
|
|
8
|
+
choose: (day) => `Choose ${day}`,
|
|
9
|
+
chosen: (day) => `Chosen, ${day}`,
|
|
10
|
+
clear: "Clear the dates",
|
|
11
|
+
close: "Close the calendar",
|
|
12
|
+
nextDecade: "Next decade",
|
|
13
|
+
nextMonth: "Next month",
|
|
14
|
+
nextYear: "Next year",
|
|
15
|
+
open: "Open the calendar",
|
|
16
|
+
patternDay: "dd",
|
|
17
|
+
patternMonth: "mm",
|
|
18
|
+
patternYear: "yyyy",
|
|
19
|
+
pickMonth: "Pick a month",
|
|
20
|
+
pickYear: "Pick a year",
|
|
21
|
+
preset: (span) => `Choose ${span}`,
|
|
22
|
+
previousDecade: "Previous decade",
|
|
23
|
+
previousMonth: "Previous month",
|
|
24
|
+
previousYear: "Previous year",
|
|
25
|
+
rangeFrom: (day) => `Start the range at ${day}`,
|
|
26
|
+
rangeTo: (day) => `End the range at ${day}`,
|
|
27
|
+
showDays: "Show the days",
|
|
28
|
+
showMonths: "Show the months",
|
|
29
|
+
showYears: "Show the years",
|
|
30
|
+
unavailable: (day) => `Not available, ${day}`,
|
|
31
|
+
week: "Wk",
|
|
32
|
+
weekNumber: (week) => `Week ${week}`
|
|
33
|
+
},
|
|
34
|
+
dialog: { close: "Close" },
|
|
35
|
+
listbox: { empty: "Nothing to choose from" },
|
|
36
|
+
queue: { label: "Queue" },
|
|
37
|
+
search: {
|
|
38
|
+
dismiss: "Esc closes",
|
|
39
|
+
nothing: "Nothing matches that",
|
|
40
|
+
results: (count, written) => {
|
|
41
|
+
if (count === SINGLE) return "1 result";
|
|
42
|
+
return `${written} results`;
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
select: { clear: "Clear" },
|
|
46
|
+
sidebar: {
|
|
47
|
+
collapse: "Collapse the sidebar",
|
|
48
|
+
expand: "Expand the sidebar",
|
|
49
|
+
openMenu: "Open menu"
|
|
50
|
+
},
|
|
51
|
+
stat: {
|
|
52
|
+
change: "Change",
|
|
53
|
+
fell: "down",
|
|
54
|
+
rose: "up"
|
|
55
|
+
},
|
|
56
|
+
table: {
|
|
57
|
+
actions: "Actions",
|
|
58
|
+
anything: "Anything",
|
|
59
|
+
clear: "Clear",
|
|
60
|
+
clearAll: "Clear the filters",
|
|
61
|
+
clearFilter: (column) => `Remove the filter on ${column}`,
|
|
62
|
+
clearSelection: "Clear selection",
|
|
63
|
+
done: "Done",
|
|
64
|
+
emptyHint: "Items will show up here once there are some.",
|
|
65
|
+
emptyTitle: "No items yet",
|
|
66
|
+
expandRow: (row) => `Show more about row ${row}`,
|
|
67
|
+
filterBy: (column) => `Filter ${column}`,
|
|
68
|
+
filterPick: (column) => `Pick from ${column}`,
|
|
69
|
+
filterRange: (column) => `Range of ${column}`,
|
|
70
|
+
filterSearch: (column) => `Search in ${column}`,
|
|
71
|
+
from: "From",
|
|
72
|
+
nextPage: "Next page",
|
|
73
|
+
noRows: "No rows",
|
|
74
|
+
nothingHint: "Drop one of the conditions, or clear the search.",
|
|
75
|
+
nothingTitle: "Nothing matches those filters",
|
|
76
|
+
pages: "Pages",
|
|
77
|
+
previousPage: "Previous page",
|
|
78
|
+
rowsPerPage: "Rows per page",
|
|
79
|
+
selectAll: "Select the rows on this page",
|
|
80
|
+
selectRow: (row) => `Select row ${row}`,
|
|
81
|
+
selected: (_count, written) => `${written} selected`,
|
|
82
|
+
shown: (from, to, total) => `${from}–${to} of ${total}`,
|
|
83
|
+
sortAscending: (column) => `Sort ${column} smallest first`,
|
|
84
|
+
sortBy: (column) => `Sort by ${column}`,
|
|
85
|
+
sortClear: (column) => `Stop sorting by ${column}`,
|
|
86
|
+
sortDescending: (column) => `Sort ${column} largest first`,
|
|
87
|
+
to: "To"
|
|
88
|
+
},
|
|
89
|
+
tail: { empty: "No log lines" },
|
|
90
|
+
userMenu: { account: "account" }
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
//#endregion
|
|
94
|
+
export { english };
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@techfides/ui-library-core",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Framework-agnostic logic for the TechFides UI library: words and languages, number tallies, chart options, field state and shared DOM maths",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"design-system",
|
|
7
|
+
"headless",
|
|
8
|
+
"i18n"
|
|
9
|
+
],
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/TechFides/ui-library.git",
|
|
14
|
+
"directory": "packages/core"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"imports": {
|
|
22
|
+
"#*": "./src/*.ts"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@tanstack/hotkeys": "^0.8.0",
|
|
36
|
+
"@techfides/ui-library-design": "^0.5.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@arethetypeswrong/core": "^0.18.5",
|
|
40
|
+
"echarts": "^6.1.0",
|
|
41
|
+
"publint": "^0.3.24",
|
|
42
|
+
"tsdown": "^0.22.14",
|
|
43
|
+
"typescript": "~6.0.3",
|
|
44
|
+
"@techfides/tsconfig": "0.0.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"echarts": "^6.1.0"
|
|
48
|
+
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"echarts": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=24"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsdown",
|
|
59
|
+
"dev": "tsdown --watch",
|
|
60
|
+
"lint": "eslint . --max-warnings=0",
|
|
61
|
+
"typecheck": "tsc --noEmit"
|
|
62
|
+
},
|
|
63
|
+
"module": "./dist/index.js",
|
|
64
|
+
"types": "./dist/index.d.ts"
|
|
65
|
+
}
|