@jirawatpyk/aura-react 5.10.1 → 5.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/README.md +25 -2
- package/dist/aura.bundle.js +679 -595
- package/dist/cjs/index.cjs +678 -594
- package/dist/esm/Checkbox.js +1 -1
- package/dist/esm/DataTable.js +13 -4
- package/dist/esm/FilterBar.js +1 -1
- package/dist/esm/FilterSelect.js +17 -0
- package/dist/esm/Select.js +82 -20
- package/dist/esm/index.js +2 -0
- package/dist/index.d.cts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/styles.css +53 -1
- package/dist/styles.layer.css +53 -1
- package/package.json +1 -1
package/dist/esm/Checkbox.js
CHANGED
|
@@ -50,7 +50,7 @@ const Checkbox = React.forwardRef(function Checkbox2(props, ref) {
|
|
|
50
50
|
checked: on,
|
|
51
51
|
tabIndex: props.tabIndex,
|
|
52
52
|
disabled: props.disabled,
|
|
53
|
-
"aria-describedby": descId,
|
|
53
|
+
"aria-describedby": cx(props["aria-describedby"], descId) || void 0,
|
|
54
54
|
"aria-label": labelled ? void 0 : props.label,
|
|
55
55
|
onChange: function(e) {
|
|
56
56
|
st[1](e.target.checked);
|
package/dist/esm/DataTable.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
4
|
import { useStrings, useLinkComponent } from "./locale.js";
|
|
5
|
-
import { cx, useMaybeControlled, compare, useIsoLayoutEffect, useMergedRef } from "./internal.js";
|
|
5
|
+
import { cx, devWarnOnce, useMaybeControlled, compare, useIsoLayoutEffect, useMergedRef } from "./internal.js";
|
|
6
6
|
import { Icon } from "./Icon.js";
|
|
7
7
|
import { IconButton } from "./IconButton.js";
|
|
8
8
|
import { Checkbox } from "./Checkbox.js";
|
|
@@ -416,6 +416,12 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
|
|
|
416
416
|
return rowHref ? /* @__PURE__ */ React.createElement(Link, { href: rowHref(r), className: "aura-table__row-link" }, content) : content;
|
|
417
417
|
}
|
|
418
418
|
const height = props.height || 0;
|
|
419
|
+
const autoRows = props.rowHeight === "auto" && !height;
|
|
420
|
+
if (props.rowHeight === "auto" && height)
|
|
421
|
+
devWarnOnce(
|
|
422
|
+
"table-row-height-auto",
|
|
423
|
+
'DataTable `rowHeight="auto"` is ignored with `height`: virtualized rows are one fixed height. Drop `height` (and paginate) to let rows grow.'
|
|
424
|
+
);
|
|
419
425
|
const virtual = !!height && !loading && pageRows.length > 0 && !stacked;
|
|
420
426
|
const stickyTotal = !!(props.footer && props.stickyFooter && rows.length && !loading);
|
|
421
427
|
const bodyH = Math.max(ROW_H, height - ROW_H - (stickyTotal ? ROW_H : 0));
|
|
@@ -940,6 +946,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
|
|
|
940
946
|
}
|
|
941
947
|
function rowCells(r, i, k, isSel) {
|
|
942
948
|
const ri = i + 1;
|
|
949
|
+
const selLabel = selectable && canSelect(r) ? props.rowSelectLabel && props.rowSelectLabel(r) || t.selectRow(k) : void 0;
|
|
943
950
|
const cells = [/* @__PURE__ */ React.createElement("span", { key: "__gl", className: "aura-table__gutter", "aria-hidden": true })];
|
|
944
951
|
if (selectable)
|
|
945
952
|
cells.push(
|
|
@@ -952,7 +959,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
|
|
|
952
959
|
className: cx("aura-table__sel", nPinned && "is-pinned"),
|
|
953
960
|
tabIndex: tabFor(ri, 0),
|
|
954
961
|
"data-rc": ri + ":0",
|
|
955
|
-
"aria-label": canSelect(r) ?
|
|
962
|
+
"aria-label": canSelect(r) ? selLabel : props.rowSelectDisabledLabel ? props.rowSelectDisabledLabel(r) : void 0,
|
|
956
963
|
onFocus: function(e) {
|
|
957
964
|
if (e.target === e.currentTarget) activeState[1]({ r: ri, c: 0 });
|
|
958
965
|
}
|
|
@@ -963,7 +970,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
|
|
|
963
970
|
hideLabel: true,
|
|
964
971
|
checked: isSel,
|
|
965
972
|
tabIndex: -1,
|
|
966
|
-
label:
|
|
973
|
+
label: selLabel,
|
|
967
974
|
onChange: function(on) {
|
|
968
975
|
toggle(k, on);
|
|
969
976
|
}
|
|
@@ -984,6 +991,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
|
|
|
984
991
|
"data-rc": ri + ":" + ci,
|
|
985
992
|
className: cx(
|
|
986
993
|
"aura-table__td",
|
|
994
|
+
autoRows && "aura-table__td--auto",
|
|
987
995
|
c.mono && "aura-table__mono",
|
|
988
996
|
c.align === "end" && "is-end",
|
|
989
997
|
pin && "is-pinned",
|
|
@@ -995,7 +1003,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
|
|
|
995
1003
|
if (activeState[0].r !== ri || activeState[0].c !== ci) activeState[1]({ r: ri, c: ci });
|
|
996
1004
|
}
|
|
997
1005
|
},
|
|
998
|
-
j === 0 ? rowLinkWrap(r, cellContent(c, r)) : cellContent(c, r)
|
|
1006
|
+
autoRows ? /* @__PURE__ */ React.createElement("span", { className: "aura-table__cell" }, j === 0 ? rowLinkWrap(r, cellContent(c, r)) : cellContent(c, r)) : j === 0 ? rowLinkWrap(r, cellContent(c, r)) : cellContent(c, r)
|
|
999
1007
|
)
|
|
1000
1008
|
);
|
|
1001
1009
|
});
|
|
@@ -1074,6 +1082,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
|
|
|
1074
1082
|
"aria-selected": selectable && canSelect(r) ? isSel : void 0,
|
|
1075
1083
|
className: cx(
|
|
1076
1084
|
"aura-table__row",
|
|
1085
|
+
autoRows && "aura-table__row--auto",
|
|
1077
1086
|
isSel && "is-selected",
|
|
1078
1087
|
(props.onRowActivate || rowHref) && "is-actionable"
|
|
1079
1088
|
),
|
package/dist/esm/FilterBar.js
CHANGED
|
@@ -55,7 +55,7 @@ const FilterBar = React.forwardRef(function FilterBar2(props, ref) {
|
|
|
55
55
|
ref,
|
|
56
56
|
role: "region",
|
|
57
57
|
"aria-label": props.label || t.filters,
|
|
58
|
-
className: cx("aura-filterbar", props.className)
|
|
58
|
+
className: cx("aura-filterbar", props.searchGrow && "aura-filterbar--grow", props.className)
|
|
59
59
|
},
|
|
60
60
|
/* @__PURE__ */ React.createElement("div", { className: "aura-filterbar__row" }, hasSearch ? /* @__PURE__ */ React.createElement("div", { className: "aura-input has-icon aura-filterbar__search" }, /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconSearch, null), className: "aura-input__icon" }), /* @__PURE__ */ React.createElement(
|
|
61
61
|
"input",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Select, FILTER_KEY } from "./Select.js";
|
|
4
|
+
import { omit } from "./internal.js";
|
|
5
|
+
const FilterSelect = React.forwardRef(function FilterSelect2(props, ref) {
|
|
6
|
+
const onChange = props.onChange;
|
|
7
|
+
const pass = Object.assign(omit(props, ["label", "allLabel", "onChange"]), {
|
|
8
|
+
[FILTER_KEY]: { name: props.label, allLabel: props.allLabel },
|
|
9
|
+
onChange: onChange ? function(e) {
|
|
10
|
+
onChange(e.target.value);
|
|
11
|
+
} : void 0
|
|
12
|
+
});
|
|
13
|
+
return /* @__PURE__ */ React.createElement(Select, { ...pass, ref });
|
|
14
|
+
});
|
|
15
|
+
export {
|
|
16
|
+
FilterSelect
|
|
17
|
+
};
|
package/dist/esm/Select.js
CHANGED
|
@@ -7,6 +7,7 @@ import { useDensity } from "./locale.js";
|
|
|
7
7
|
import { cx, devWarnOnce, omit, uid, useIsoLayoutEffect, useMergedRef, useMounted } from "./internal.js";
|
|
8
8
|
import { IconCheck, IconChevronDown } from "./icons.js";
|
|
9
9
|
const h = React.createElement;
|
|
10
|
+
const FILTER_KEY = "__auraFilter";
|
|
10
11
|
const FORM_KEYS = ["name", "form", "value", "defaultValue", "disabled", "autoComplete", "onInput", "onInvalid"];
|
|
11
12
|
const HANDLED_KEYS = FORM_KEYS.concat([
|
|
12
13
|
"onChange",
|
|
@@ -40,20 +41,49 @@ function readItems(el) {
|
|
|
40
41
|
};
|
|
41
42
|
});
|
|
42
43
|
}
|
|
43
|
-
function
|
|
44
|
+
function textOf(n) {
|
|
45
|
+
if (n == null || typeof n === "boolean") return "";
|
|
46
|
+
if (typeof n === "string" || typeof n === "number") return String(n);
|
|
47
|
+
if (Array.isArray(n)) return n.map(textOf).join("");
|
|
48
|
+
return React.isValidElement(n) ? textOf(n.props.children) : "";
|
|
49
|
+
}
|
|
50
|
+
function childOptions(children, off) {
|
|
51
|
+
const out = [];
|
|
52
|
+
React.Children.forEach(children, function(c) {
|
|
53
|
+
if (!React.isValidElement(c)) return;
|
|
54
|
+
const p = c.props;
|
|
55
|
+
if (c.type === "optgroup" || c.type === React.Fragment)
|
|
56
|
+
out.push.apply(out, childOptions(p.children, off || c.type === "optgroup" && !!p.disabled));
|
|
57
|
+
else if (c.type === "option") {
|
|
58
|
+
const label = textOf(p.children);
|
|
59
|
+
out.push({ value: p.value != null ? String(p.value) : label, label, disabled: off || !!p.disabled });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
function initialLabel(props, filter) {
|
|
44
65
|
const opts = (props.options || []).map(function(o) {
|
|
45
66
|
return typeof o === "object" ? o : { value: o, label: o };
|
|
46
|
-
});
|
|
47
|
-
const
|
|
67
|
+
}).concat(childOptions(props.children));
|
|
68
|
+
const first = opts.filter(function(o) {
|
|
69
|
+
return !o.disabled;
|
|
70
|
+
})[0];
|
|
71
|
+
const v = props.value !== void 0 && props.value !== null ? String(props.value) : props.defaultValue !== void 0 && props.defaultValue !== null ? String(props.defaultValue) : props.placeholder ? "" : first ? first.value : "";
|
|
48
72
|
const hit = opts.filter(function(o) {
|
|
49
73
|
return o.value === v;
|
|
50
74
|
})[0];
|
|
51
|
-
if (hit)
|
|
52
|
-
|
|
75
|
+
if (hit)
|
|
76
|
+
return {
|
|
77
|
+
label: filter && filter.allLabel && opts[0] && hit.value === opts[0].value ? filter.allLabel : hit.label,
|
|
78
|
+
full: hit.label,
|
|
79
|
+
empty: false
|
|
80
|
+
};
|
|
81
|
+
return { label: props.placeholder || "", full: props.placeholder || "", empty: true };
|
|
53
82
|
}
|
|
54
83
|
const Select = React.forwardRef(function Select2(props, ref) {
|
|
55
84
|
const auto = uid(), id = props.id || auto;
|
|
56
|
-
const
|
|
85
|
+
const filter = props[FILTER_KEY];
|
|
86
|
+
const rest = omit(props, FIELD_KEYS.concat(["children", FILTER_KEY]));
|
|
57
87
|
const opts = (props.options || []).map(function(o) {
|
|
58
88
|
const v = typeof o === "object" ? o : { value: o, label: o };
|
|
59
89
|
return /* @__PURE__ */ React.createElement("option", { key: v.value, value: v.value, disabled: v.disabled }, v.label);
|
|
@@ -68,7 +98,7 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
68
98
|
const live = !native && mounted;
|
|
69
99
|
const density = useDensity();
|
|
70
100
|
React.useEffect(function() {
|
|
71
|
-
if (props.label || props["aria-label"] || props["aria-labelledby"] || props.title) return;
|
|
101
|
+
if (filter || props.label || props["aria-label"] || props["aria-labelledby"] || props.title) return;
|
|
72
102
|
if (document.querySelector('label[for="' + id.replace(/["\\]/g, "\\$&") + '"]')) return;
|
|
73
103
|
devWarnOnce(
|
|
74
104
|
"select-name",
|
|
@@ -77,20 +107,24 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
77
107
|
}, []);
|
|
78
108
|
const selRef = React.useRef(null), trigRef = React.useRef(null), listRef = React.useRef(null);
|
|
79
109
|
const shown = React.useState(function() {
|
|
80
|
-
return initialLabel(props);
|
|
110
|
+
return initialLabel(props, filter);
|
|
81
111
|
});
|
|
82
112
|
const openState = React.useState(false), open = openState[0];
|
|
83
113
|
const activeState = React.useState(-1), active = activeState[0];
|
|
84
114
|
const items = React.useState([]);
|
|
85
115
|
const pos = React.useState(null);
|
|
86
116
|
const typed = React.useRef({ text: "", at: 0 });
|
|
117
|
+
const allLabel = React.useRef(void 0);
|
|
118
|
+
allLabel.current = filter ? filter.allLabel : void 0;
|
|
87
119
|
const sync = React.useCallback(function() {
|
|
88
120
|
const el = selRef.current;
|
|
89
121
|
if (!el) return;
|
|
90
122
|
const o = el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null;
|
|
91
|
-
const
|
|
123
|
+
const text = o ? o.textContent || "" : "";
|
|
124
|
+
const short = allLabel.current && el.selectedIndex === 0 ? allLabel.current : text;
|
|
125
|
+
const next = o ? { label: short, full: text, empty: o.value === "" } : { label: "", full: "", empty: true };
|
|
92
126
|
shown[1](function(cur) {
|
|
93
|
-
return cur.label === next.label && cur.empty === next.empty ? cur : next;
|
|
127
|
+
return cur.label === next.label && cur.full === next.full && cur.empty === next.empty ? cur : next;
|
|
94
128
|
});
|
|
95
129
|
}, []);
|
|
96
130
|
const hook = React.useCallback(
|
|
@@ -281,12 +315,16 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
281
315
|
const t = trigRef.current && trigRef.current.parentElement;
|
|
282
316
|
if (!t) return;
|
|
283
317
|
const r = t.getBoundingClientRect(), below = window.innerHeight - r.bottom - 8, above = r.top - 8, want = listRef.current ? listRef.current.scrollHeight : 320, up = below < Math.min(want, 200) && above > below;
|
|
318
|
+
const lw = listRef.current ? Math.max(r.width, listRef.current.offsetWidth) : r.width;
|
|
319
|
+
const rtl = getComputedStyle(t).direction === "rtl";
|
|
320
|
+
const left = lw <= r.width ? r.left : Math.max(8, Math.min(rtl ? r.right - lw : r.left, window.innerWidth - lw - 8));
|
|
284
321
|
pos[1]({
|
|
285
|
-
left
|
|
322
|
+
left,
|
|
286
323
|
width: r.width,
|
|
287
324
|
top: up ? void 0 : r.bottom + 4,
|
|
288
325
|
bottom: up ? window.innerHeight - r.top + 4 : void 0,
|
|
289
|
-
maxHeight: Math.min(320, (up ? above : below) - 4)
|
|
326
|
+
maxHeight: Math.min(320, (up ? above : below) - 4),
|
|
327
|
+
rtl
|
|
290
328
|
});
|
|
291
329
|
}
|
|
292
330
|
place();
|
|
@@ -319,7 +357,7 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
319
357
|
[open, active, pos[0] != null]
|
|
320
358
|
);
|
|
321
359
|
const described = [describedBy(id, props), rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
322
|
-
const field = (child) => /* @__PURE__ */ React.createElement(
|
|
360
|
+
const field = (child) => filter ? child : /* @__PURE__ */ React.createElement(
|
|
323
361
|
Field,
|
|
324
362
|
{
|
|
325
363
|
id,
|
|
@@ -334,6 +372,21 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
334
372
|
},
|
|
335
373
|
child
|
|
336
374
|
);
|
|
375
|
+
const nameId = id + "-name";
|
|
376
|
+
const face = filter ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", { id: nameId, className: "aura-filterselect__name", "aria-hidden": true }, filter.name), /* @__PURE__ */ React.createElement("span", { className: "aura-filterselect__value", "aria-hidden": shown[0].label !== shown[0].full || void 0 }, shown[0].label || " "), shown[0].label !== shown[0].full ? /* @__PURE__ */ React.createElement("span", { className: "aura-sr-only" }, shown[0].full) : null, /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconChevronDown, null), className: "aura-filterselect__chevron" })) : null;
|
|
377
|
+
if (!live && filter)
|
|
378
|
+
return /* @__PURE__ */ React.createElement("div", { className: cx("aura-filterselect", props.disabled && "is-disabled", props.className) }, /* @__PURE__ */ React.createElement("span", { className: "aura-filterselect__face", "aria-hidden": true, style: props.style }, face), h(
|
|
379
|
+
"select",
|
|
380
|
+
Object.assign(extra, omit(rest, ["style"]), {
|
|
381
|
+
ref: selMerged,
|
|
382
|
+
id,
|
|
383
|
+
className: "aura-filterselect__native",
|
|
384
|
+
"aria-label": rest["aria-label"] || (rest["aria-labelledby"] ? void 0 : filter.name),
|
|
385
|
+
"aria-describedby": described
|
|
386
|
+
}),
|
|
387
|
+
opts,
|
|
388
|
+
props.children
|
|
389
|
+
));
|
|
337
390
|
if (!live)
|
|
338
391
|
return field(
|
|
339
392
|
/* @__PURE__ */ React.createElement("div", { className: cx("aura-input aura-select", props.icon && "has-icon") }, props.icon ? /* @__PURE__ */ React.createElement(Icon, { name: props.icon, className: "aura-input__icon" }) : null, h(
|
|
@@ -354,7 +407,7 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
354
407
|
const optId = function(i) {
|
|
355
408
|
return id + "-opt-" + i;
|
|
356
409
|
};
|
|
357
|
-
const labelledBy = rest["aria-labelledby"] || (props.label ? labelId : void 0);
|
|
410
|
+
const labelledBy = rest["aria-labelledby"] || (filter && !rest["aria-label"] ? nameId : props.label ? labelId : void 0);
|
|
358
411
|
const selIndex = selRef.current ? selRef.current.selectedIndex : -1;
|
|
359
412
|
const option = function(it) {
|
|
360
413
|
const sel = selIndex === it.index;
|
|
@@ -400,6 +453,7 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
400
453
|
{
|
|
401
454
|
ref: listRef,
|
|
402
455
|
"data-density": density,
|
|
456
|
+
dir: pos[0] ? pos[0].rtl ? "rtl" : "ltr" : void 0,
|
|
403
457
|
className: "aura-combo__popover aura-select__popover",
|
|
404
458
|
style: pos[0] ? {
|
|
405
459
|
left: pos[0].left,
|
|
@@ -432,10 +486,17 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
432
486
|
/* @__PURE__ */ React.createElement(
|
|
433
487
|
"div",
|
|
434
488
|
{
|
|
435
|
-
className: cx(
|
|
489
|
+
className: cx(
|
|
490
|
+
filter ? "aura-filterselect" : "aura-input",
|
|
491
|
+
"aura-select aura-select--custom",
|
|
492
|
+
props.icon && "has-icon",
|
|
493
|
+
open && "is-open",
|
|
494
|
+
filter && props.disabled && "is-disabled",
|
|
495
|
+
filter && props.className
|
|
496
|
+
),
|
|
436
497
|
"data-invalid": props.error ? "" : void 0
|
|
437
498
|
},
|
|
438
|
-
props.icon ? /* @__PURE__ */ React.createElement(Icon, { name: props.icon, className: "aura-input__icon" }) : null,
|
|
499
|
+
props.icon && !filter ? /* @__PURE__ */ React.createElement(Icon, { name: props.icon, className: "aura-input__icon" }) : null,
|
|
439
500
|
h(
|
|
440
501
|
"select",
|
|
441
502
|
Object.assign(extra, pick(rest, FORM_KEYS), {
|
|
@@ -469,7 +530,7 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
469
530
|
type: "button",
|
|
470
531
|
role: "combobox",
|
|
471
532
|
form: id + "-no-form",
|
|
472
|
-
className: "aura-input__control aura-select__trigger",
|
|
533
|
+
className: filter ? "aura-select__trigger aura-filterselect__face" : "aura-input__control aura-select__trigger",
|
|
473
534
|
disabled: props.disabled,
|
|
474
535
|
tabIndex: rest.tabIndex,
|
|
475
536
|
"aria-haspopup": "listbox",
|
|
@@ -478,7 +539,7 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
478
539
|
"aria-activedescendant": open && active >= 0 ? optId(active) : void 0,
|
|
479
540
|
id,
|
|
480
541
|
"aria-label": rest["aria-label"],
|
|
481
|
-
"aria-labelledby": rest["aria-labelledby"],
|
|
542
|
+
"aria-labelledby": rest["aria-labelledby"] || (filter && !rest["aria-label"] ? nameId : void 0),
|
|
482
543
|
"aria-required": props.required || void 0,
|
|
483
544
|
"aria-invalid": props.error ? true : void 0,
|
|
484
545
|
"aria-describedby": described,
|
|
@@ -501,13 +562,14 @@ const Select = React.forwardRef(function Select2(props, ref) {
|
|
|
501
562
|
if (selRef.current) selRef.current.dispatchEvent(new FocusEvent("focusout", { bubbles: true }));
|
|
502
563
|
}
|
|
503
564
|
},
|
|
504
|
-
/* @__PURE__ */ React.createElement("span", { id: id + "-value", className: cx("aura-select__value", shown[0].empty && "is-placeholder") }, shown[0].label || " ")
|
|
565
|
+
face || /* @__PURE__ */ React.createElement("span", { id: id + "-value", className: cx("aura-select__value", shown[0].empty && "is-placeholder") }, shown[0].label || " ")
|
|
505
566
|
),
|
|
506
|
-
/* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconChevronDown, null), className: "aura-select__chevron" }),
|
|
567
|
+
filter ? null : /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconChevronDown, null), className: "aura-select__chevron" }),
|
|
507
568
|
popup
|
|
508
569
|
)
|
|
509
570
|
);
|
|
510
571
|
});
|
|
511
572
|
export {
|
|
573
|
+
FILTER_KEY,
|
|
512
574
|
Select
|
|
513
575
|
};
|
package/dist/esm/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import { Field } from "./Field.js";
|
|
|
10
10
|
import { TextField } from "./TextField.js";
|
|
11
11
|
import { Textarea } from "./Textarea.js";
|
|
12
12
|
import { Select } from "./Select.js";
|
|
13
|
+
import { FilterSelect } from "./FilterSelect.js";
|
|
13
14
|
import { RadioGroup } from "./RadioGroup.js";
|
|
14
15
|
import { Switch } from "./Switch.js";
|
|
15
16
|
import { Combobox, defaultFilter } from "./Combobox.js";
|
|
@@ -87,6 +88,7 @@ export {
|
|
|
87
88
|
Field,
|
|
88
89
|
FileUpload,
|
|
89
90
|
FilterBar,
|
|
91
|
+
FilterSelect,
|
|
90
92
|
FormErrorSummary,
|
|
91
93
|
Grid,
|
|
92
94
|
ICONS,
|
package/dist/index.d.cts
CHANGED
|
@@ -129,6 +129,9 @@ export interface DataTableProps<Row extends Record<string, any> = Record<string,
|
|
|
129
129
|
isRowSelectable?: RowCallback<boolean, Row> | undefined;
|
|
130
130
|
/** Accessible name for a rejected row's empty cell, e.g. `(r) => 'Not awaiting review'` (5.6). */
|
|
131
131
|
rowSelectDisabledLabel?: RowCallback<string, Row> | undefined;
|
|
132
|
+
/** Accessible name for a row's checkbox (and its cell), e.g. `(r) => 'Select ' + r.company` (5.11). Default: the
|
|
133
|
+
* `selectRow` string with the row key ("Select M-102"), also used when this returns an empty string. */
|
|
134
|
+
rowSelectLabel?: RowCallback<string, Row> | undefined;
|
|
132
135
|
/** Controlled selection (row keys); pair with onSelectionChange. */
|
|
133
136
|
selected?: Array<string | number> | undefined;
|
|
134
137
|
/** Initial selection when uncontrolled. */
|
|
@@ -175,6 +178,10 @@ export interface DataTableProps<Row extends Record<string, any> = Record<string,
|
|
|
175
178
|
onRowActivate?: RowCallback<void, Row> | undefined;
|
|
176
179
|
/** Fixed height in px: sticky header, and only the rows in view are rendered. */
|
|
177
180
|
height?: number | undefined;
|
|
181
|
+
/** `'auto'` (5.11): rows grow to fit content that wraps (two badges, a long name); cells stay vertically centred and
|
|
182
|
+
* rows keep at least the density's row height. Needs every row in the DOM, so it is ignored with `height`
|
|
183
|
+
* (virtualized rows are one fixed height). Default: one fixed-height line per row, long text ends in an ellipsis. */
|
|
184
|
+
rowHeight?: "auto" | undefined;
|
|
178
185
|
/** Column menu on every header, drag-to-reorder, and the show/hide columns button. */
|
|
179
186
|
columnControls?: boolean | undefined;
|
|
180
187
|
/** Set false to keep column controls but turn off reordering. */
|
|
@@ -256,7 +263,7 @@ export interface CheckboxProps extends Omit<React$1.InputHTMLAttributes<HTMLInpu
|
|
|
256
263
|
hideLabel?: boolean | undefined;
|
|
257
264
|
/** The visible label beside the box. */
|
|
258
265
|
children?: React$1.ReactNode | undefined;
|
|
259
|
-
/** Second line under the visible label
|
|
266
|
+
/** Second line under the visible label, linked by `aria-describedby` after any id you pass there (5.11). */
|
|
260
267
|
description?: React$1.ReactNode | undefined;
|
|
261
268
|
onChange?: ((checked: boolean) => void) | undefined;
|
|
262
269
|
disabled?: boolean | undefined;
|
|
@@ -394,6 +401,9 @@ export interface FilterBarProps {
|
|
|
394
401
|
actions?: React$1.ReactNode | undefined;
|
|
395
402
|
/** Accessible name of the region. Default "Filters". */
|
|
396
403
|
label?: string | undefined;
|
|
404
|
+
/** The search takes all the room the controls leave in its row, instead of stopping at 360px with the count and
|
|
405
|
+
* actions pushed to the end (5.12). */
|
|
406
|
+
searchGrow?: boolean | undefined;
|
|
397
407
|
className?: string | undefined;
|
|
398
408
|
}
|
|
399
409
|
/** One command in the palette. */
|
|
@@ -460,6 +470,20 @@ export interface SelectProps extends Omit<FieldProps, "label">, Omit<React$1.Sel
|
|
|
460
470
|
placeholder?: string | undefined;
|
|
461
471
|
icon?: IconInput | undefined;
|
|
462
472
|
}
|
|
473
|
+
/** A compact filter for FilterBar (5.12): "Status All ▾", as wide as its words. */
|
|
474
|
+
export interface FilterSelectProps extends Omit<React$1.SelectHTMLAttributes<HTMLSelectElement>, "onChange" | "value" | "defaultValue" | "multiple" | "size" | "placeholder" | "required" | "children"> {
|
|
475
|
+
/** The filter's name: shown first on the face ("Status") and its accessible name. */
|
|
476
|
+
label: string;
|
|
477
|
+
/** The choices; the first is the "all" choice. Or pass `<option>` children. */
|
|
478
|
+
options?: SelectOption[] | undefined;
|
|
479
|
+
children?: React$1.ReactNode | undefined;
|
|
480
|
+
value?: string | undefined;
|
|
481
|
+
defaultValue?: string | undefined;
|
|
482
|
+
onChange?: ((value: string) => void) | undefined;
|
|
483
|
+
/** A shorter word the face shows while the first option is chosen ("All" for "All statuses"). The list and screen
|
|
484
|
+
* readers keep the option's own text. */
|
|
485
|
+
allLabel?: string | undefined;
|
|
486
|
+
}
|
|
463
487
|
export type ChoiceOption = string | {
|
|
464
488
|
value: string;
|
|
465
489
|
label: string;
|
|
@@ -1331,6 +1355,9 @@ export declare const TextField: React$1.ForwardRefExoticComponent<TextFieldProps
|
|
|
1331
1355
|
export declare const Textarea: React$1.ForwardRefExoticComponent<TextareaProps & React$1.RefAttributes<HTMLTextAreaElement>>;
|
|
1332
1356
|
/** A select field: a button that opens an AURA list (5.3), over a real <select> that keeps forms, refs and events. */
|
|
1333
1357
|
export declare const Select: React$1.ForwardRefExoticComponent<SelectProps & React$1.RefAttributes<HTMLSelectElement>>;
|
|
1358
|
+
/** A compact filter for FilterBar (5.12): a small button reading "Status All ▾" that opens Select's list. The name
|
|
1359
|
+
* is the accessible name, the chosen option its value; forms, refs and the keyboard work as in Select. */
|
|
1360
|
+
export declare const FilterSelect: React$1.ForwardRefExoticComponent<FilterSelectProps & React$1.RefAttributes<HTMLSelectElement>>;
|
|
1334
1361
|
export declare const RadioGroup: React$1.ForwardRefExoticComponent<RadioGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
|
|
1335
1362
|
export declare const Switch: React$1.ForwardRefExoticComponent<SwitchProps & React$1.RefAttributes<HTMLButtonElement>>;
|
|
1336
1363
|
/** One value, or with `multiple` any number (chips). Two call signatures so value/onChange are typed for each. */
|
package/dist/index.d.ts
CHANGED
|
@@ -129,6 +129,9 @@ export interface DataTableProps<Row extends Record<string, any> = Record<string,
|
|
|
129
129
|
isRowSelectable?: RowCallback<boolean, Row> | undefined;
|
|
130
130
|
/** Accessible name for a rejected row's empty cell, e.g. `(r) => 'Not awaiting review'` (5.6). */
|
|
131
131
|
rowSelectDisabledLabel?: RowCallback<string, Row> | undefined;
|
|
132
|
+
/** Accessible name for a row's checkbox (and its cell), e.g. `(r) => 'Select ' + r.company` (5.11). Default: the
|
|
133
|
+
* `selectRow` string with the row key ("Select M-102"), also used when this returns an empty string. */
|
|
134
|
+
rowSelectLabel?: RowCallback<string, Row> | undefined;
|
|
132
135
|
/** Controlled selection (row keys); pair with onSelectionChange. */
|
|
133
136
|
selected?: Array<string | number> | undefined;
|
|
134
137
|
/** Initial selection when uncontrolled. */
|
|
@@ -175,6 +178,10 @@ export interface DataTableProps<Row extends Record<string, any> = Record<string,
|
|
|
175
178
|
onRowActivate?: RowCallback<void, Row> | undefined;
|
|
176
179
|
/** Fixed height in px: sticky header, and only the rows in view are rendered. */
|
|
177
180
|
height?: number | undefined;
|
|
181
|
+
/** `'auto'` (5.11): rows grow to fit content that wraps (two badges, a long name); cells stay vertically centred and
|
|
182
|
+
* rows keep at least the density's row height. Needs every row in the DOM, so it is ignored with `height`
|
|
183
|
+
* (virtualized rows are one fixed height). Default: one fixed-height line per row, long text ends in an ellipsis. */
|
|
184
|
+
rowHeight?: "auto" | undefined;
|
|
178
185
|
/** Column menu on every header, drag-to-reorder, and the show/hide columns button. */
|
|
179
186
|
columnControls?: boolean | undefined;
|
|
180
187
|
/** Set false to keep column controls but turn off reordering. */
|
|
@@ -256,7 +263,7 @@ export interface CheckboxProps extends Omit<React$1.InputHTMLAttributes<HTMLInpu
|
|
|
256
263
|
hideLabel?: boolean | undefined;
|
|
257
264
|
/** The visible label beside the box. */
|
|
258
265
|
children?: React$1.ReactNode | undefined;
|
|
259
|
-
/** Second line under the visible label
|
|
266
|
+
/** Second line under the visible label, linked by `aria-describedby` after any id you pass there (5.11). */
|
|
260
267
|
description?: React$1.ReactNode | undefined;
|
|
261
268
|
onChange?: ((checked: boolean) => void) | undefined;
|
|
262
269
|
disabled?: boolean | undefined;
|
|
@@ -394,6 +401,9 @@ export interface FilterBarProps {
|
|
|
394
401
|
actions?: React$1.ReactNode | undefined;
|
|
395
402
|
/** Accessible name of the region. Default "Filters". */
|
|
396
403
|
label?: string | undefined;
|
|
404
|
+
/** The search takes all the room the controls leave in its row, instead of stopping at 360px with the count and
|
|
405
|
+
* actions pushed to the end (5.12). */
|
|
406
|
+
searchGrow?: boolean | undefined;
|
|
397
407
|
className?: string | undefined;
|
|
398
408
|
}
|
|
399
409
|
/** One command in the palette. */
|
|
@@ -460,6 +470,20 @@ export interface SelectProps extends Omit<FieldProps, "label">, Omit<React$1.Sel
|
|
|
460
470
|
placeholder?: string | undefined;
|
|
461
471
|
icon?: IconInput | undefined;
|
|
462
472
|
}
|
|
473
|
+
/** A compact filter for FilterBar (5.12): "Status All ▾", as wide as its words. */
|
|
474
|
+
export interface FilterSelectProps extends Omit<React$1.SelectHTMLAttributes<HTMLSelectElement>, "onChange" | "value" | "defaultValue" | "multiple" | "size" | "placeholder" | "required" | "children"> {
|
|
475
|
+
/** The filter's name: shown first on the face ("Status") and its accessible name. */
|
|
476
|
+
label: string;
|
|
477
|
+
/** The choices; the first is the "all" choice. Or pass `<option>` children. */
|
|
478
|
+
options?: SelectOption[] | undefined;
|
|
479
|
+
children?: React$1.ReactNode | undefined;
|
|
480
|
+
value?: string | undefined;
|
|
481
|
+
defaultValue?: string | undefined;
|
|
482
|
+
onChange?: ((value: string) => void) | undefined;
|
|
483
|
+
/** A shorter word the face shows while the first option is chosen ("All" for "All statuses"). The list and screen
|
|
484
|
+
* readers keep the option's own text. */
|
|
485
|
+
allLabel?: string | undefined;
|
|
486
|
+
}
|
|
463
487
|
export type ChoiceOption = string | {
|
|
464
488
|
value: string;
|
|
465
489
|
label: string;
|
|
@@ -1331,6 +1355,9 @@ export declare const TextField: React$1.ForwardRefExoticComponent<TextFieldProps
|
|
|
1331
1355
|
export declare const Textarea: React$1.ForwardRefExoticComponent<TextareaProps & React$1.RefAttributes<HTMLTextAreaElement>>;
|
|
1332
1356
|
/** A select field: a button that opens an AURA list (5.3), over a real <select> that keeps forms, refs and events. */
|
|
1333
1357
|
export declare const Select: React$1.ForwardRefExoticComponent<SelectProps & React$1.RefAttributes<HTMLSelectElement>>;
|
|
1358
|
+
/** A compact filter for FilterBar (5.12): a small button reading "Status All ▾" that opens Select's list. The name
|
|
1359
|
+
* is the accessible name, the chosen option its value; forms, refs and the keyboard work as in Select. */
|
|
1360
|
+
export declare const FilterSelect: React$1.ForwardRefExoticComponent<FilterSelectProps & React$1.RefAttributes<HTMLSelectElement>>;
|
|
1334
1361
|
export declare const RadioGroup: React$1.ForwardRefExoticComponent<RadioGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
|
|
1335
1362
|
export declare const Switch: React$1.ForwardRefExoticComponent<SwitchProps & React$1.RefAttributes<HTMLButtonElement>>;
|
|
1336
1363
|
/** One value, or with `multiple` any number (chips). Two call signatures so value/onChange are typed for each. */
|
package/dist/styles.css
CHANGED
|
@@ -130,7 +130,21 @@ a.aura-btn { text-decoration: none; }
|
|
|
130
130
|
box-sizing: border-box; height: 100%; line-height: calc(var(--aura-table-row-height) - 1px);
|
|
131
131
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-right: var(--aura-space-4);
|
|
132
132
|
}
|
|
133
|
-
|
|
133
|
+
/* 5.11 rowHeight="auto" (never virtualized): a row grows to fit what wraps in it; each cell centres its content.
|
|
134
|
+
* The padding only shows once content is taller than the row: a small Button or IconButton (32px), a pill or one line
|
|
135
|
+
* still fits the density's row height (7.5px above and below at 48px, 3.5px compact). */
|
|
136
|
+
.aura-table__row--auto { height: auto; min-height: var(--aura-table-row-height); }
|
|
137
|
+
.aura-table__td--auto {
|
|
138
|
+
--aura-cell-pad-y: clamp(0px, calc((var(--aura-table-row-height) - 1px - var(--aura-button-height-sm)) / 2), var(--aura-space-2));
|
|
139
|
+
display: flex; align-items: center; height: auto; line-height: 20px; white-space: normal;
|
|
140
|
+
padding-top: var(--aura-cell-pad-y); padding-bottom: var(--aura-cell-pad-y);
|
|
141
|
+
}
|
|
142
|
+
.aura-table__cell { flex: 1 1 auto; min-width: 0; overflow-wrap: break-word; }
|
|
143
|
+
/* Badges and pills side by side keep apart when they wrap onto a second line. */
|
|
144
|
+
.aura-table__cell > .aura-badge, .aura-table__cell > .aura-pill { vertical-align: middle; margin-top: 2px; margin-bottom: 2px; }
|
|
145
|
+
.aura-table__cell > .aura-badge:not(:last-child), .aura-table__cell > .aura-pill:not(:last-child) { margin-inline-end: var(--aura-space-1); }
|
|
146
|
+
.aura-table__td .aura-pill, .aura-table__td .aura-dropdown, .aura-table__td > .aura-icon-btn, .aura-table__td > .aura-btn,
|
|
147
|
+
.aura-table__cell > .aura-icon-btn, .aura-table__cell > .aura-btn { vertical-align: middle; }
|
|
134
148
|
.aura-table__th { position: relative; box-sizing: border-box; display: flex; align-items: center; padding-right: var(--aura-space-2); }
|
|
135
149
|
/* Column sizes come from custom properties set per cell (4.20), so the card layout can override them. */
|
|
136
150
|
.aura-table__th, .aura-table__td { flex: var(--aura-cell-flex, none); width: var(--aura-cell-w, auto); min-width: var(--aura-cell-min, 0); }
|
|
@@ -153,6 +167,10 @@ a.aura-btn { text-decoration: none; }
|
|
|
153
167
|
|
|
154
168
|
/* Selection column */
|
|
155
169
|
.aura-table__sel { width: var(--aura-table-select-width); flex: none; display: flex; align-items: center; background: inherit; }
|
|
170
|
+
/* 5.11: the selection box's invisible input reaches 24×24 (WCAG 2.5.8) around the 16px box it draws. Its left edge
|
|
171
|
+
* overlaps the sticky 24px gutter, so it sits one layer up — unless the column has scrolled under that gutter. */
|
|
172
|
+
.aura-table__sel .aura-check__input { inset: calc((var(--aura-icon-sm) - 24px) / 2); z-index: 2; }
|
|
173
|
+
.aura-table.is-scrolled-x .aura-table__sel:not(.is-pinned) .aura-check__input { z-index: auto; }
|
|
156
174
|
.aura-table__sel.is-pinned { position: sticky; left: var(--aura-space-6); z-index: 2; }
|
|
157
175
|
|
|
158
176
|
/* Pinned columns */
|
|
@@ -1345,6 +1363,37 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
1345
1363
|
.aura-filterbar__search { flex-basis: 100%; max-width: none; }
|
|
1346
1364
|
.aura-filterbar__spacer { display: none; }
|
|
1347
1365
|
}
|
|
1366
|
+
/* 5.12 searchGrow: the search fills what the controls leave. */
|
|
1367
|
+
.aura-filterbar--grow .aura-filterbar__search { max-width: none; }
|
|
1368
|
+
.aura-filterbar--grow .aura-filterbar__search ~ .aura-filterbar__spacer { display: none; }
|
|
1369
|
+
/* Compact filters sit closer together than full fields. */
|
|
1370
|
+
.aura-filterbar__controls:has(> .aura-filterselect) { gap: var(--aura-space-2); }
|
|
1371
|
+
|
|
1372
|
+
/* 5.12 FilterSelect: a compact face — "Status All ▾" — as wide as its words, over Select's machinery and list. */
|
|
1373
|
+
.aura-filterselect { position: relative; display: inline-flex; width: fit-content; max-width: 100%; vertical-align: middle; font-family: var(--font-sans); }
|
|
1374
|
+
.aura-filterselect__face {
|
|
1375
|
+
box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--aura-space-1); width: auto; max-width: 100%;
|
|
1376
|
+
min-height: var(--aura-input-height); padding-block: 0; padding-inline: var(--aura-space-2) var(--aura-space-1);
|
|
1377
|
+
background: var(--aura-bg-input); color: var(--aura-fg-primary);
|
|
1378
|
+
border: 1px solid var(--aura-border-control); border-radius: var(--aura-radius-md);
|
|
1379
|
+
font: inherit; font-size: 13px; line-height: 18px; text-align: start; cursor: pointer;
|
|
1380
|
+
transition: border-color var(--aura-duration-fast) var(--aura-ease);
|
|
1381
|
+
}
|
|
1382
|
+
.aura-filterselect__face:hover { border-color: var(--aura-fg-secondary); }
|
|
1383
|
+
.aura-filterselect__name { flex: none; white-space: nowrap; color: var(--aura-fg-secondary); }
|
|
1384
|
+
.aura-filterselect__value { min-width: 0; font-weight: 500; overflow-wrap: anywhere; }
|
|
1385
|
+
.aura-filterselect__chevron { flex: none; width: 14px; height: 14px; color: var(--aura-fg-secondary); }
|
|
1386
|
+
.aura-filterselect.is-open .aura-filterselect__chevron { transform: rotate(180deg); }
|
|
1387
|
+
.aura-filterselect__face:focus-visible, .aura-filterselect:has(.aura-filterselect__native:focus-visible) .aura-filterselect__face {
|
|
1388
|
+
outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 1px; border-color: var(--aura-border-strong);
|
|
1389
|
+
}
|
|
1390
|
+
.aura-filterselect__face:focus { outline-style: none; }
|
|
1391
|
+
.aura-filterselect__face:focus-visible { outline-style: solid; }
|
|
1392
|
+
/* Before hydration: the real <select>, invisible, over the face (16px so iOS doesn't zoom when it opens). */
|
|
1393
|
+
.aura-filterselect__native { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; opacity: 0; font-size: 16px; cursor: pointer; appearance: none; }
|
|
1394
|
+
.aura-filterselect.is-disabled .aura-filterselect__face { background: var(--aura-bg-input-disabled); color: var(--aura-fg-secondary); border-color: var(--aura-border-default); cursor: not-allowed; }
|
|
1395
|
+
.aura-filterselect.is-disabled .aura-filterselect__native { cursor: not-allowed; }
|
|
1396
|
+
@media (forced-colors: active) { .aura-filterselect__face { border-color: ButtonText; } }
|
|
1348
1397
|
|
|
1349
1398
|
/* Command palette: a search field over a grouped list, above everything else (it can open from a Dialog) */
|
|
1350
1399
|
.aura-dialog-layer.aura-command-layer { z-index: var(--aura-z-menu); align-items: flex-start; padding: 12vh var(--aura-space-4) var(--aura-space-4); }
|
|
@@ -1580,6 +1629,9 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
1580
1629
|
padding: 0; line-height: normal;
|
|
1581
1630
|
}
|
|
1582
1631
|
.aura-table__td[data-hide], .aura-table__head > .aura-table__th[data-hide] { display: block; }
|
|
1632
|
+
/* 5.11: rowHeight="auto" leaves cards as they are. */
|
|
1633
|
+
.aura-table__td--auto { display: block; white-space: nowrap; }
|
|
1634
|
+
.aura-table__td--auto .aura-table__cell > .aura-badge, .aura-table__td--auto .aura-table__cell > .aura-pill { margin: 0; }
|
|
1583
1635
|
.aura-table__spacer { display: none; }
|
|
1584
1636
|
.aura-table__td[data-label]::before {
|
|
1585
1637
|
content: attr(data-label); content: attr(data-label) / '';
|