@jirawatpyk/aura-react 5.11.0 → 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 +15 -2
- package/dist/aura.bundle.js +667 -592
- package/dist/cjs/index.cjs +666 -591
- 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 +20 -0
- package/dist/index.d.ts +20 -0
- package/dist/styles.css +31 -0
- package/dist/styles.layer.css +31 -0
- package/package.json +1 -1
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
|
@@ -401,6 +401,9 @@ export interface FilterBarProps {
|
|
|
401
401
|
actions?: React$1.ReactNode | undefined;
|
|
402
402
|
/** Accessible name of the region. Default "Filters". */
|
|
403
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;
|
|
404
407
|
className?: string | undefined;
|
|
405
408
|
}
|
|
406
409
|
/** One command in the palette. */
|
|
@@ -467,6 +470,20 @@ export interface SelectProps extends Omit<FieldProps, "label">, Omit<React$1.Sel
|
|
|
467
470
|
placeholder?: string | undefined;
|
|
468
471
|
icon?: IconInput | undefined;
|
|
469
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
|
+
}
|
|
470
487
|
export type ChoiceOption = string | {
|
|
471
488
|
value: string;
|
|
472
489
|
label: string;
|
|
@@ -1338,6 +1355,9 @@ export declare const TextField: React$1.ForwardRefExoticComponent<TextFieldProps
|
|
|
1338
1355
|
export declare const Textarea: React$1.ForwardRefExoticComponent<TextareaProps & React$1.RefAttributes<HTMLTextAreaElement>>;
|
|
1339
1356
|
/** A select field: a button that opens an AURA list (5.3), over a real <select> that keeps forms, refs and events. */
|
|
1340
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>>;
|
|
1341
1361
|
export declare const RadioGroup: React$1.ForwardRefExoticComponent<RadioGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
|
|
1342
1362
|
export declare const Switch: React$1.ForwardRefExoticComponent<SwitchProps & React$1.RefAttributes<HTMLButtonElement>>;
|
|
1343
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
|
@@ -401,6 +401,9 @@ export interface FilterBarProps {
|
|
|
401
401
|
actions?: React$1.ReactNode | undefined;
|
|
402
402
|
/** Accessible name of the region. Default "Filters". */
|
|
403
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;
|
|
404
407
|
className?: string | undefined;
|
|
405
408
|
}
|
|
406
409
|
/** One command in the palette. */
|
|
@@ -467,6 +470,20 @@ export interface SelectProps extends Omit<FieldProps, "label">, Omit<React$1.Sel
|
|
|
467
470
|
placeholder?: string | undefined;
|
|
468
471
|
icon?: IconInput | undefined;
|
|
469
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
|
+
}
|
|
470
487
|
export type ChoiceOption = string | {
|
|
471
488
|
value: string;
|
|
472
489
|
label: string;
|
|
@@ -1338,6 +1355,9 @@ export declare const TextField: React$1.ForwardRefExoticComponent<TextFieldProps
|
|
|
1338
1355
|
export declare const Textarea: React$1.ForwardRefExoticComponent<TextareaProps & React$1.RefAttributes<HTMLTextAreaElement>>;
|
|
1339
1356
|
/** A select field: a button that opens an AURA list (5.3), over a real <select> that keeps forms, refs and events. */
|
|
1340
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>>;
|
|
1341
1361
|
export declare const RadioGroup: React$1.ForwardRefExoticComponent<RadioGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
|
|
1342
1362
|
export declare const Switch: React$1.ForwardRefExoticComponent<SwitchProps & React$1.RefAttributes<HTMLButtonElement>>;
|
|
1343
1363
|
/** One value, or with `multiple` any number (chips). Two call signatures so value/onChange are typed for each. */
|
package/dist/styles.css
CHANGED
|
@@ -1363,6 +1363,37 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
1363
1363
|
.aura-filterbar__search { flex-basis: 100%; max-width: none; }
|
|
1364
1364
|
.aura-filterbar__spacer { display: none; }
|
|
1365
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; } }
|
|
1366
1397
|
|
|
1367
1398
|
/* Command palette: a search field over a grouped list, above everything else (it can open from a Dialog) */
|
|
1368
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); }
|
package/dist/styles.layer.css
CHANGED
|
@@ -1365,6 +1365,37 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
1365
1365
|
.aura-filterbar__search { flex-basis: 100%; max-width: none; }
|
|
1366
1366
|
.aura-filterbar__spacer { display: none; }
|
|
1367
1367
|
}
|
|
1368
|
+
/* 5.12 searchGrow: the search fills what the controls leave. */
|
|
1369
|
+
.aura-filterbar--grow .aura-filterbar__search { max-width: none; }
|
|
1370
|
+
.aura-filterbar--grow .aura-filterbar__search ~ .aura-filterbar__spacer { display: none; }
|
|
1371
|
+
/* Compact filters sit closer together than full fields. */
|
|
1372
|
+
.aura-filterbar__controls:has(> .aura-filterselect) { gap: var(--aura-space-2); }
|
|
1373
|
+
|
|
1374
|
+
/* 5.12 FilterSelect: a compact face — "Status All ▾" — as wide as its words, over Select's machinery and list. */
|
|
1375
|
+
.aura-filterselect { position: relative; display: inline-flex; width: fit-content; max-width: 100%; vertical-align: middle; font-family: var(--font-sans); }
|
|
1376
|
+
.aura-filterselect__face {
|
|
1377
|
+
box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--aura-space-1); width: auto; max-width: 100%;
|
|
1378
|
+
min-height: var(--aura-input-height); padding-block: 0; padding-inline: var(--aura-space-2) var(--aura-space-1);
|
|
1379
|
+
background: var(--aura-bg-input); color: var(--aura-fg-primary);
|
|
1380
|
+
border: 1px solid var(--aura-border-control); border-radius: var(--aura-radius-md);
|
|
1381
|
+
font: inherit; font-size: 13px; line-height: 18px; text-align: start; cursor: pointer;
|
|
1382
|
+
transition: border-color var(--aura-duration-fast) var(--aura-ease);
|
|
1383
|
+
}
|
|
1384
|
+
.aura-filterselect__face:hover { border-color: var(--aura-fg-secondary); }
|
|
1385
|
+
.aura-filterselect__name { flex: none; white-space: nowrap; color: var(--aura-fg-secondary); }
|
|
1386
|
+
.aura-filterselect__value { min-width: 0; font-weight: 500; overflow-wrap: anywhere; }
|
|
1387
|
+
.aura-filterselect__chevron { flex: none; width: 14px; height: 14px; color: var(--aura-fg-secondary); }
|
|
1388
|
+
.aura-filterselect.is-open .aura-filterselect__chevron { transform: rotate(180deg); }
|
|
1389
|
+
.aura-filterselect__face:focus-visible, .aura-filterselect:has(.aura-filterselect__native:focus-visible) .aura-filterselect__face {
|
|
1390
|
+
outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 1px; border-color: var(--aura-border-strong);
|
|
1391
|
+
}
|
|
1392
|
+
.aura-filterselect__face:focus { outline-style: none; }
|
|
1393
|
+
.aura-filterselect__face:focus-visible { outline-style: solid; }
|
|
1394
|
+
/* Before hydration: the real <select>, invisible, over the face (16px so iOS doesn't zoom when it opens). */
|
|
1395
|
+
.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; }
|
|
1396
|
+
.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; }
|
|
1397
|
+
.aura-filterselect.is-disabled .aura-filterselect__native { cursor: not-allowed; }
|
|
1398
|
+
@media (forced-colors: active) { .aura-filterselect__face { border-color: ButtonText; } }
|
|
1368
1399
|
|
|
1369
1400
|
/* Command palette: a search field over a grouped list, above everything else (it can open from a Dialog) */
|
|
1370
1401
|
.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); }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jirawatpyk/aura-react",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.12.0",
|
|
4
4
|
"description": "AURA Design System — React components (Enterprise Standard, Human Creative). Thai-first: Buddhist-era dates, Thai collation.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|