@sentropic/design-system-vue 0.10.0 → 0.12.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/dist/ComboChart.d.ts +119 -0
- package/dist/ComboChart.d.ts.map +1 -0
- package/dist/ComboChart.js +280 -0
- package/dist/ComboChart.js.map +1 -0
- package/dist/ForceGraph.d.ts +104 -0
- package/dist/ForceGraph.d.ts.map +1 -1
- package/dist/ForceGraph.js +193 -4
- package/dist/ForceGraph.js.map +1 -1
- package/dist/FunnelChart.d.ts +103 -0
- package/dist/FunnelChart.d.ts.map +1 -0
- package/dist/FunnelChart.js +191 -0
- package/dist/FunnelChart.js.map +1 -0
- package/dist/GaugeChart.d.ts +134 -0
- package/dist/GaugeChart.d.ts.map +1 -0
- package/dist/GaugeChart.js +152 -0
- package/dist/GaugeChart.js.map +1 -0
- package/dist/KpiCard.d.ts +151 -0
- package/dist/KpiCard.d.ts.map +1 -0
- package/dist/KpiCard.js +155 -0
- package/dist/KpiCard.js.map +1 -0
- package/dist/SelectableList.d.ts +98 -0
- package/dist/SelectableList.d.ts.map +1 -0
- package/dist/SelectableList.js +174 -0
- package/dist/SelectableList.js.map +1 -0
- package/dist/SelectableRow.d.ts +140 -0
- package/dist/SelectableRow.d.ts.map +1 -0
- package/dist/SelectableRow.js +130 -0
- package/dist/SelectableRow.js.map +1 -0
- package/dist/TimePicker.d.ts +1 -1
- package/dist/TreemapChart.d.ts +95 -0
- package/dist/TreemapChart.d.ts.map +1 -0
- package/dist/TreemapChart.js +255 -0
- package/dist/TreemapChart.js.map +1 -0
- package/dist/WaterfallChart.d.ts +84 -0
- package/dist/WaterfallChart.d.ts.map +1 -0
- package/dist/WaterfallChart.js +186 -0
- package/dist/WaterfallChart.js.map +1 -0
- package/dist/chartScale.d.ts +4 -0
- package/dist/chartScale.d.ts.map +1 -1
- package/dist/chartScale.js +44 -0
- package/dist/chartScale.js.map +1 -1
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/styles.css +851 -2
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KpiCard.d.ts","sourceRoot":"","sources":["../src/KpiCard.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC7C,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAClD,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAC9D,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,UAAU,CAAC;AACxD,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,CAAC;AAEhB,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,OAAO;;cAG8B,MAAM,MAAM,GAAG,MAAM;;;;;;;;;;;;cAGpC,MAAM,kBAAkB;;;;cAC9B,MAAM,YAAY;;;;cACjB,MAAM,aAAa;;;;;;;;;;;;;;;;cAIjB,MAAM,MAAM,EAAE;;;;cAClB,MAAM,WAAW;;;;cACjB,MAAM,WAAW;;;;;;;;;;;cAXK,MAAM,MAAM,GAAG,MAAM;;;;;;;;;;;;cAGpC,MAAM,kBAAkB;;;;cAC9B,MAAM,YAAY;;;;cACjB,MAAM,aAAa;;;;;;;;;;;;;;;;cAIjB,MAAM,MAAM,EAAE;;;;cAClB,MAAM,WAAW;;;;cACjB,MAAM,WAAW;;;;;;;;;;;;;;;;;;;4EAyK3C,CAAC"}
|
package/dist/KpiCard.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { defineComponent, h } from "vue";
|
|
2
|
+
import { classNames } from "./classNames.js";
|
|
3
|
+
import { Sparkline } from "./Sparkline.js";
|
|
4
|
+
export const KpiCard = defineComponent({
|
|
5
|
+
name: "KpiCard",
|
|
6
|
+
props: {
|
|
7
|
+
value: { type: [Number, String], required: true },
|
|
8
|
+
label: { type: String, required: true },
|
|
9
|
+
delta: { type: Number, default: undefined },
|
|
10
|
+
deltaFormat: { type: String, default: "percent" },
|
|
11
|
+
trend: { type: String, default: undefined },
|
|
12
|
+
format: { type: String, default: "number" },
|
|
13
|
+
unit: { type: String, default: undefined },
|
|
14
|
+
currency: { type: String, default: "EUR" },
|
|
15
|
+
locale: { type: String, default: undefined },
|
|
16
|
+
sparkline: { type: Array, default: undefined },
|
|
17
|
+
size: { type: String, default: "md" },
|
|
18
|
+
tone: { type: String, default: undefined },
|
|
19
|
+
class: { type: String, default: undefined },
|
|
20
|
+
},
|
|
21
|
+
setup(props, { attrs }) {
|
|
22
|
+
return () => {
|
|
23
|
+
const value = props.value;
|
|
24
|
+
const label = props.label;
|
|
25
|
+
const delta = props.delta;
|
|
26
|
+
const deltaFormat = props.deltaFormat ?? "percent";
|
|
27
|
+
const format = props.format ?? "number";
|
|
28
|
+
const unit = props.unit;
|
|
29
|
+
const currency = props.currency ?? "EUR";
|
|
30
|
+
const locale = props.locale;
|
|
31
|
+
const sparkline = props.sparkline;
|
|
32
|
+
const size = props.size ?? "md";
|
|
33
|
+
const tone = props.tone;
|
|
34
|
+
const resolvedTrend = props.trend ?? (delta == null ? undefined : delta > 0 ? "up" : delta < 0 ? "down" : "flat");
|
|
35
|
+
let formattedValue;
|
|
36
|
+
if (typeof value === "string") {
|
|
37
|
+
formattedValue = value;
|
|
38
|
+
}
|
|
39
|
+
else if (!Number.isFinite(value)) {
|
|
40
|
+
// Jamais de « NaN »/« ∞ » dans le DOM ni l'aria.
|
|
41
|
+
formattedValue = "—";
|
|
42
|
+
}
|
|
43
|
+
else if (format === "currency") {
|
|
44
|
+
// Un code devise invalide fait lever Intl ; on retombe sur le nombre brut.
|
|
45
|
+
try {
|
|
46
|
+
formattedValue = new Intl.NumberFormat(locale, { style: "currency", currency }).format(value);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
formattedValue = new Intl.NumberFormat(locale).format(value);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (format === "percent") {
|
|
53
|
+
formattedValue = new Intl.NumberFormat(locale, {
|
|
54
|
+
style: "percent",
|
|
55
|
+
maximumFractionDigits: 2,
|
|
56
|
+
}).format(value);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
formattedValue = new Intl.NumberFormat(locale).format(value);
|
|
60
|
+
}
|
|
61
|
+
let formattedDelta;
|
|
62
|
+
if (delta != null && Number.isFinite(delta)) {
|
|
63
|
+
const sign = delta > 0 ? "+" : "";
|
|
64
|
+
if (deltaFormat === "percent") {
|
|
65
|
+
const pct = new Intl.NumberFormat(locale, {
|
|
66
|
+
style: "percent",
|
|
67
|
+
maximumFractionDigits: 1,
|
|
68
|
+
}).format(delta);
|
|
69
|
+
formattedDelta = `${sign}${pct}`;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
formattedDelta = `${sign}${new Intl.NumberFormat(locale).format(delta)}`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const sparklineTone = resolvedTrend === "up" ? "success" : resolvedTrend === "down" ? "error" : "neutral";
|
|
76
|
+
const arrow = resolvedTrend === "up"
|
|
77
|
+
? "M3 8.5 7 4l4 4.5"
|
|
78
|
+
: resolvedTrend === "down"
|
|
79
|
+
? "M3 5.5 7 10l4-4.5"
|
|
80
|
+
: "M3 7h8";
|
|
81
|
+
const trendLabel = resolvedTrend === "up"
|
|
82
|
+
? "en hausse"
|
|
83
|
+
: resolvedTrend === "down"
|
|
84
|
+
? "en baisse"
|
|
85
|
+
: resolvedTrend === "flat"
|
|
86
|
+
? "stable"
|
|
87
|
+
: undefined;
|
|
88
|
+
// L'unité est redondante quand le format est déjà autosuffisant.
|
|
89
|
+
const ariaUnit = format === "currency" || format === "percent" ? undefined : unit;
|
|
90
|
+
const ariaLabel = [
|
|
91
|
+
label,
|
|
92
|
+
formattedValue,
|
|
93
|
+
ariaUnit,
|
|
94
|
+
formattedDelta && `${formattedDelta} ${trendLabel ?? ""}`.trim(),
|
|
95
|
+
]
|
|
96
|
+
.filter(Boolean)
|
|
97
|
+
.join(", ");
|
|
98
|
+
const classes = classNames("st-kpiCard", `st-kpiCard--${size}`, tone && `st-kpiCard--${tone}`, tone && "st-kpiCard--toned", props.class);
|
|
99
|
+
const valueChildren = [
|
|
100
|
+
h("span", { class: "st-kpiCard__number" }, formattedValue),
|
|
101
|
+
];
|
|
102
|
+
if (unit) {
|
|
103
|
+
valueChildren.push(h("span", { class: "st-kpiCard__unit" }, unit));
|
|
104
|
+
}
|
|
105
|
+
const footerChildren = [];
|
|
106
|
+
if (formattedDelta) {
|
|
107
|
+
footerChildren.push(h("span", {
|
|
108
|
+
class: `st-kpiCard__delta st-kpiCard__delta--${resolvedTrend ?? "flat"}`,
|
|
109
|
+
"aria-hidden": "true",
|
|
110
|
+
}, [
|
|
111
|
+
h("svg", {
|
|
112
|
+
class: "st-kpiCard__arrow",
|
|
113
|
+
width: "14",
|
|
114
|
+
height: "14",
|
|
115
|
+
viewBox: "0 0 14 14",
|
|
116
|
+
"aria-hidden": "true",
|
|
117
|
+
focusable: "false",
|
|
118
|
+
}, [
|
|
119
|
+
h("path", {
|
|
120
|
+
d: arrow,
|
|
121
|
+
fill: "none",
|
|
122
|
+
stroke: "currentColor",
|
|
123
|
+
"stroke-width": "1.75",
|
|
124
|
+
"stroke-linecap": "round",
|
|
125
|
+
"stroke-linejoin": "round",
|
|
126
|
+
}),
|
|
127
|
+
]),
|
|
128
|
+
h("span", { class: "st-kpiCard__deltaValue" }, formattedDelta),
|
|
129
|
+
]));
|
|
130
|
+
}
|
|
131
|
+
if (sparkline && sparkline.length > 0) {
|
|
132
|
+
footerChildren.push(h(Sparkline, {
|
|
133
|
+
class: "st-kpiCard__sparkline",
|
|
134
|
+
data: sparkline,
|
|
135
|
+
tone: sparklineTone,
|
|
136
|
+
area: true,
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
const labelChildren = [];
|
|
140
|
+
if (tone) {
|
|
141
|
+
labelChildren.push(h("span", { class: "st-kpiCard__swatch", "aria-hidden": "true" }));
|
|
142
|
+
}
|
|
143
|
+
labelChildren.push(h("span", { class: "st-kpiCard__labelText" }, label));
|
|
144
|
+
const children = [
|
|
145
|
+
h("p", { class: "st-kpiCard__label" }, labelChildren),
|
|
146
|
+
h("p", { class: "st-kpiCard__value" }, valueChildren),
|
|
147
|
+
];
|
|
148
|
+
if (formattedDelta || sparkline) {
|
|
149
|
+
children.push(h("div", { class: "st-kpiCard__footer" }, footerChildren));
|
|
150
|
+
}
|
|
151
|
+
return h("article", { ...attrs, class: classes, role: "group", "aria-label": ariaLabel }, children);
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
//# sourceMappingURL=KpiCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KpiCard.js","sourceRoot":"","sources":["../src/KpiCard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { type PropType } from "vue";
|
|
2
|
+
export type SelectableListProps = {
|
|
3
|
+
/** Accessible name for the listbox (required for SR users). */
|
|
4
|
+
label?: string;
|
|
5
|
+
/** References the id of an external visible label (alternative to `label`). */
|
|
6
|
+
labelledby?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Allow more than one selected row. Adds aria-multiselectable and toggles
|
|
9
|
+
* each row independently. Defaults to false (single-select).
|
|
10
|
+
*/
|
|
11
|
+
multiple?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Selected value(s). Controlled when provided. For single-select pass a
|
|
14
|
+
* string (or null); for multiple pass a string[]. When omitted the list is
|
|
15
|
+
* uncontrolled and keeps its own internal selection.
|
|
16
|
+
*/
|
|
17
|
+
value?: string | string[] | null;
|
|
18
|
+
/**
|
|
19
|
+
* Fired with the new selection on every change. Receives a string|null for
|
|
20
|
+
* single-select and a string[] for multiple. Required for the controlled
|
|
21
|
+
* pattern; also fires for uncontrolled lists.
|
|
22
|
+
*/
|
|
23
|
+
onChange?: (value: string | string[] | null) => void;
|
|
24
|
+
class?: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Accessible listbox that owns selection + a roving tabindex for its
|
|
28
|
+
* {@link SelectableRow} children. Arrow / Home / End move focus (roving),
|
|
29
|
+
* Space / Enter / click toggle the focused row. Single-select by default;
|
|
30
|
+
* `multiple` toggles rows independently. Controlled via `value`/`onChange`,
|
|
31
|
+
* otherwise it keeps its own internal selection. Pilots each child row through
|
|
32
|
+
* provide/inject (role="option" + the computed tabindex / aria-selected).
|
|
33
|
+
*/
|
|
34
|
+
export declare const SelectableList: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
35
|
+
label: {
|
|
36
|
+
type: StringConstructor;
|
|
37
|
+
default: undefined;
|
|
38
|
+
};
|
|
39
|
+
labelledby: {
|
|
40
|
+
type: StringConstructor;
|
|
41
|
+
default: undefined;
|
|
42
|
+
};
|
|
43
|
+
multiple: {
|
|
44
|
+
type: BooleanConstructor;
|
|
45
|
+
default: boolean;
|
|
46
|
+
};
|
|
47
|
+
value: {
|
|
48
|
+
type: PropType<string | string[] | null>;
|
|
49
|
+
default: undefined;
|
|
50
|
+
};
|
|
51
|
+
onChange: {
|
|
52
|
+
type: PropType<(value: string | string[] | null) => void>;
|
|
53
|
+
default: undefined;
|
|
54
|
+
};
|
|
55
|
+
class: {
|
|
56
|
+
type: StringConstructor;
|
|
57
|
+
default: undefined;
|
|
58
|
+
};
|
|
59
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
60
|
+
[key: string]: any;
|
|
61
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
62
|
+
change: (_value: string | string[] | null) => true;
|
|
63
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
64
|
+
label: {
|
|
65
|
+
type: StringConstructor;
|
|
66
|
+
default: undefined;
|
|
67
|
+
};
|
|
68
|
+
labelledby: {
|
|
69
|
+
type: StringConstructor;
|
|
70
|
+
default: undefined;
|
|
71
|
+
};
|
|
72
|
+
multiple: {
|
|
73
|
+
type: BooleanConstructor;
|
|
74
|
+
default: boolean;
|
|
75
|
+
};
|
|
76
|
+
value: {
|
|
77
|
+
type: PropType<string | string[] | null>;
|
|
78
|
+
default: undefined;
|
|
79
|
+
};
|
|
80
|
+
onChange: {
|
|
81
|
+
type: PropType<(value: string | string[] | null) => void>;
|
|
82
|
+
default: undefined;
|
|
83
|
+
};
|
|
84
|
+
class: {
|
|
85
|
+
type: StringConstructor;
|
|
86
|
+
default: undefined;
|
|
87
|
+
};
|
|
88
|
+
}>> & Readonly<{
|
|
89
|
+
onChange?: ((_value: string | string[] | null) => any) | undefined;
|
|
90
|
+
}>, {
|
|
91
|
+
multiple: boolean;
|
|
92
|
+
class: string;
|
|
93
|
+
onChange: (value: string | string[] | null) => void;
|
|
94
|
+
label: string;
|
|
95
|
+
value: string | string[] | null;
|
|
96
|
+
labelledby: string;
|
|
97
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
98
|
+
//# sourceMappingURL=SelectableList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectableList.d.ts","sourceRoot":"","sources":["../src/SelectableList.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,QAAQ,EACd,MAAM,KAAK,CAAC;AAOb,MAAM,MAAM,mBAAmB,GAAG;IAChC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAkBF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;cASI,QAAQ,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;;;;cAIzC,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC;;;;;;;;;;qBAMtD,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI;;;;;;;;;;;;;;;cAVd,QAAQ,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;;;;cAIzC,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC;;;;;;;;;;;;sBAAlC,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI;;;;4EA+IxE,CAAC"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { computed, defineComponent, h, provide, ref, } from "vue";
|
|
2
|
+
import { classNames } from "./classNames.js";
|
|
3
|
+
import { SELECTABLE_LIST_KEY, } from "./SelectableRow.js";
|
|
4
|
+
function toSet(v) {
|
|
5
|
+
if (v == null)
|
|
6
|
+
return new Set();
|
|
7
|
+
return new Set(Array.isArray(v) ? v : [v]);
|
|
8
|
+
}
|
|
9
|
+
function sortByDom(list) {
|
|
10
|
+
return [...list].sort((a, b) => {
|
|
11
|
+
const pos = a.el.compareDocumentPosition(b.el);
|
|
12
|
+
if (pos & Node.DOCUMENT_POSITION_FOLLOWING)
|
|
13
|
+
return -1;
|
|
14
|
+
if (pos & Node.DOCUMENT_POSITION_PRECEDING)
|
|
15
|
+
return 1;
|
|
16
|
+
return 0;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Accessible listbox that owns selection + a roving tabindex for its
|
|
21
|
+
* {@link SelectableRow} children. Arrow / Home / End move focus (roving),
|
|
22
|
+
* Space / Enter / click toggle the focused row. Single-select by default;
|
|
23
|
+
* `multiple` toggles rows independently. Controlled via `value`/`onChange`,
|
|
24
|
+
* otherwise it keeps its own internal selection. Pilots each child row through
|
|
25
|
+
* provide/inject (role="option" + the computed tabindex / aria-selected).
|
|
26
|
+
*/
|
|
27
|
+
export const SelectableList = defineComponent({
|
|
28
|
+
name: "SelectableList",
|
|
29
|
+
props: {
|
|
30
|
+
label: { type: String, default: undefined },
|
|
31
|
+
labelledby: { type: String, default: undefined },
|
|
32
|
+
multiple: { type: Boolean, default: false },
|
|
33
|
+
value: {
|
|
34
|
+
// Vue skips type validation for null/undefined values, so [String, Array]
|
|
35
|
+
// accepts a string, a string[], or null/undefined (uncontrolled).
|
|
36
|
+
type: [String, Array],
|
|
37
|
+
default: undefined,
|
|
38
|
+
},
|
|
39
|
+
onChange: {
|
|
40
|
+
type: Function,
|
|
41
|
+
default: undefined,
|
|
42
|
+
},
|
|
43
|
+
class: { type: String, default: undefined },
|
|
44
|
+
},
|
|
45
|
+
emits: {
|
|
46
|
+
change: (_value) => true,
|
|
47
|
+
},
|
|
48
|
+
setup(props, { slots, attrs, emit }) {
|
|
49
|
+
// Controlled when the consumer passes `value` (including null).
|
|
50
|
+
const controlled = computed(() => props.value !== undefined);
|
|
51
|
+
// Internal selection for the uncontrolled case.
|
|
52
|
+
const internal = ref(new Set());
|
|
53
|
+
const selectedValues = computed(() => controlled.value ? toSet(props.value) : internal.value);
|
|
54
|
+
// Row registry, ordered by DOM position so arrow nav matches the visual
|
|
55
|
+
// order regardless of registration timing.
|
|
56
|
+
const entries = ref([]);
|
|
57
|
+
// The element holding the roving tab stop (tabindex 0). Null until a row is
|
|
58
|
+
// focused; until then the FIRST registered row is the default stop.
|
|
59
|
+
const tabStopEl = ref(null);
|
|
60
|
+
// Bumped on every selection / focus / registry change so child rows (which
|
|
61
|
+
// read `version`) re-render and recompute role / tabindex / aria-selected.
|
|
62
|
+
const version = ref(0);
|
|
63
|
+
function bump() {
|
|
64
|
+
version.value++;
|
|
65
|
+
}
|
|
66
|
+
function register(el, rowValue) {
|
|
67
|
+
entries.value = sortByDom([
|
|
68
|
+
...entries.value.filter((e) => e.el !== el),
|
|
69
|
+
{ el, value: rowValue },
|
|
70
|
+
]);
|
|
71
|
+
bump();
|
|
72
|
+
return () => {
|
|
73
|
+
entries.value = entries.value.filter((e) => e.el !== el);
|
|
74
|
+
if (tabStopEl.value === el)
|
|
75
|
+
tabStopEl.value = null;
|
|
76
|
+
bump();
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// Default roving stop = first registered (DOM-ordered) row when none focused.
|
|
80
|
+
const effectiveTabStop = computed(() => tabStopEl.value ?? entries.value[0]?.el ?? null);
|
|
81
|
+
function valueOf(el) {
|
|
82
|
+
return entries.value.find((e) => e.el === el)?.value;
|
|
83
|
+
}
|
|
84
|
+
function isSelected(el) {
|
|
85
|
+
const v = valueOf(el);
|
|
86
|
+
return v !== undefined && selectedValues.value.has(v);
|
|
87
|
+
}
|
|
88
|
+
function isTabStop(el) {
|
|
89
|
+
return el === effectiveTabStop.value;
|
|
90
|
+
}
|
|
91
|
+
function fireChange(value) {
|
|
92
|
+
// `emit("change")` invokes the `onChange` prop/listener exactly once.
|
|
93
|
+
emit("change", value);
|
|
94
|
+
}
|
|
95
|
+
function emitNext(next) {
|
|
96
|
+
if (!controlled.value)
|
|
97
|
+
internal.value = next;
|
|
98
|
+
if (props.multiple)
|
|
99
|
+
fireChange([...next]);
|
|
100
|
+
else
|
|
101
|
+
fireChange(next.size ? [...next][0] : null);
|
|
102
|
+
bump();
|
|
103
|
+
}
|
|
104
|
+
function activate(el) {
|
|
105
|
+
const v = valueOf(el);
|
|
106
|
+
if (v === undefined)
|
|
107
|
+
return;
|
|
108
|
+
const current = selectedValues.value;
|
|
109
|
+
let next;
|
|
110
|
+
if (props.multiple) {
|
|
111
|
+
next = new Set(current);
|
|
112
|
+
if (next.has(v))
|
|
113
|
+
next.delete(v);
|
|
114
|
+
else
|
|
115
|
+
next.add(v);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// Single-select toggles off when re-activating the selected row.
|
|
119
|
+
next = current.has(v) && current.size === 1 ? new Set() : new Set([v]);
|
|
120
|
+
}
|
|
121
|
+
emitNext(next);
|
|
122
|
+
}
|
|
123
|
+
function focusRow(el) {
|
|
124
|
+
tabStopEl.value = el;
|
|
125
|
+
bump();
|
|
126
|
+
}
|
|
127
|
+
function navigate(el, key) {
|
|
128
|
+
const list = entries.value;
|
|
129
|
+
if (list.length === 0)
|
|
130
|
+
return;
|
|
131
|
+
const idx = list.findIndex((e) => e.el === el);
|
|
132
|
+
if (idx === -1)
|
|
133
|
+
return;
|
|
134
|
+
let targetIdx = idx;
|
|
135
|
+
if (key === "ArrowDown" || key === "ArrowRight")
|
|
136
|
+
targetIdx = idx + 1;
|
|
137
|
+
else if (key === "ArrowUp" || key === "ArrowLeft")
|
|
138
|
+
targetIdx = idx - 1;
|
|
139
|
+
else if (key === "Home")
|
|
140
|
+
targetIdx = 0;
|
|
141
|
+
else if (key === "End")
|
|
142
|
+
targetIdx = list.length - 1;
|
|
143
|
+
// Clamp (no wrap) so Home/End and arrows stay within bounds.
|
|
144
|
+
targetIdx = Math.max(0, Math.min(list.length - 1, targetIdx));
|
|
145
|
+
const target = list[targetIdx]?.el;
|
|
146
|
+
if (target) {
|
|
147
|
+
tabStopEl.value = target;
|
|
148
|
+
target.focus();
|
|
149
|
+
bump();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const context = {
|
|
153
|
+
version,
|
|
154
|
+
managed: true,
|
|
155
|
+
itemRole: "option",
|
|
156
|
+
register,
|
|
157
|
+
isSelected,
|
|
158
|
+
isTabStop,
|
|
159
|
+
activate,
|
|
160
|
+
focusRow,
|
|
161
|
+
navigate,
|
|
162
|
+
};
|
|
163
|
+
provide(SELECTABLE_LIST_KEY, context);
|
|
164
|
+
return () => h("div", {
|
|
165
|
+
...attrs,
|
|
166
|
+
class: classNames("st-selectableList", props.class),
|
|
167
|
+
role: "listbox",
|
|
168
|
+
"aria-label": props.labelledby ? undefined : props.label,
|
|
169
|
+
"aria-labelledby": props.labelledby,
|
|
170
|
+
"aria-multiselectable": props.multiple ? "true" : undefined,
|
|
171
|
+
}, slots.default?.());
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
//# sourceMappingURL=SelectableList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectableList.js","sourceRoot":"","sources":["../src/SelectableList.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { type InjectionKey, type PropType, type VNode } from "vue";
|
|
2
|
+
/**
|
|
3
|
+
* Shared context contract between {@link SelectableList} and its slotted
|
|
4
|
+
* {@link SelectableRow} children. The list owns selection + the roving tabindex
|
|
5
|
+
* and exposes the getters/callbacks the rows read to derive their own `role` /
|
|
6
|
+
* `tabindex` / `aria-selected`. When a row is used STANDALONE (no provider)
|
|
7
|
+
* `inject` returns undefined and the row falls back to its own state.
|
|
8
|
+
*/
|
|
9
|
+
export type SelectableListContext = {
|
|
10
|
+
/** Reactive bump incremented on every selection / focus / registry change. */
|
|
11
|
+
version: {
|
|
12
|
+
value: number;
|
|
13
|
+
};
|
|
14
|
+
/** True when the list manages selection/roving for its rows. */
|
|
15
|
+
readonly managed: true;
|
|
16
|
+
/** listbox role for the wrapper → rows are "option". */
|
|
17
|
+
readonly itemRole: "option";
|
|
18
|
+
/** Register a row element; returns an unregister callback. */
|
|
19
|
+
register: (el: HTMLElement, value: string | undefined) => () => void;
|
|
20
|
+
/** Is the row with this element currently selected? */
|
|
21
|
+
isSelected: (el: HTMLElement) => boolean;
|
|
22
|
+
/** Should the row with this element be the roving-tabindex stop (tabindex 0)? */
|
|
23
|
+
isTabStop: (el: HTMLElement) => boolean;
|
|
24
|
+
/** Row was activated (click / Space / Enter). The list toggles selection. */
|
|
25
|
+
activate: (el: HTMLElement) => void;
|
|
26
|
+
/** Row received focus → becomes the roving tab stop. */
|
|
27
|
+
focusRow: (el: HTMLElement) => void;
|
|
28
|
+
/** Arrow / Home / End navigation from a row. */
|
|
29
|
+
navigate: (el: HTMLElement, key: string) => void;
|
|
30
|
+
};
|
|
31
|
+
export declare const SELECTABLE_LIST_KEY: InjectionKey<SelectableListContext>;
|
|
32
|
+
export type SelectableRowProps = {
|
|
33
|
+
/**
|
|
34
|
+
* Selected state. Honoured when the row is used STANDALONE; inside a
|
|
35
|
+
* {@link SelectableList} the list is the source of truth, so this prop is
|
|
36
|
+
* ignored for managed rows.
|
|
37
|
+
*/
|
|
38
|
+
selected?: boolean;
|
|
39
|
+
/** Notified on every toggle with the new selected state (standalone rows). */
|
|
40
|
+
onSelect?: (selected: boolean) => void;
|
|
41
|
+
/** Non-interactive when true. */
|
|
42
|
+
disabled?: boolean;
|
|
43
|
+
/** Stable value, surfaced as `data-value` and used by the list for `value`. */
|
|
44
|
+
value?: string;
|
|
45
|
+
/**
|
|
46
|
+
* ARIA role for the standalone row. Defaults to "option" so a lone row still
|
|
47
|
+
* reads as a selectable item. Inside a list the role is forced to "option".
|
|
48
|
+
*/
|
|
49
|
+
role?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Opt-in left accent bar on the selected state. Off by default so the
|
|
52
|
+
* selected item is a calm tinted surface + accented text (two signals only).
|
|
53
|
+
*/
|
|
54
|
+
accentBar?: boolean;
|
|
55
|
+
class?: string;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Compact, full-width selectable list/rail row. By DEFAULT the selected state
|
|
59
|
+
* is two calm signals — a tinted surface + accented text — deliberately NOT the
|
|
60
|
+
* off-theme "boudin box" it replaces, and NOT a reflow-causing font-weight
|
|
61
|
+
* bump. The fine left accent bar is OPT-IN via the `accentBar` prop. Focus is an
|
|
62
|
+
* EXTERNAL offset outline. role="option" + aria-selected, keyboard-activatable
|
|
63
|
+
* (Enter / Space), inert when disabled. Inside a {@link SelectableList} the list
|
|
64
|
+
* (via provide/inject) owns selection and the roving tabindex.
|
|
65
|
+
* Slots: default (content), leading (icon / avatar), trailing (meta / icon).
|
|
66
|
+
*/
|
|
67
|
+
export declare const SelectableRow: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
68
|
+
selected: {
|
|
69
|
+
type: BooleanConstructor;
|
|
70
|
+
default: boolean;
|
|
71
|
+
};
|
|
72
|
+
onSelect: {
|
|
73
|
+
type: PropType<(selected: boolean) => void>;
|
|
74
|
+
default: undefined;
|
|
75
|
+
};
|
|
76
|
+
disabled: {
|
|
77
|
+
type: BooleanConstructor;
|
|
78
|
+
default: boolean;
|
|
79
|
+
};
|
|
80
|
+
value: {
|
|
81
|
+
type: StringConstructor;
|
|
82
|
+
default: undefined;
|
|
83
|
+
};
|
|
84
|
+
role: {
|
|
85
|
+
type: StringConstructor;
|
|
86
|
+
default: string;
|
|
87
|
+
};
|
|
88
|
+
accentBar: {
|
|
89
|
+
type: BooleanConstructor;
|
|
90
|
+
default: boolean;
|
|
91
|
+
};
|
|
92
|
+
class: {
|
|
93
|
+
type: StringConstructor;
|
|
94
|
+
default: undefined;
|
|
95
|
+
};
|
|
96
|
+
}>, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
97
|
+
[key: string]: any;
|
|
98
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
99
|
+
select: (_selected: boolean) => true;
|
|
100
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
101
|
+
selected: {
|
|
102
|
+
type: BooleanConstructor;
|
|
103
|
+
default: boolean;
|
|
104
|
+
};
|
|
105
|
+
onSelect: {
|
|
106
|
+
type: PropType<(selected: boolean) => void>;
|
|
107
|
+
default: undefined;
|
|
108
|
+
};
|
|
109
|
+
disabled: {
|
|
110
|
+
type: BooleanConstructor;
|
|
111
|
+
default: boolean;
|
|
112
|
+
};
|
|
113
|
+
value: {
|
|
114
|
+
type: StringConstructor;
|
|
115
|
+
default: undefined;
|
|
116
|
+
};
|
|
117
|
+
role: {
|
|
118
|
+
type: StringConstructor;
|
|
119
|
+
default: string;
|
|
120
|
+
};
|
|
121
|
+
accentBar: {
|
|
122
|
+
type: BooleanConstructor;
|
|
123
|
+
default: boolean;
|
|
124
|
+
};
|
|
125
|
+
class: {
|
|
126
|
+
type: StringConstructor;
|
|
127
|
+
default: undefined;
|
|
128
|
+
};
|
|
129
|
+
}>> & Readonly<{
|
|
130
|
+
onSelect?: ((_selected: boolean) => any) | undefined;
|
|
131
|
+
}>, {
|
|
132
|
+
class: string;
|
|
133
|
+
onSelect: (selected: boolean) => void;
|
|
134
|
+
disabled: boolean;
|
|
135
|
+
role: string;
|
|
136
|
+
value: string;
|
|
137
|
+
selected: boolean;
|
|
138
|
+
accentBar: boolean;
|
|
139
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
140
|
+
//# sourceMappingURL=SelectableRow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectableRow.d.ts","sourceRoot":"","sources":["../src/SelectableRow.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,KAAK,EACX,MAAM,KAAK,CAAC;AAGb;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,8EAA8E;IAC9E,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,8DAA8D;IAC9D,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,IAAI,CAAC;IACrE,uDAAuD;IACvD,UAAU,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC;IACzC,iFAAiF;IACjF,SAAS,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC;IACxC,6EAA6E;IAC7E,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IACpC,wDAAwD;IACxD,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IACpC,gDAAgD;IAChD,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,YAAY,CAAC,qBAAqB,CAEnE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa;;;;;;cAKF,QAAQ,CAAC,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;wBAUrC,OAAO;;;;;;;cAVP,QAAQ,CAAC,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAAjB,OAAO,KAAK,IAAI;;;;;;4EAiI1D,CAAC"}
|