@kapiuara/ui 0.1.0 → 0.2.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 +20 -0
- package/README.md +38 -1
- package/dist/components/data/KapiTable.d.ts +6 -0
- package/dist/components/data/KapiTable.js +359 -330
- package/dist/components/data/KapiTableFilter.d.ts +4 -1
- package/dist/components/data/KapiTableFilter.js +31 -29
- package/dist/components/inputs/KapiFacetedSearch.d.ts +4 -1
- package/dist/components/inputs/KapiFacetedSearch.js +68 -66
- package/dist/components/layout/KapiShell.js +1 -0
- package/dist/kapi.css +1 -1
- package/dist/kapi.layered.css +1 -1
- package/package.json +21 -20
|
@@ -11,6 +11,9 @@ export type KapiTableFilterLabels = {
|
|
|
11
11
|
filterAll: string;
|
|
12
12
|
/** Separador del contador "N de M". */
|
|
13
13
|
of: string;
|
|
14
|
+
/** Nombre accesible de la región `role="search"`. Dos filtros en la misma página son
|
|
15
|
+
* indistinguibles sin él; `aria-label` del consumidor lo pisa. */
|
|
16
|
+
region: string;
|
|
14
17
|
};
|
|
15
18
|
export declare const DEFAULT_TABLE_FILTER_LABELS: KapiTableFilterLabels;
|
|
16
19
|
/** Atributos nativos (`id`, `style`, `data-*`…) van a la región `role="search"` (el rol es propio). */
|
|
@@ -45,4 +48,4 @@ export type KapiTableFilterProps = Omit<HTMLAttributes<HTMLDivElement>, "childre
|
|
|
45
48
|
* lugar de la pantalla y conectarla al `filter`/`onFilterChange` de la tabla, o reemplazarla por una
|
|
46
49
|
* UI propia. Con `debounce` el campo va adelante del valor emitido.
|
|
47
50
|
*/
|
|
48
|
-
export declare function KapiTableFilter({ value, onChange, columns, count, debounce, label, size, labels, className, ...rest }: KapiTableFilterProps): import("react").JSX.Element;
|
|
51
|
+
export declare function KapiTableFilter({ value, onChange, columns, count, debounce, label, size, labels, className, "aria-label": ariaLabel, ...rest }: KapiTableFilterProps): import("react").JSX.Element;
|
|
@@ -16,64 +16,66 @@ var g = {
|
|
|
16
16
|
filterPlaceholder: "Filtrar…",
|
|
17
17
|
filterColumn: "Columna del filtro",
|
|
18
18
|
filterAll: "Todas",
|
|
19
|
-
of: "de"
|
|
19
|
+
of: "de",
|
|
20
|
+
region: "Filtro de la tabla"
|
|
20
21
|
}, _ = "\0all", v = (e, t) => e.text === t.text && e.column === t.column;
|
|
21
|
-
function y({ value: y, onChange: b, columns: x, count: S, debounce: C = 0, label: w, size: T = "sm", labels: E, className: D,
|
|
22
|
-
let
|
|
23
|
-
v(
|
|
24
|
-
let
|
|
25
|
-
u(() => () => clearTimeout(
|
|
26
|
-
let
|
|
27
|
-
clearTimeout(
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
},
|
|
22
|
+
function y({ value: y, onChange: b, columns: x, count: S, debounce: C = 0, label: w, size: T = "sm", labels: E, className: D, "aria-label": O, ...k }) {
|
|
23
|
+
let A = n("tableFilter", g, E), j = f(() => o(x), [x]), [M, N] = m(y), P = p(y), [F, I] = m(y);
|
|
24
|
+
v(F, y) || (I(y), v(P.current, y) || N(y));
|
|
25
|
+
let L = p(void 0);
|
|
26
|
+
u(() => () => clearTimeout(L.current), []);
|
|
27
|
+
let R = (e) => {
|
|
28
|
+
clearTimeout(L.current), P.current = e, b(e);
|
|
29
|
+
}, z = (e, t) => {
|
|
30
|
+
N(e), clearTimeout(L.current), !t && C > 0 ? L.current = setTimeout(() => R(e), C) : R(e);
|
|
31
|
+
}, B = d(), V = /* @__PURE__ */ l(t, {
|
|
31
32
|
size: T,
|
|
32
33
|
className: "kapi-tablefilter__group",
|
|
33
34
|
children: [/* @__PURE__ */ c(i, {
|
|
34
|
-
id: `${
|
|
35
|
+
id: `${B}-col`,
|
|
35
36
|
searchable: !1,
|
|
36
|
-
"aria-label":
|
|
37
|
+
"aria-label": A.filterColumn,
|
|
37
38
|
className: "kapi-tablefilter__col",
|
|
38
39
|
options: [{
|
|
39
40
|
value: _,
|
|
40
|
-
label:
|
|
41
|
-
}, ...
|
|
42
|
-
value:
|
|
41
|
+
label: A.filterAll
|
|
42
|
+
}, ...j],
|
|
43
|
+
value: M.column ?? _,
|
|
43
44
|
onChange: (e) => {
|
|
44
|
-
e !== null &&
|
|
45
|
-
...
|
|
45
|
+
e !== null && z({
|
|
46
|
+
...M,
|
|
46
47
|
column: e === _ ? null : e
|
|
47
48
|
}, !0);
|
|
48
49
|
}
|
|
49
50
|
}), /* @__PURE__ */ c(r, {
|
|
50
|
-
id:
|
|
51
|
+
id: B,
|
|
51
52
|
type: "search",
|
|
52
|
-
"aria-label": w == null ?
|
|
53
|
-
placeholder:
|
|
53
|
+
"aria-label": w == null ? A.filter : void 0,
|
|
54
|
+
placeholder: A.filterPlaceholder,
|
|
54
55
|
spellCheck: !1,
|
|
55
56
|
startIcon: /* @__PURE__ */ c(h, {}),
|
|
56
57
|
clearable: !0,
|
|
57
|
-
value:
|
|
58
|
-
onChange: (e) =>
|
|
59
|
-
...
|
|
58
|
+
value: M.text,
|
|
59
|
+
onChange: (e) => z({
|
|
60
|
+
...M,
|
|
60
61
|
text: e.target.value
|
|
61
62
|
}, !1)
|
|
62
63
|
})]
|
|
63
64
|
});
|
|
64
65
|
return /* @__PURE__ */ l("div", {
|
|
65
|
-
...
|
|
66
|
+
...k,
|
|
66
67
|
className: a("kapi-tablefilter", D),
|
|
67
68
|
role: "search",
|
|
68
|
-
|
|
69
|
+
"aria-label": O ?? A.region,
|
|
70
|
+
children: [w == null ? V : /* @__PURE__ */ c(e, {
|
|
69
71
|
label: w,
|
|
70
|
-
htmlFor:
|
|
72
|
+
htmlFor: B,
|
|
71
73
|
className: "kapi-tablefilter__field",
|
|
72
|
-
children:
|
|
74
|
+
children: V
|
|
73
75
|
}), /* @__PURE__ */ c("span", {
|
|
74
76
|
className: "kapi-tablefilter__count",
|
|
75
77
|
"aria-live": "polite",
|
|
76
|
-
children: S && s(y) ? `${S.shown} ${
|
|
78
|
+
children: S && s(y) ? `${S.shown} ${A.of} ${S.total}` : ""
|
|
77
79
|
})]
|
|
78
80
|
});
|
|
79
81
|
}
|
|
@@ -5,6 +5,9 @@ import type { KapiLabelsOverride } from "../labelsLogic";
|
|
|
5
5
|
export type KapiFacetedSearchLabels = {
|
|
6
6
|
/** Nombre accesible del campo. */
|
|
7
7
|
input: string;
|
|
8
|
+
/** Nombre accesible de la región `role="search"`. Dos búsquedas en la misma página son
|
|
9
|
+
* indistinguibles sin él; `aria-label` del consumidor lo pisa. */
|
|
10
|
+
region: string;
|
|
8
11
|
placeholder: string;
|
|
9
12
|
/** "Buscar “texto”" en el desplegable. */
|
|
10
13
|
searchFor: string;
|
|
@@ -42,4 +45,4 @@ export type KapiFacetedSearchProps = Omit<HTMLAttributes<HTMLDivElement>, "child
|
|
|
42
45
|
* Teclado: flechas y Enter en el desplegable, Backspace con el campo vacío suelta la faceta pendiente
|
|
43
46
|
* y después el último chip, Escape cancela la faceta pendiente.
|
|
44
47
|
*/
|
|
45
|
-
export declare function KapiFacetedSearch({ facets, chips, onText, onClearAll, labels, className, onMouseDown, ...rest }: KapiFacetedSearchProps): import("react").JSX.Element;
|
|
48
|
+
export declare function KapiFacetedSearch({ facets, chips, onText, onClearAll, labels, className, onMouseDown, "aria-label": ariaLabel, ...rest }: KapiFacetedSearchProps): import("react").JSX.Element;
|
|
@@ -13,6 +13,7 @@ import { Search as y } from "lucide-react";
|
|
|
13
13
|
//#region src/components/inputs/KapiFacetedSearch.tsx
|
|
14
14
|
var b = {
|
|
15
15
|
input: "Buscar o filtrar",
|
|
16
|
+
region: "Búsqueda",
|
|
16
17
|
placeholder: "Buscar o filtrar…",
|
|
17
18
|
searchFor: "Buscar",
|
|
18
19
|
pickValue: "elegir valor…",
|
|
@@ -21,56 +22,57 @@ var b = {
|
|
|
21
22
|
valueOf: "Valor de",
|
|
22
23
|
clearAll: "Limpiar todo"
|
|
23
24
|
};
|
|
24
|
-
function x({ facets: x, chips: S, onText: C, onClearAll: w, labels: T, className: E, onMouseDown: D,
|
|
25
|
-
let
|
|
26
|
-
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
}, Y = (e) => {
|
|
30
|
-
e.type === "text" ? (C(e.text), J()) : e.type === "option" ? (L?.apply(e.option.value), J()) : e.facet.kind === "flag" ? (e.facet.apply("true"), J()) : (R(e.facet), I(""), H(-1), B(!0), l(e.facet) ? requestAnimationFrame(() => P.current?.focus()) : K());
|
|
25
|
+
function x({ facets: x, chips: S, onText: C, onClearAll: w, labels: T, className: E, onMouseDown: D, "aria-label": O, ...k }) {
|
|
26
|
+
let A = e("facetedSearch", b, T), j = g(), M = `${j}-list`, N = _(null), P = _(null), F = _(null), [I, L] = v(""), [R, z] = v(null), [B, V] = v(!1), [H, U] = v(-1), W = s(x, R, I), G = l(R), K = B && !G, q = () => requestAnimationFrame(() => P.current?.focus()), J = () => {
|
|
27
|
+
L(""), z(null), U(-1);
|
|
28
|
+
}, Y = () => {
|
|
29
|
+
J(), V(!1), q();
|
|
31
30
|
}, X = (e) => {
|
|
31
|
+
e.type === "text" ? (C(e.text), Y()) : e.type === "option" ? (R?.apply(e.option.value), Y()) : e.facet.kind === "flag" ? (e.facet.apply("true"), Y()) : (z(e.facet), L(""), U(-1), V(!0), l(e.facet) ? requestAnimationFrame(() => F.current?.focus()) : q());
|
|
32
|
+
}, Z = (e) => {
|
|
32
33
|
let t = o(e.key, {
|
|
33
|
-
input:
|
|
34
|
-
pending: !!
|
|
35
|
-
active:
|
|
36
|
-
open:
|
|
34
|
+
input: I,
|
|
35
|
+
pending: !!R,
|
|
36
|
+
active: H,
|
|
37
|
+
open: K,
|
|
37
38
|
chips: S.length
|
|
38
39
|
});
|
|
39
40
|
if (t) switch (e.preventDefault(), t) {
|
|
40
41
|
case "next":
|
|
41
42
|
case "prev":
|
|
42
|
-
|
|
43
|
+
V(!0), U((e) => u(K ? e : -1, W.length, t === "next" ? 1 : -1));
|
|
43
44
|
break;
|
|
44
45
|
case "select": {
|
|
45
|
-
let e =
|
|
46
|
-
e &&
|
|
46
|
+
let e = W[H];
|
|
47
|
+
e && X(e);
|
|
47
48
|
break;
|
|
48
49
|
}
|
|
49
50
|
case "text":
|
|
50
|
-
C(
|
|
51
|
+
C(I.trim()), Y();
|
|
51
52
|
break;
|
|
52
53
|
case "cancel":
|
|
53
|
-
|
|
54
|
+
J();
|
|
54
55
|
break;
|
|
55
56
|
case "close":
|
|
56
|
-
|
|
57
|
+
V(!1), U(-1);
|
|
57
58
|
break;
|
|
58
59
|
case "dropPending":
|
|
59
|
-
|
|
60
|
+
z(null), U(-1);
|
|
60
61
|
break;
|
|
61
62
|
case "removeLast": S[S.length - 1]?.onRemove();
|
|
62
63
|
}
|
|
63
|
-
},
|
|
64
|
+
}, Q = (e) => {
|
|
64
65
|
let t = e.target.value === "";
|
|
65
|
-
(e.key === "Escape" || e.key === "Backspace" && t) && (e.preventDefault(),
|
|
66
|
-
},
|
|
66
|
+
(e.key === "Escape" || e.key === "Backspace" && t) && (e.preventDefault(), J(), q());
|
|
67
|
+
}, $ = (e) => `${j}-opt-${e}`;
|
|
67
68
|
return /* @__PURE__ */ h("div", {
|
|
68
|
-
...
|
|
69
|
-
ref:
|
|
69
|
+
...k,
|
|
70
|
+
ref: N,
|
|
70
71
|
className: t("kapi-facets", E),
|
|
71
72
|
role: "search",
|
|
73
|
+
"aria-label": O ?? A.region,
|
|
72
74
|
onMouseDown: (e) => {
|
|
73
|
-
D?.(e), !e.defaultPrevented && e.target === e.currentTarget && (e.preventDefault(),
|
|
75
|
+
D?.(e), !e.defaultPrevented && e.target === e.currentTarget && (e.preventDefault(), P.current?.focus(), V(!0));
|
|
74
76
|
},
|
|
75
77
|
children: [
|
|
76
78
|
/* @__PURE__ */ m(y, {
|
|
@@ -81,90 +83,90 @@ function x({ facets: x, chips: S, onText: C, onClearAll: w, labels: T, className
|
|
|
81
83
|
S.map((e) => /* @__PURE__ */ m(i, {
|
|
82
84
|
size: "sm",
|
|
83
85
|
onRemove: () => {
|
|
84
|
-
e.onRemove(),
|
|
86
|
+
e.onRemove(), q();
|
|
85
87
|
},
|
|
86
|
-
removeLabel: `${
|
|
88
|
+
removeLabel: `${A.remove} ${e.label}`,
|
|
87
89
|
children: e.label
|
|
88
90
|
}, e.key)),
|
|
89
|
-
|
|
91
|
+
R && /* @__PURE__ */ h(i, {
|
|
90
92
|
size: "sm",
|
|
91
93
|
tone: "primary",
|
|
92
94
|
className: "kapi-facets__pending",
|
|
93
|
-
children: [
|
|
95
|
+
children: [R.label, ":"]
|
|
94
96
|
}),
|
|
95
|
-
|
|
97
|
+
G && R ? /* @__PURE__ */ m("span", {
|
|
96
98
|
className: "kapi-facets__date",
|
|
97
|
-
onKeyDown:
|
|
98
|
-
children:
|
|
99
|
-
ref:
|
|
100
|
-
"aria-label": `${
|
|
99
|
+
onKeyDown: Q,
|
|
100
|
+
children: R.kind === "dateRange" ? /* @__PURE__ */ m(r, {
|
|
101
|
+
ref: F,
|
|
102
|
+
"aria-label": `${A.valueOf} ${R.label}`,
|
|
101
103
|
onChange: ({ from: e, to: t }) => {
|
|
102
|
-
e && t && (
|
|
104
|
+
e && t && (R.apply(d(e, t)), Y());
|
|
103
105
|
}
|
|
104
106
|
}) : /* @__PURE__ */ m(n, {
|
|
105
|
-
ref:
|
|
106
|
-
"aria-label": `${
|
|
107
|
+
ref: F,
|
|
108
|
+
"aria-label": `${A.valueOf} ${R.label}`,
|
|
107
109
|
onChange: (e) => {
|
|
108
|
-
e && (
|
|
110
|
+
e && (R.apply(f(e)), Y());
|
|
109
111
|
}
|
|
110
112
|
})
|
|
111
113
|
}) : /* @__PURE__ */ m("input", {
|
|
112
|
-
ref:
|
|
114
|
+
ref: P,
|
|
113
115
|
className: "kapi-facets__input",
|
|
114
116
|
type: "text",
|
|
115
117
|
role: "combobox",
|
|
116
118
|
autoComplete: "off",
|
|
117
|
-
"aria-label":
|
|
118
|
-
"aria-expanded":
|
|
119
|
-
"aria-controls":
|
|
119
|
+
"aria-label": A.input,
|
|
120
|
+
"aria-expanded": K,
|
|
121
|
+
"aria-controls": M,
|
|
120
122
|
"aria-autocomplete": "list",
|
|
121
|
-
"aria-activedescendant":
|
|
122
|
-
placeholder: S.length === 0 && !
|
|
123
|
-
value:
|
|
124
|
-
onFocus: () =>
|
|
125
|
-
onClick: () =>
|
|
123
|
+
"aria-activedescendant": K && H >= 0 ? $(H) : void 0,
|
|
124
|
+
placeholder: S.length === 0 && !R ? A.placeholder : void 0,
|
|
125
|
+
value: I,
|
|
126
|
+
onFocus: () => V(!0),
|
|
127
|
+
onClick: () => V(!0),
|
|
126
128
|
onBlur: (e) => {
|
|
127
129
|
let t = e.relatedTarget;
|
|
128
|
-
(!t || !
|
|
130
|
+
(!t || !N.current?.contains(t)) && V(!1);
|
|
129
131
|
},
|
|
130
132
|
onChange: (e) => {
|
|
131
|
-
|
|
133
|
+
L(e.target.value), V(!0), U(-1);
|
|
132
134
|
},
|
|
133
|
-
onKeyDown:
|
|
135
|
+
onKeyDown: Z
|
|
134
136
|
}),
|
|
135
137
|
w && S.length > 0 && /* @__PURE__ */ m("button", {
|
|
136
138
|
type: "button",
|
|
137
139
|
className: "kapi-facets__clear",
|
|
138
140
|
onClick: () => {
|
|
139
|
-
w(),
|
|
141
|
+
w(), J(), q();
|
|
140
142
|
},
|
|
141
|
-
children:
|
|
143
|
+
children: A.clearAll
|
|
142
144
|
}),
|
|
143
145
|
/* @__PURE__ */ h(a, {
|
|
144
|
-
open:
|
|
145
|
-
anchorRef:
|
|
146
|
-
onClose: () =>
|
|
146
|
+
open: K,
|
|
147
|
+
anchorRef: N,
|
|
148
|
+
onClose: () => V(!1),
|
|
147
149
|
matchAnchorWidth: !0,
|
|
148
150
|
role: "listbox",
|
|
149
|
-
id:
|
|
150
|
-
"aria-label":
|
|
151
|
+
id: M,
|
|
152
|
+
"aria-label": R ? R.label : A.input,
|
|
151
153
|
closeOnEscape: !1,
|
|
152
154
|
restoreFocus: !1,
|
|
153
155
|
className: "kapi-facets__menu",
|
|
154
|
-
children: [
|
|
156
|
+
children: [W.length === 0 && /* @__PURE__ */ m("div", {
|
|
155
157
|
className: "kapi-facets__empty",
|
|
156
|
-
children:
|
|
157
|
-
}),
|
|
158
|
-
id:
|
|
158
|
+
children: A.empty
|
|
159
|
+
}), W.map((e, t) => /* @__PURE__ */ m("div", {
|
|
160
|
+
id: $(t),
|
|
159
161
|
role: "option",
|
|
160
|
-
"aria-selected": t ===
|
|
162
|
+
"aria-selected": t === H,
|
|
161
163
|
"aria-label": e.type === "option" ? c(e.option) : void 0,
|
|
162
|
-
className: `kapi-facets__opt${t ===
|
|
164
|
+
className: `kapi-facets__opt${t === H ? " kapi-facets__opt--active" : ""}`,
|
|
163
165
|
onMouseDown: (e) => e.preventDefault(),
|
|
164
|
-
onMouseEnter: () =>
|
|
165
|
-
onClick: () =>
|
|
166
|
+
onMouseEnter: () => U(t),
|
|
167
|
+
onClick: () => X(e),
|
|
166
168
|
children: e.type === "text" ? /* @__PURE__ */ h("span", { children: [
|
|
167
|
-
|
|
169
|
+
A.searchFor,
|
|
168
170
|
" “",
|
|
169
171
|
e.text,
|
|
170
172
|
"”"
|
|
@@ -177,7 +179,7 @@ function x({ facets: x, chips: S, onText: C, onClearAll: w, labels: T, className
|
|
|
177
179
|
children: e.facet.label
|
|
178
180
|
}), e.facet.kind !== "flag" && /* @__PURE__ */ h("span", {
|
|
179
181
|
className: "kapi-facets__hint",
|
|
180
|
-
children: [" · ",
|
|
182
|
+
children: [" · ", A.pickValue]
|
|
181
183
|
})] })
|
|
182
184
|
}, e.type === "facet" ? `f-${e.facet.key}` : e.type === "option" ? `o-${e.option.value}` : "t"))]
|
|
183
185
|
})
|