@jirawatpyk/aura-react 5.67.0 → 5.69.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 +11 -0
- package/dist/aura.bundle.js +67 -12
- package/dist/cjs/index.cjs +67 -12
- package/dist/esm/ActionBar.js +47 -1
- package/dist/esm/CheckboxGroup.js +3 -4
- package/dist/esm/Field.js +9 -1
- package/dist/esm/PageHeaderClient.js +1 -9
- package/dist/esm/RadioGroup.js +3 -4
- package/dist/esm/internal.js +9 -0
- package/dist/index.d.cts +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/styles.css +29 -0
- package/dist/styles.layer.css +29 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -186,6 +186,17 @@ DataTable with sort and page in the URL (4.17): `onStateChange={({ sort, page })
|
|
|
186
186
|
- **Time zone**: `timeZone` on AuraProvider, DatePicker, DateRangePicker and Calendar decides "today" (the marker, `min`/`max="today"`, the first month shown); or pass `today` as an ISO date. `todayIn('Asia/Bangkok')` is exported from the root and `/server`.
|
|
187
187
|
- **Toasts** queue past three instead of dropping: six in a row all show, in order, three at a time.
|
|
188
188
|
|
|
189
|
+
## 5.69 — Chamber-OS addendum 86 (#185)
|
|
190
|
+
|
|
191
|
+
- **ActionBar's edge look:** a `position="viewport"` bar takes `look="edge"` (every width) or `edgeBelow="sm"` / `"md"` (the strip below 640px / 768px, the card at and above it — as PageHeader's `actionsBarBelow`) and draws PageHeader's edge strip: the screen's full width, on the bottom edge or directly on a BottomNav, a top border only (no radius, shadow or top margin), the home-indicator inset as padding inside it. `look="floating"` (default) is the inset card, unchanged; a `container` bar ignores both props.
|
|
192
|
+
- **Its promises hold:** the strip is `position: fixed`, so it stays on screen for the whole page, not only while its form is. As PageHeader's bar, `<html>` gets its measured height as `--aura-actionbar-height` (60px before hydration; the home-indicator padding counts), the page's end is padded by it (AppShell's content, else the `body`) and `scroll-padding-bottom` keeps a focused field clear — so the last field, and anything after the form, scroll clear. The ActionBar root is the strip, so `getBoundingClientRect()` on it measures the strip. On a screen 30rem tall or less it is static, in the flow, as every bar. An idle bulk bar (`selected={0}`) stays folded away and adds no room. Drop your own clearance (a hook adding the bar's height to `scroll-padding-bottom` or page padding) when you adopt `look` / `edgeBelow`, or it is counted twice. Buttons stay 44px on a phone; `start`, `status`, `children`, the region and its label are unchanged.
|
|
193
|
+
- **Mind:** a transform, filter, `will-change` or paint containment on an ancestor places a fixed strip against that ancestor instead of the screen (a dev warning says so), and `look="edge"` at desktop widths spans the screen under a side nav — use `edgeBelow` for a phone-only strip. Passing both `look="edge"` and `edgeBelow` warns in development (`look` wins). Replace a hand-built `position: fixed` pay band with `<ActionBar edgeBelow="sm">`.
|
|
194
|
+
|
|
195
|
+
## 5.68 — Chamber-OS addendum 85 (#184)
|
|
196
|
+
|
|
197
|
+
- **A disabled group dims its legend:** `RadioGroup` and `CheckboxGroup` with `disabled` add `is-disabled` to the fieldset, so the legend takes the disabled colour (`fg-secondary`) a disabled `Field`'s label has — a form that disables its fields while submitting no longer shows group legends at full contrast over dimmed controls.
|
|
198
|
+
- **`errorLive` — an error line that announces:** on `CheckboxGroup`, `RadioGroup` and `Field`, `errorLive` gives the error line `aria-live="polite"` and keeps it in the page, empty and taking no room, while there is no error (the hint shows), so a message that appears as the user changes the field ("Choose at least one membership category" the moment the last box is unticked) is read once. Off by default: an error shown on submit, with focus moved to the field, is read already. Under a `Field`, your own control should still point at `{id}-error` in its `aria-describedby` while there is an error, so the message stays its description. Not on TextField and the other controls. Hand-written markup with an empty `.aura-field__error` placeholder is now hidden until it has content. Drop a hand-made `sr-only` `role="status"` beside the group.
|
|
199
|
+
|
|
189
200
|
## 5.67 — Chamber-OS addendum 84 (#183)
|
|
190
201
|
|
|
191
202
|
- **`CheckboxGroup` — RadioGroup's many-choice twin:** one `fieldset` named by its `legend`, with RadioGroup's props — `label`, `hint`, `error`, `required` (the same `*` marker), `disabled` (every box), `orientation`, `touchHeight` (44px rows), `options` (`{ value, label, description?, disabled? }` or strings), `name` — and a set of values: `value: string[]` / `defaultValue` / `onChange(values)`, always in option order whatever order they were ticked in. The group is described by the hint, or by the error line, which also marks every box `aria-invalid` and edges the empty ones. `required` shows the `*` and adds a hidden "(required)" to the group's name (localised), since a group can't take `aria-required` and a native `required` on each box would demand all of them; "at least one" is yours to check (pass `error`, which each box then also points at). Values not among the options (archived, still loading) are kept, after the others. `focus()` on the ref lands on the first ticked enabled box. Replaces a hand-made fieldset of Checkboxes.
|
package/dist/aura.bundle.js
CHANGED
|
@@ -409,6 +409,14 @@ window.Aura = (() => {
|
|
|
409
409
|
return !e.defaultPrevented && e.button === 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey;
|
|
410
410
|
}
|
|
411
411
|
var FilterSheet = React3.createContext(false);
|
|
412
|
+
function fixedTrapped(el) {
|
|
413
|
+
for (let p = el.parentElement; p && p !== document.documentElement; p = p.parentElement) {
|
|
414
|
+
const s = getComputedStyle(p);
|
|
415
|
+
if (s.transform !== "none" || s.filter !== "none" || (s.backdropFilter || "none") !== "none" || s.contentVisibility === "auto" || s.perspective !== "none" || /transform|filter|perspective/.test(s.willChange) || /paint|layout|strict|content/.test(s.contain))
|
|
416
|
+
return true;
|
|
417
|
+
}
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
412
420
|
|
|
413
421
|
// src/display.tsx
|
|
414
422
|
var React4 = __toESM(require_react(), 1);
|
|
@@ -2081,12 +2089,19 @@ window.Aura = (() => {
|
|
|
2081
2089
|
) : null,
|
|
2082
2090
|
hasAddon(props.labelAddon) ? /* @__PURE__ */ React13.createElement("div", { className: "aura-field__addon", id: props.id + "-addon" }, props.labelAddon) : null,
|
|
2083
2091
|
props.children,
|
|
2084
|
-
|
|
2092
|
+
fieldNote(props.id, props.error, props.hint, props.errorLive)
|
|
2085
2093
|
);
|
|
2086
2094
|
});
|
|
2087
2095
|
function describedBy(id, p) {
|
|
2088
2096
|
return p.error ? id + "-error" : p.hint ? id + "-hint" : void 0;
|
|
2089
2097
|
}
|
|
2098
|
+
function fieldNote(id, error, hint, live) {
|
|
2099
|
+
const err = error ? /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Icon, { name: /* @__PURE__ */ React13.createElement(IconCircleAlert, null), size: 14 }), error) : null;
|
|
2100
|
+
const hintLine = hint ? /* @__PURE__ */ React13.createElement("p", { className: "aura-field__hint", id: id + "-hint" }, hint) : null;
|
|
2101
|
+
if (!live)
|
|
2102
|
+
return err ? /* @__PURE__ */ React13.createElement("p", { className: "aura-field__error", id: id + "-error" }, err) : hintLine;
|
|
2103
|
+
return /* @__PURE__ */ React13.createElement(React13.Fragment, null, err ? null : hintLine, /* @__PURE__ */ React13.createElement("p", { className: "aura-field__error", id: id == null ? void 0 : id + "-error", "aria-live": "polite" }, err));
|
|
2104
|
+
}
|
|
2090
2105
|
function hasAddon(n3) {
|
|
2091
2106
|
return n3 != null && typeof n3 !== "boolean" && n3 !== "";
|
|
2092
2107
|
}
|
|
@@ -3872,6 +3887,7 @@ window.Aura = (() => {
|
|
|
3872
3887
|
className: cx(
|
|
3873
3888
|
"aura-field aura-radio-group",
|
|
3874
3889
|
props.error && "is-invalid",
|
|
3890
|
+
props.disabled && "is-disabled",
|
|
3875
3891
|
touchClass(props.touchHeight),
|
|
3876
3892
|
props.className
|
|
3877
3893
|
),
|
|
@@ -3901,7 +3917,7 @@ window.Aura = (() => {
|
|
|
3901
3917
|
}
|
|
3902
3918
|
), /* @__PURE__ */ React20.createElement("span", { className: "aura-choice__text" }, /* @__PURE__ */ React20.createElement("span", { className: "aura-choice__label", id: oid ? oid + "-label" : void 0 }, v.label), v.description ? /* @__PURE__ */ React20.createElement("span", { className: "aura-choice__desc", id: oid + "-desc" }, v.description) : null));
|
|
3903
3919
|
})),
|
|
3904
|
-
|
|
3920
|
+
fieldNote(id, props.error, props.hint, props.errorLive)
|
|
3905
3921
|
);
|
|
3906
3922
|
});
|
|
3907
3923
|
|
|
@@ -3936,6 +3952,7 @@ window.Aura = (() => {
|
|
|
3936
3952
|
className: cx(
|
|
3937
3953
|
"aura-field aura-radio-group aura-checkbox-group",
|
|
3938
3954
|
props.error && "is-invalid",
|
|
3955
|
+
props.disabled && "is-disabled",
|
|
3939
3956
|
touchClass(props.touchHeight),
|
|
3940
3957
|
props.className
|
|
3941
3958
|
),
|
|
@@ -3973,7 +3990,7 @@ window.Aura = (() => {
|
|
|
3973
3990
|
v.label
|
|
3974
3991
|
);
|
|
3975
3992
|
})),
|
|
3976
|
-
|
|
3993
|
+
fieldNote(id, props.error, props.hint, props.errorLive)
|
|
3977
3994
|
);
|
|
3978
3995
|
}
|
|
3979
3996
|
);
|
|
@@ -8104,14 +8121,6 @@ window.Aura = (() => {
|
|
|
8104
8121
|
// src/PageHeaderClient.tsx
|
|
8105
8122
|
var NAME = "--aura-page-actions-height";
|
|
8106
8123
|
var bars = [];
|
|
8107
|
-
function trapped(el) {
|
|
8108
|
-
for (let p = el.parentElement; p && p !== document.documentElement; p = p.parentElement) {
|
|
8109
|
-
const s = getComputedStyle(p);
|
|
8110
|
-
if (s.transform !== "none" || s.filter !== "none" || (s.backdropFilter || "none") !== "none" || s.contentVisibility === "auto" || s.perspective !== "none" || /transform|filter|perspective/.test(s.willChange) || /paint|layout|strict|content/.test(s.contain))
|
|
8111
|
-
return true;
|
|
8112
|
-
}
|
|
8113
|
-
return false;
|
|
8114
|
-
}
|
|
8115
8124
|
var PageHeader3 = React45.forwardRef(function PageHeader4(props, ref) {
|
|
8116
8125
|
const own = React45.useRef(null);
|
|
8117
8126
|
const merged = useMergedRef(ref, own);
|
|
@@ -8128,7 +8137,7 @@ window.Aura = (() => {
|
|
|
8128
8137
|
if (bars[bars.length - 1] !== sync) return;
|
|
8129
8138
|
if (getComputedStyle(el).position === "fixed") {
|
|
8130
8139
|
root.style.setProperty(NAME, el.offsetHeight + "px");
|
|
8131
|
-
if (!checked && (checked = true,
|
|
8140
|
+
if (!checked && (checked = true, fixedTrapped(el)))
|
|
8132
8141
|
devWarnOnce(
|
|
8133
8142
|
"pageheader-bar-trapped",
|
|
8134
8143
|
"PageHeader actionsBarBelow: an ancestor has a transform, filter, will-change or paint containment, so the fixed bar is placed against it instead of the screen. Remove it from the page header's ancestors."
|
|
@@ -8671,6 +8680,17 @@ window.Aura = (() => {
|
|
|
8671
8680
|
|
|
8672
8681
|
// src/ActionBar.tsx
|
|
8673
8682
|
var React50 = __toESM(require_react(), 1);
|
|
8683
|
+
var HEIGHT = "--aura-actionbar-height";
|
|
8684
|
+
var edges = [];
|
|
8685
|
+
function writeHeight() {
|
|
8686
|
+
const root = document.documentElement;
|
|
8687
|
+
for (let i = edges.length - 1; i >= 0; i--)
|
|
8688
|
+
if (getComputedStyle(edges[i]).position === "fixed") {
|
|
8689
|
+
root.style.setProperty(HEIGHT, edges[i].offsetHeight + "px");
|
|
8690
|
+
return;
|
|
8691
|
+
}
|
|
8692
|
+
root.style.removeProperty(HEIGHT);
|
|
8693
|
+
}
|
|
8674
8694
|
var ActionBar = React50.forwardRef(function ActionBar2(props, ref) {
|
|
8675
8695
|
const t = useStrings();
|
|
8676
8696
|
const bulk = props.selected != null;
|
|
@@ -8681,6 +8701,40 @@ window.Aura = (() => {
|
|
|
8681
8701
|
});
|
|
8682
8702
|
const cameFrom = React50.useRef(null);
|
|
8683
8703
|
const own = React50.useRef(null);
|
|
8704
|
+
const viewport = (props.position || "viewport") === "viewport";
|
|
8705
|
+
const edge = !viewport ? null : props.look === "edge" ? "all" : props.edgeBelow || null;
|
|
8706
|
+
if (props.look === "edge" && props.edgeBelow && viewport)
|
|
8707
|
+
devWarnOnce(
|
|
8708
|
+
"actionbar-edge-both",
|
|
8709
|
+
'ActionBar: look="edge" draws the edge strip at every width, so edgeBelow does nothing. Pass edgeBelow alone for a strip on a phone and the floating card above it.'
|
|
8710
|
+
);
|
|
8711
|
+
React50.useEffect(
|
|
8712
|
+
function() {
|
|
8713
|
+
const el = own.current;
|
|
8714
|
+
if (!edge || !el) return;
|
|
8715
|
+
let checked = false;
|
|
8716
|
+
function sync() {
|
|
8717
|
+
writeHeight();
|
|
8718
|
+
if (!checked && getComputedStyle(el).position === "fixed" && (checked = true, fixedTrapped(el)))
|
|
8719
|
+
devWarnOnce(
|
|
8720
|
+
"actionbar-edge-trapped",
|
|
8721
|
+
`ActionBar look="edge": an ancestor has a transform, filter, will-change or paint containment, so the fixed strip is placed against it instead of the screen. Remove it from the bar's ancestors.`
|
|
8722
|
+
);
|
|
8723
|
+
}
|
|
8724
|
+
edges.push(el);
|
|
8725
|
+
const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
|
|
8726
|
+
if (ro) ro.observe(el, { box: "border-box" });
|
|
8727
|
+
window.addEventListener("resize", sync);
|
|
8728
|
+
sync();
|
|
8729
|
+
return function() {
|
|
8730
|
+
if (ro) ro.disconnect();
|
|
8731
|
+
window.removeEventListener("resize", sync);
|
|
8732
|
+
edges.splice(edges.indexOf(el), 1);
|
|
8733
|
+
writeHeight();
|
|
8734
|
+
};
|
|
8735
|
+
},
|
|
8736
|
+
[edge, idle]
|
|
8737
|
+
);
|
|
8684
8738
|
function clear() {
|
|
8685
8739
|
props.onClearSelection();
|
|
8686
8740
|
setTimeout(function() {
|
|
@@ -8707,6 +8761,7 @@ window.Aura = (() => {
|
|
|
8707
8761
|
className: cx(
|
|
8708
8762
|
"aura-actionbar",
|
|
8709
8763
|
"aura-actionbar--" + (props.position || "viewport"),
|
|
8764
|
+
edge && (edge === "all" ? "aura-actionbar--edge" : "aura-actionbar--edge-below-" + edge),
|
|
8710
8765
|
idle && "is-idle",
|
|
8711
8766
|
props.className
|
|
8712
8767
|
)
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -391,6 +391,14 @@ function plainClick(e) {
|
|
|
391
391
|
return !e.defaultPrevented && e.button === 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey;
|
|
392
392
|
}
|
|
393
393
|
var FilterSheet = React3.createContext(false);
|
|
394
|
+
function fixedTrapped(el) {
|
|
395
|
+
for (let p = el.parentElement; p && p !== document.documentElement; p = p.parentElement) {
|
|
396
|
+
const s = getComputedStyle(p);
|
|
397
|
+
if (s.transform !== "none" || s.filter !== "none" || (s.backdropFilter || "none") !== "none" || s.contentVisibility === "auto" || s.perspective !== "none" || /transform|filter|perspective/.test(s.willChange) || /paint|layout|strict|content/.test(s.contain))
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
394
402
|
|
|
395
403
|
// src/display.tsx
|
|
396
404
|
var React4 = __toESM(require("react"), 1);
|
|
@@ -2063,12 +2071,19 @@ var Field = React13.forwardRef(function Field2(props, ref) {
|
|
|
2063
2071
|
) : null,
|
|
2064
2072
|
hasAddon(props.labelAddon) ? /* @__PURE__ */ React13.createElement("div", { className: "aura-field__addon", id: props.id + "-addon" }, props.labelAddon) : null,
|
|
2065
2073
|
props.children,
|
|
2066
|
-
|
|
2074
|
+
fieldNote(props.id, props.error, props.hint, props.errorLive)
|
|
2067
2075
|
);
|
|
2068
2076
|
});
|
|
2069
2077
|
function describedBy(id, p) {
|
|
2070
2078
|
return p.error ? id + "-error" : p.hint ? id + "-hint" : void 0;
|
|
2071
2079
|
}
|
|
2080
|
+
function fieldNote(id, error, hint, live) {
|
|
2081
|
+
const err = error ? /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Icon, { name: /* @__PURE__ */ React13.createElement(IconCircleAlert, null), size: 14 }), error) : null;
|
|
2082
|
+
const hintLine = hint ? /* @__PURE__ */ React13.createElement("p", { className: "aura-field__hint", id: id + "-hint" }, hint) : null;
|
|
2083
|
+
if (!live)
|
|
2084
|
+
return err ? /* @__PURE__ */ React13.createElement("p", { className: "aura-field__error", id: id + "-error" }, err) : hintLine;
|
|
2085
|
+
return /* @__PURE__ */ React13.createElement(React13.Fragment, null, err ? null : hintLine, /* @__PURE__ */ React13.createElement("p", { className: "aura-field__error", id: id == null ? void 0 : id + "-error", "aria-live": "polite" }, err));
|
|
2086
|
+
}
|
|
2072
2087
|
function hasAddon(n3) {
|
|
2073
2088
|
return n3 != null && typeof n3 !== "boolean" && n3 !== "";
|
|
2074
2089
|
}
|
|
@@ -3854,6 +3869,7 @@ var RadioGroup = React20.forwardRef(function RadioGroup2(props, ref) {
|
|
|
3854
3869
|
className: cx(
|
|
3855
3870
|
"aura-field aura-radio-group",
|
|
3856
3871
|
props.error && "is-invalid",
|
|
3872
|
+
props.disabled && "is-disabled",
|
|
3857
3873
|
touchClass(props.touchHeight),
|
|
3858
3874
|
props.className
|
|
3859
3875
|
),
|
|
@@ -3883,7 +3899,7 @@ var RadioGroup = React20.forwardRef(function RadioGroup2(props, ref) {
|
|
|
3883
3899
|
}
|
|
3884
3900
|
), /* @__PURE__ */ React20.createElement("span", { className: "aura-choice__text" }, /* @__PURE__ */ React20.createElement("span", { className: "aura-choice__label", id: oid ? oid + "-label" : void 0 }, v.label), v.description ? /* @__PURE__ */ React20.createElement("span", { className: "aura-choice__desc", id: oid + "-desc" }, v.description) : null));
|
|
3885
3901
|
})),
|
|
3886
|
-
|
|
3902
|
+
fieldNote(id, props.error, props.hint, props.errorLive)
|
|
3887
3903
|
);
|
|
3888
3904
|
});
|
|
3889
3905
|
|
|
@@ -3918,6 +3934,7 @@ var CheckboxGroup = React21.forwardRef(
|
|
|
3918
3934
|
className: cx(
|
|
3919
3935
|
"aura-field aura-radio-group aura-checkbox-group",
|
|
3920
3936
|
props.error && "is-invalid",
|
|
3937
|
+
props.disabled && "is-disabled",
|
|
3921
3938
|
touchClass(props.touchHeight),
|
|
3922
3939
|
props.className
|
|
3923
3940
|
),
|
|
@@ -3955,7 +3972,7 @@ var CheckboxGroup = React21.forwardRef(
|
|
|
3955
3972
|
v.label
|
|
3956
3973
|
);
|
|
3957
3974
|
})),
|
|
3958
|
-
|
|
3975
|
+
fieldNote(id, props.error, props.hint, props.errorLive)
|
|
3959
3976
|
);
|
|
3960
3977
|
}
|
|
3961
3978
|
);
|
|
@@ -8086,14 +8103,6 @@ var PageHeader = React44.forwardRef(function PageHeader2(props, ref) {
|
|
|
8086
8103
|
// src/PageHeaderClient.tsx
|
|
8087
8104
|
var NAME = "--aura-page-actions-height";
|
|
8088
8105
|
var bars = [];
|
|
8089
|
-
function trapped(el) {
|
|
8090
|
-
for (let p = el.parentElement; p && p !== document.documentElement; p = p.parentElement) {
|
|
8091
|
-
const s = getComputedStyle(p);
|
|
8092
|
-
if (s.transform !== "none" || s.filter !== "none" || (s.backdropFilter || "none") !== "none" || s.contentVisibility === "auto" || s.perspective !== "none" || /transform|filter|perspective/.test(s.willChange) || /paint|layout|strict|content/.test(s.contain))
|
|
8093
|
-
return true;
|
|
8094
|
-
}
|
|
8095
|
-
return false;
|
|
8096
|
-
}
|
|
8097
8106
|
var PageHeader3 = React45.forwardRef(function PageHeader4(props, ref) {
|
|
8098
8107
|
const own = React45.useRef(null);
|
|
8099
8108
|
const merged = useMergedRef(ref, own);
|
|
@@ -8110,7 +8119,7 @@ var PageHeader3 = React45.forwardRef(function PageHeader4(props, ref) {
|
|
|
8110
8119
|
if (bars[bars.length - 1] !== sync) return;
|
|
8111
8120
|
if (getComputedStyle(el).position === "fixed") {
|
|
8112
8121
|
root.style.setProperty(NAME, el.offsetHeight + "px");
|
|
8113
|
-
if (!checked && (checked = true,
|
|
8122
|
+
if (!checked && (checked = true, fixedTrapped(el)))
|
|
8114
8123
|
devWarnOnce(
|
|
8115
8124
|
"pageheader-bar-trapped",
|
|
8116
8125
|
"PageHeader actionsBarBelow: an ancestor has a transform, filter, will-change or paint containment, so the fixed bar is placed against it instead of the screen. Remove it from the page header's ancestors."
|
|
@@ -8653,6 +8662,17 @@ var AppShell = React49.forwardRef(function AppShell2(props, ref) {
|
|
|
8653
8662
|
|
|
8654
8663
|
// src/ActionBar.tsx
|
|
8655
8664
|
var React50 = __toESM(require("react"), 1);
|
|
8665
|
+
var HEIGHT = "--aura-actionbar-height";
|
|
8666
|
+
var edges = [];
|
|
8667
|
+
function writeHeight() {
|
|
8668
|
+
const root = document.documentElement;
|
|
8669
|
+
for (let i = edges.length - 1; i >= 0; i--)
|
|
8670
|
+
if (getComputedStyle(edges[i]).position === "fixed") {
|
|
8671
|
+
root.style.setProperty(HEIGHT, edges[i].offsetHeight + "px");
|
|
8672
|
+
return;
|
|
8673
|
+
}
|
|
8674
|
+
root.style.removeProperty(HEIGHT);
|
|
8675
|
+
}
|
|
8656
8676
|
var ActionBar = React50.forwardRef(function ActionBar2(props, ref) {
|
|
8657
8677
|
const t = useStrings();
|
|
8658
8678
|
const bulk = props.selected != null;
|
|
@@ -8663,6 +8683,40 @@ var ActionBar = React50.forwardRef(function ActionBar2(props, ref) {
|
|
|
8663
8683
|
});
|
|
8664
8684
|
const cameFrom = React50.useRef(null);
|
|
8665
8685
|
const own = React50.useRef(null);
|
|
8686
|
+
const viewport = (props.position || "viewport") === "viewport";
|
|
8687
|
+
const edge = !viewport ? null : props.look === "edge" ? "all" : props.edgeBelow || null;
|
|
8688
|
+
if (props.look === "edge" && props.edgeBelow && viewport)
|
|
8689
|
+
devWarnOnce(
|
|
8690
|
+
"actionbar-edge-both",
|
|
8691
|
+
'ActionBar: look="edge" draws the edge strip at every width, so edgeBelow does nothing. Pass edgeBelow alone for a strip on a phone and the floating card above it.'
|
|
8692
|
+
);
|
|
8693
|
+
React50.useEffect(
|
|
8694
|
+
function() {
|
|
8695
|
+
const el = own.current;
|
|
8696
|
+
if (!edge || !el) return;
|
|
8697
|
+
let checked = false;
|
|
8698
|
+
function sync() {
|
|
8699
|
+
writeHeight();
|
|
8700
|
+
if (!checked && getComputedStyle(el).position === "fixed" && (checked = true, fixedTrapped(el)))
|
|
8701
|
+
devWarnOnce(
|
|
8702
|
+
"actionbar-edge-trapped",
|
|
8703
|
+
`ActionBar look="edge": an ancestor has a transform, filter, will-change or paint containment, so the fixed strip is placed against it instead of the screen. Remove it from the bar's ancestors.`
|
|
8704
|
+
);
|
|
8705
|
+
}
|
|
8706
|
+
edges.push(el);
|
|
8707
|
+
const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
|
|
8708
|
+
if (ro) ro.observe(el, { box: "border-box" });
|
|
8709
|
+
window.addEventListener("resize", sync);
|
|
8710
|
+
sync();
|
|
8711
|
+
return function() {
|
|
8712
|
+
if (ro) ro.disconnect();
|
|
8713
|
+
window.removeEventListener("resize", sync);
|
|
8714
|
+
edges.splice(edges.indexOf(el), 1);
|
|
8715
|
+
writeHeight();
|
|
8716
|
+
};
|
|
8717
|
+
},
|
|
8718
|
+
[edge, idle]
|
|
8719
|
+
);
|
|
8666
8720
|
function clear() {
|
|
8667
8721
|
props.onClearSelection();
|
|
8668
8722
|
setTimeout(function() {
|
|
@@ -8689,6 +8743,7 @@ var ActionBar = React50.forwardRef(function ActionBar2(props, ref) {
|
|
|
8689
8743
|
className: cx(
|
|
8690
8744
|
"aura-actionbar",
|
|
8691
8745
|
"aura-actionbar--" + (props.position || "viewport"),
|
|
8746
|
+
edge && (edge === "all" ? "aura-actionbar--edge" : "aura-actionbar--edge-below-" + edge),
|
|
8692
8747
|
idle && "is-idle",
|
|
8693
8748
|
props.className
|
|
8694
8749
|
)
|
package/dist/esm/ActionBar.js
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { Button } from "./Button.js";
|
|
4
|
-
import { cx } from "./internal.js";
|
|
4
|
+
import { cx, devWarnOnce, fixedTrapped } from "./internal.js";
|
|
5
5
|
import { useStrings } from "./locale.js";
|
|
6
|
+
const HEIGHT = "--aura-actionbar-height";
|
|
7
|
+
const edges = [];
|
|
8
|
+
function writeHeight() {
|
|
9
|
+
const root = document.documentElement;
|
|
10
|
+
for (let i = edges.length - 1; i >= 0; i--)
|
|
11
|
+
if (getComputedStyle(edges[i]).position === "fixed") {
|
|
12
|
+
root.style.setProperty(HEIGHT, edges[i].offsetHeight + "px");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
root.style.removeProperty(HEIGHT);
|
|
16
|
+
}
|
|
6
17
|
const ActionBar = React.forwardRef(function ActionBar2(props, ref) {
|
|
7
18
|
const t = useStrings();
|
|
8
19
|
const bulk = props.selected != null;
|
|
@@ -13,6 +24,40 @@ const ActionBar = React.forwardRef(function ActionBar2(props, ref) {
|
|
|
13
24
|
});
|
|
14
25
|
const cameFrom = React.useRef(null);
|
|
15
26
|
const own = React.useRef(null);
|
|
27
|
+
const viewport = (props.position || "viewport") === "viewport";
|
|
28
|
+
const edge = !viewport ? null : props.look === "edge" ? "all" : props.edgeBelow || null;
|
|
29
|
+
if (props.look === "edge" && props.edgeBelow && viewport)
|
|
30
|
+
devWarnOnce(
|
|
31
|
+
"actionbar-edge-both",
|
|
32
|
+
'ActionBar: look="edge" draws the edge strip at every width, so edgeBelow does nothing. Pass edgeBelow alone for a strip on a phone and the floating card above it.'
|
|
33
|
+
);
|
|
34
|
+
React.useEffect(
|
|
35
|
+
function() {
|
|
36
|
+
const el = own.current;
|
|
37
|
+
if (!edge || !el) return;
|
|
38
|
+
let checked = false;
|
|
39
|
+
function sync() {
|
|
40
|
+
writeHeight();
|
|
41
|
+
if (!checked && getComputedStyle(el).position === "fixed" && (checked = true, fixedTrapped(el)))
|
|
42
|
+
devWarnOnce(
|
|
43
|
+
"actionbar-edge-trapped",
|
|
44
|
+
`ActionBar look="edge": an ancestor has a transform, filter, will-change or paint containment, so the fixed strip is placed against it instead of the screen. Remove it from the bar's ancestors.`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
edges.push(el);
|
|
48
|
+
const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
|
|
49
|
+
if (ro) ro.observe(el, { box: "border-box" });
|
|
50
|
+
window.addEventListener("resize", sync);
|
|
51
|
+
sync();
|
|
52
|
+
return function() {
|
|
53
|
+
if (ro) ro.disconnect();
|
|
54
|
+
window.removeEventListener("resize", sync);
|
|
55
|
+
edges.splice(edges.indexOf(el), 1);
|
|
56
|
+
writeHeight();
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
[edge, idle]
|
|
60
|
+
);
|
|
16
61
|
function clear() {
|
|
17
62
|
props.onClearSelection();
|
|
18
63
|
setTimeout(function() {
|
|
@@ -39,6 +84,7 @@ const ActionBar = React.forwardRef(function ActionBar2(props, ref) {
|
|
|
39
84
|
className: cx(
|
|
40
85
|
"aura-actionbar",
|
|
41
86
|
"aura-actionbar--" + (props.position || "viewport"),
|
|
87
|
+
edge && (edge === "all" ? "aura-actionbar--edge" : "aura-actionbar--edge-below-" + edge),
|
|
42
88
|
idle && "is-idle",
|
|
43
89
|
props.className
|
|
44
90
|
)
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { Checkbox } from "./Checkbox.js";
|
|
4
|
-
import { describedBy } from "./Field.js";
|
|
5
|
-
import { Icon } from "./Icon.js";
|
|
4
|
+
import { describedBy, fieldNote } from "./Field.js";
|
|
6
5
|
import { cx, touchClass, uid, useMaybeControlled } from "./internal.js";
|
|
7
6
|
import { useStrings } from "./locale.js";
|
|
8
|
-
import { IconCircleAlert } from "./icons.js";
|
|
9
7
|
const CheckboxGroup = React.forwardRef(
|
|
10
8
|
function CheckboxGroup2(props, ref) {
|
|
11
9
|
const t = useStrings();
|
|
@@ -35,6 +33,7 @@ const CheckboxGroup = React.forwardRef(
|
|
|
35
33
|
className: cx(
|
|
36
34
|
"aura-field aura-radio-group aura-checkbox-group",
|
|
37
35
|
props.error && "is-invalid",
|
|
36
|
+
props.disabled && "is-disabled",
|
|
38
37
|
touchClass(props.touchHeight),
|
|
39
38
|
props.className
|
|
40
39
|
),
|
|
@@ -72,7 +71,7 @@ const CheckboxGroup = React.forwardRef(
|
|
|
72
71
|
v.label
|
|
73
72
|
);
|
|
74
73
|
})),
|
|
75
|
-
|
|
74
|
+
fieldNote(id, props.error, props.hint, props.errorLive)
|
|
76
75
|
);
|
|
77
76
|
}
|
|
78
77
|
);
|
package/dist/esm/Field.js
CHANGED
|
@@ -27,12 +27,19 @@ const Field = React.forwardRef(function Field2(props, ref) {
|
|
|
27
27
|
) : null,
|
|
28
28
|
hasAddon(props.labelAddon) ? /* @__PURE__ */ React.createElement("div", { className: "aura-field__addon", id: props.id + "-addon" }, props.labelAddon) : null,
|
|
29
29
|
props.children,
|
|
30
|
-
|
|
30
|
+
fieldNote(props.id, props.error, props.hint, props.errorLive)
|
|
31
31
|
);
|
|
32
32
|
});
|
|
33
33
|
function describedBy(id, p) {
|
|
34
34
|
return p.error ? id + "-error" : p.hint ? id + "-hint" : void 0;
|
|
35
35
|
}
|
|
36
|
+
function fieldNote(id, error, hint, live) {
|
|
37
|
+
const err = error ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconCircleAlert, null), size: 14 }), error) : null;
|
|
38
|
+
const hintLine = hint ? /* @__PURE__ */ React.createElement("p", { className: "aura-field__hint", id: id + "-hint" }, hint) : null;
|
|
39
|
+
if (!live)
|
|
40
|
+
return err ? /* @__PURE__ */ React.createElement("p", { className: "aura-field__error", id: id + "-error" }, err) : hintLine;
|
|
41
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, err ? null : hintLine, /* @__PURE__ */ React.createElement("p", { className: "aura-field__error", id: id == null ? void 0 : id + "-error", "aria-live": "polite" }, err));
|
|
42
|
+
}
|
|
36
43
|
function hasAddon(n) {
|
|
37
44
|
return n != null && typeof n !== "boolean" && n !== "";
|
|
38
45
|
}
|
|
@@ -68,6 +75,7 @@ export {
|
|
|
68
75
|
FIELD_KEYS,
|
|
69
76
|
Field,
|
|
70
77
|
describedBy,
|
|
78
|
+
fieldNote,
|
|
71
79
|
hasAddon,
|
|
72
80
|
joinDescribedBy
|
|
73
81
|
};
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { PageHeader as StaticPageHeader } from "./PageHeader.js";
|
|
4
|
-
import { devWarnOnce, useMergedRef } from "./internal.js";
|
|
4
|
+
import { devWarnOnce, fixedTrapped as trapped, useMergedRef } from "./internal.js";
|
|
5
5
|
const NAME = "--aura-page-actions-height";
|
|
6
6
|
const bars = [];
|
|
7
|
-
function trapped(el) {
|
|
8
|
-
for (let p = el.parentElement; p && p !== document.documentElement; p = p.parentElement) {
|
|
9
|
-
const s = getComputedStyle(p);
|
|
10
|
-
if (s.transform !== "none" || s.filter !== "none" || (s.backdropFilter || "none") !== "none" || s.contentVisibility === "auto" || s.perspective !== "none" || /transform|filter|perspective/.test(s.willChange) || /paint|layout|strict|content/.test(s.contain))
|
|
11
|
-
return true;
|
|
12
|
-
}
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
7
|
const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
|
|
16
8
|
const own = React.useRef(null);
|
|
17
9
|
const merged = useMergedRef(ref, own);
|
package/dist/esm/RadioGroup.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import { describedBy } from "./Field.js";
|
|
4
|
-
import { Icon } from "./Icon.js";
|
|
3
|
+
import { describedBy, fieldNote } from "./Field.js";
|
|
5
4
|
import { cx, touchClass, uid, useMaybeControlled } from "./internal.js";
|
|
6
|
-
import { IconCircleAlert } from "./icons.js";
|
|
7
5
|
const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
|
|
8
6
|
const auto = uid(), id = props.id || auto;
|
|
9
7
|
const st = useMaybeControlled(
|
|
@@ -31,6 +29,7 @@ const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
|
|
|
31
29
|
className: cx(
|
|
32
30
|
"aura-field aura-radio-group",
|
|
33
31
|
props.error && "is-invalid",
|
|
32
|
+
props.disabled && "is-disabled",
|
|
34
33
|
touchClass(props.touchHeight),
|
|
35
34
|
props.className
|
|
36
35
|
),
|
|
@@ -60,7 +59,7 @@ const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
|
|
|
60
59
|
}
|
|
61
60
|
), /* @__PURE__ */ React.createElement("span", { className: "aura-choice__text" }, /* @__PURE__ */ React.createElement("span", { className: "aura-choice__label", id: oid ? oid + "-label" : void 0 }, v.label), v.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-choice__desc", id: oid + "-desc" }, v.description) : null));
|
|
62
61
|
})),
|
|
63
|
-
|
|
62
|
+
fieldNote(id, props.error, props.hint, props.errorLive)
|
|
64
63
|
);
|
|
65
64
|
});
|
|
66
65
|
export {
|
package/dist/esm/internal.js
CHANGED
|
@@ -109,6 +109,14 @@ function plainClick(e) {
|
|
|
109
109
|
return !e.defaultPrevented && e.button === 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey;
|
|
110
110
|
}
|
|
111
111
|
const FilterSheet = React.createContext(false);
|
|
112
|
+
function fixedTrapped(el) {
|
|
113
|
+
for (let p = el.parentElement; p && p !== document.documentElement; p = p.parentElement) {
|
|
114
|
+
const s = getComputedStyle(p);
|
|
115
|
+
if (s.transform !== "none" || s.filter !== "none" || (s.backdropFilter || "none") !== "none" || s.contentVisibility === "auto" || s.perspective !== "none" || /transform|filter|perspective/.test(s.willChange) || /paint|layout|strict|content/.test(s.contain))
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
112
120
|
export {
|
|
113
121
|
FOCUSABLE,
|
|
114
122
|
FilterSheet,
|
|
@@ -117,6 +125,7 @@ export {
|
|
|
117
125
|
compare,
|
|
118
126
|
cx,
|
|
119
127
|
devWarnOnce,
|
|
128
|
+
fixedTrapped,
|
|
120
129
|
focusFirst,
|
|
121
130
|
inClosedDetails,
|
|
122
131
|
isTabStop,
|
package/dist/index.d.cts
CHANGED
|
@@ -680,7 +680,12 @@ export interface RadioGroupProps extends FieldProps {
|
|
|
680
680
|
name?: string | undefined;
|
|
681
681
|
/** Default `vertical`. */
|
|
682
682
|
orientation?: "vertical" | "horizontal" | undefined;
|
|
683
|
+
/** Disables every option and (5.68) dims the legend, as Field does its label. */
|
|
683
684
|
disabled?: boolean | undefined;
|
|
685
|
+
/** 5.68 (Chamber-OS 184): announce the error line when it appears (`aria-live="polite"`) — for an error shown as
|
|
686
|
+
* the user changes the group ("Choose at least one…" when the last box is unticked), not on submit. The error line
|
|
687
|
+
* stays in the page, empty, while there is none, so the first message is read too. Off by default. */
|
|
688
|
+
errorLive?: boolean | undefined;
|
|
684
689
|
id?: string | undefined;
|
|
685
690
|
className?: string | undefined;
|
|
686
691
|
/** 44px rows (5.30, Chamber-OS 135), the one-line label centred: `true` below 640px or on a coarse pointer (touch
|
|
@@ -700,7 +705,12 @@ export interface CheckboxGroupProps extends FieldProps {
|
|
|
700
705
|
name?: string | undefined;
|
|
701
706
|
/** Default `vertical`. */
|
|
702
707
|
orientation?: "vertical" | "horizontal" | undefined;
|
|
708
|
+
/** Disables every option and (5.68) dims the legend, as Field does its label. */
|
|
703
709
|
disabled?: boolean | undefined;
|
|
710
|
+
/** 5.68 (Chamber-OS 184): announce the error line when it appears (`aria-live="polite"`) — for an error shown as
|
|
711
|
+
* the user changes the group ("Choose at least one…" when the last box is unticked), not on submit. The error line
|
|
712
|
+
* stays in the page, empty, while there is none, so the first message is read too. Off by default. */
|
|
713
|
+
errorLive?: boolean | undefined;
|
|
704
714
|
id?: string | undefined;
|
|
705
715
|
className?: string | undefined;
|
|
706
716
|
/** 44px rows, as RadioGroup: `true` below 640px or on a coarse pointer, `'always'` at every width. */
|
|
@@ -1504,6 +1514,16 @@ export interface ActionBarProps {
|
|
|
1504
1514
|
* parent, so they never cover the last field. Make it the last child of the form or card it belongs to: like any
|
|
1505
1515
|
* `position: sticky` element it sticks only while that parent is on screen. */
|
|
1506
1516
|
position?: "viewport" | "container" | undefined;
|
|
1517
|
+
/** 5.69 (Chamber-OS 185), `position="viewport"` only. `floating` (default): the inset card, bordered all round,
|
|
1518
|
+
* rounded, with a shadow. `edge`: PageHeader's edge strip at every width — the screen's full width, on the bottom
|
|
1519
|
+
* edge or on a BottomNav, a top border only, the home-indicator inset inside it. The strip is `position: fixed` and
|
|
1520
|
+
* stays on screen for the whole page (not only while its form is), so, as PageHeader's bar, the page gains its height
|
|
1521
|
+
* at the end (`--aura-actionbar-height` on `<html>`) and a focused field scrolls clear; on a screen 30rem tall or
|
|
1522
|
+
* less it is static, in the flow. For a strip on a phone only, use `edgeBelow`. */
|
|
1523
|
+
look?: "floating" | "edge" | undefined;
|
|
1524
|
+
/** 5.69 (Chamber-OS 185), `position="viewport"` only: the edge strip below this width (`sm` 640px, `md` 768px),
|
|
1525
|
+
* the `look` card at and above it — as PageHeader's `actionsBarBelow`. */
|
|
1526
|
+
edgeBelow?: "sm" | "md" | undefined;
|
|
1507
1527
|
/** 5.35 (DxT Monitor #14): while this bar is on the page, a BottomNav (and its spacer) is hidden and the bar takes the
|
|
1508
1528
|
* bottom edge — for a page whose own actions (Acknowledge, Visit site) replace the tab bar. Any element can do the
|
|
1509
1529
|
* same with the `data-aura-hide-bottomnav` attribute. */
|
|
@@ -1927,6 +1947,12 @@ export interface FieldComponentProps extends Omit<FieldPropsPublic, "label"> {
|
|
|
1927
1947
|
/** The control's id: the label points at it, and the hint/error ids derive from it. */
|
|
1928
1948
|
id?: string | undefined;
|
|
1929
1949
|
children?: React$1.ReactNode | undefined;
|
|
1950
|
+
/** 5.68 (Chamber-OS 184): announce the error line when it appears — for an error shown as the user types or ticks,
|
|
1951
|
+
* not on submit. The error `<p>` gets `aria-live="polite"` and stays in the page, empty, while there is no error, so
|
|
1952
|
+
* the first message is read too. Off by default: an error shown on submit, with focus moved to the field, is read
|
|
1953
|
+
* already, and a live line would read it twice. Your control should still point at `{id}-error` in its
|
|
1954
|
+
* `aria-describedby` while there is an error (TextField and the others do), so the message stays its description. */
|
|
1955
|
+
errorLive?: boolean | undefined;
|
|
1930
1956
|
/** 5.31 (Chamber-OS addendum 41): a node between the label and the control, in a `.aura-field__addon` box with the
|
|
1931
1957
|
* id `{id}-addon`. TextField and Textarea add that id to the input's `aria-describedby`; a custom control should too. */
|
|
1932
1958
|
labelAddon?: React$1.ReactNode | undefined;
|
|
@@ -2280,8 +2306,6 @@ export declare const STRINGS: {
|
|
|
2280
2306
|
export declare const TileGrid: React$1.ForwardRefExoticComponent<TileGridProps & React$1.RefAttributes<HTMLUListElement>>;
|
|
2281
2307
|
export declare const Sparkline: React$1.ForwardRefExoticComponent<SparklineProps & React$1.RefAttributes<SVGSVGElement>>;
|
|
2282
2308
|
export declare const AppShell: React$1.ForwardRefExoticComponent<AppShellProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
2283
|
-
/** ActionBar — a bar stuck to the bottom of the screen or of a card: a status line and the form's or selection's
|
|
2284
|
-
* actions. It is `position: sticky`, so it stays in the flow at the end of its parent and never covers the last field. */
|
|
2285
2309
|
export declare const ActionBar: React$1.ForwardRefExoticComponent<ActionBarProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
2286
2310
|
/** Separator — a 1px `aura-border-default` rule between groups of content (4.20). Decorative by default (hidden from
|
|
2287
2311
|
* screen readers); `decorative={false}` makes it a `role="separator"` that is announced. */
|
package/dist/index.d.ts
CHANGED
|
@@ -680,7 +680,12 @@ export interface RadioGroupProps extends FieldProps {
|
|
|
680
680
|
name?: string | undefined;
|
|
681
681
|
/** Default `vertical`. */
|
|
682
682
|
orientation?: "vertical" | "horizontal" | undefined;
|
|
683
|
+
/** Disables every option and (5.68) dims the legend, as Field does its label. */
|
|
683
684
|
disabled?: boolean | undefined;
|
|
685
|
+
/** 5.68 (Chamber-OS 184): announce the error line when it appears (`aria-live="polite"`) — for an error shown as
|
|
686
|
+
* the user changes the group ("Choose at least one…" when the last box is unticked), not on submit. The error line
|
|
687
|
+
* stays in the page, empty, while there is none, so the first message is read too. Off by default. */
|
|
688
|
+
errorLive?: boolean | undefined;
|
|
684
689
|
id?: string | undefined;
|
|
685
690
|
className?: string | undefined;
|
|
686
691
|
/** 44px rows (5.30, Chamber-OS 135), the one-line label centred: `true` below 640px or on a coarse pointer (touch
|
|
@@ -700,7 +705,12 @@ export interface CheckboxGroupProps extends FieldProps {
|
|
|
700
705
|
name?: string | undefined;
|
|
701
706
|
/** Default `vertical`. */
|
|
702
707
|
orientation?: "vertical" | "horizontal" | undefined;
|
|
708
|
+
/** Disables every option and (5.68) dims the legend, as Field does its label. */
|
|
703
709
|
disabled?: boolean | undefined;
|
|
710
|
+
/** 5.68 (Chamber-OS 184): announce the error line when it appears (`aria-live="polite"`) — for an error shown as
|
|
711
|
+
* the user changes the group ("Choose at least one…" when the last box is unticked), not on submit. The error line
|
|
712
|
+
* stays in the page, empty, while there is none, so the first message is read too. Off by default. */
|
|
713
|
+
errorLive?: boolean | undefined;
|
|
704
714
|
id?: string | undefined;
|
|
705
715
|
className?: string | undefined;
|
|
706
716
|
/** 44px rows, as RadioGroup: `true` below 640px or on a coarse pointer, `'always'` at every width. */
|
|
@@ -1504,6 +1514,16 @@ export interface ActionBarProps {
|
|
|
1504
1514
|
* parent, so they never cover the last field. Make it the last child of the form or card it belongs to: like any
|
|
1505
1515
|
* `position: sticky` element it sticks only while that parent is on screen. */
|
|
1506
1516
|
position?: "viewport" | "container" | undefined;
|
|
1517
|
+
/** 5.69 (Chamber-OS 185), `position="viewport"` only. `floating` (default): the inset card, bordered all round,
|
|
1518
|
+
* rounded, with a shadow. `edge`: PageHeader's edge strip at every width — the screen's full width, on the bottom
|
|
1519
|
+
* edge or on a BottomNav, a top border only, the home-indicator inset inside it. The strip is `position: fixed` and
|
|
1520
|
+
* stays on screen for the whole page (not only while its form is), so, as PageHeader's bar, the page gains its height
|
|
1521
|
+
* at the end (`--aura-actionbar-height` on `<html>`) and a focused field scrolls clear; on a screen 30rem tall or
|
|
1522
|
+
* less it is static, in the flow. For a strip on a phone only, use `edgeBelow`. */
|
|
1523
|
+
look?: "floating" | "edge" | undefined;
|
|
1524
|
+
/** 5.69 (Chamber-OS 185), `position="viewport"` only: the edge strip below this width (`sm` 640px, `md` 768px),
|
|
1525
|
+
* the `look` card at and above it — as PageHeader's `actionsBarBelow`. */
|
|
1526
|
+
edgeBelow?: "sm" | "md" | undefined;
|
|
1507
1527
|
/** 5.35 (DxT Monitor #14): while this bar is on the page, a BottomNav (and its spacer) is hidden and the bar takes the
|
|
1508
1528
|
* bottom edge — for a page whose own actions (Acknowledge, Visit site) replace the tab bar. Any element can do the
|
|
1509
1529
|
* same with the `data-aura-hide-bottomnav` attribute. */
|
|
@@ -1927,6 +1947,12 @@ export interface FieldComponentProps extends Omit<FieldPropsPublic, "label"> {
|
|
|
1927
1947
|
/** The control's id: the label points at it, and the hint/error ids derive from it. */
|
|
1928
1948
|
id?: string | undefined;
|
|
1929
1949
|
children?: React$1.ReactNode | undefined;
|
|
1950
|
+
/** 5.68 (Chamber-OS 184): announce the error line when it appears — for an error shown as the user types or ticks,
|
|
1951
|
+
* not on submit. The error `<p>` gets `aria-live="polite"` and stays in the page, empty, while there is no error, so
|
|
1952
|
+
* the first message is read too. Off by default: an error shown on submit, with focus moved to the field, is read
|
|
1953
|
+
* already, and a live line would read it twice. Your control should still point at `{id}-error` in its
|
|
1954
|
+
* `aria-describedby` while there is an error (TextField and the others do), so the message stays its description. */
|
|
1955
|
+
errorLive?: boolean | undefined;
|
|
1930
1956
|
/** 5.31 (Chamber-OS addendum 41): a node between the label and the control, in a `.aura-field__addon` box with the
|
|
1931
1957
|
* id `{id}-addon`. TextField and Textarea add that id to the input's `aria-describedby`; a custom control should too. */
|
|
1932
1958
|
labelAddon?: React$1.ReactNode | undefined;
|
|
@@ -2280,8 +2306,6 @@ export declare const STRINGS: {
|
|
|
2280
2306
|
export declare const TileGrid: React$1.ForwardRefExoticComponent<TileGridProps & React$1.RefAttributes<HTMLUListElement>>;
|
|
2281
2307
|
export declare const Sparkline: React$1.ForwardRefExoticComponent<SparklineProps & React$1.RefAttributes<SVGSVGElement>>;
|
|
2282
2308
|
export declare const AppShell: React$1.ForwardRefExoticComponent<AppShellProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
2283
|
-
/** ActionBar — a bar stuck to the bottom of the screen or of a card: a status line and the form's or selection's
|
|
2284
|
-
* actions. It is `position: sticky`, so it stays in the flow at the end of its parent and never covers the last field. */
|
|
2285
2309
|
export declare const ActionBar: React$1.ForwardRefExoticComponent<ActionBarProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
2286
2310
|
/** Separator — a 1px `aura-border-default` rule between groups of content (4.20). Decorative by default (hidden from
|
|
2287
2311
|
* screen readers); `decorative={false}` makes it a `role="separator"` that is announced. */
|
package/dist/styles.css
CHANGED
|
@@ -525,6 +525,9 @@ a.aura-icon-btn { text-decoration: none; }
|
|
|
525
525
|
.aura-field__hint, .aura-field__error { display: flex; align-items: flex-start; gap: var(--aura-space-1); margin: 0; font-size: max(12px, .75rem); line-height: 1.5; color: var(--aura-fg-secondary); }
|
|
526
526
|
.aura-field__error { color: var(--aura-fg-danger); }
|
|
527
527
|
.aura-field__error .aura-icon { margin-top: 2px; }
|
|
528
|
+
/* 5.68 (Chamber-OS 184): an `errorLive` error line waits in the page, empty, until there is an error. Out of the
|
|
529
|
+
* flow (an absolute child takes no gap) and clipped; the screen reader still has the live region. */
|
|
530
|
+
.aura-field__error:empty { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
528
531
|
/* 5.31 (Chamber-OS addendum 41): TextField/Textarea `labelAddon`, between the label and the box, in the field's gap. */
|
|
529
532
|
.aura-field__addon { min-width: 0; font-size: max(13px, .8125rem); line-height: 1.5; color: var(--aura-fg-primary); }
|
|
530
533
|
.aura-field.is-disabled .aura-field__label { color: var(--aura-fg-secondary); }
|
|
@@ -2267,6 +2270,32 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
2267
2270
|
.aura-actionbar__start:empty { display: none; }
|
|
2268
2271
|
@container aura-actionbar (min-width: 640px) { .aura-actionbar__start { order: -1; } }
|
|
2269
2272
|
@container aura-actionbar (max-width: 639.98px) { .aura-actionbar__inner.has-start > .aura-actionbar__status:not(:empty) { flex-basis: 100%; } }
|
|
2273
|
+
/* 5.69 (Chamber-OS 185): look="edge" / edgeBelow — PageHeader's edge strip (5.48): the screen's full width, on the
|
|
2274
|
+
* bottom edge or on a BottomNav, a top border only, the home-indicator inset inside it. Fixed, so it spans the screen
|
|
2275
|
+
* and not its parent; as PageHeader's bar, the page gains its height at the end (the shell's content, else the body)
|
|
2276
|
+
* and as scroll-padding — --aura-actionbar-height, measured on the client, 60px until then — so the page's end and a
|
|
2277
|
+
* focused field scroll clear of it. On a screen 30rem tall or less it is static, in the flow, as every bar (5.48/5.49). */
|
|
2278
|
+
.aura-actionbar--edge:not(.is-idle) { border: 0; border-top: 1px solid var(--aura-border-default); border-radius: 0; box-shadow: none; }
|
|
2279
|
+
@media (min-height: 30.00125rem) {
|
|
2280
|
+
.aura-actionbar--edge:not(.is-idle) { position: fixed; left: 0; right: 0; width: auto; bottom: var(--aura-bottomnav-offset, 0px); margin: 0; padding-bottom: max(0px, env(safe-area-inset-bottom, 0px) - var(--aura-bottomnav-offset, 0px)); }
|
|
2281
|
+
:root:has(.aura-actionbar--edge:not(.is-idle)) { --aura-actionbar-space: calc(var(--aura-actionbar-height, 60px) + var(--aura-bottomnav-offset, 0px) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-actionbar-space); }
|
|
2282
|
+
:root:has(.aura-actionbar--edge:not(.is-idle)) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-actionbar-space)); }
|
|
2283
|
+
:root:has(.aura-actionbar--edge:not(.is-idle)):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-actionbar-space); }
|
|
2284
|
+
}
|
|
2285
|
+
@media (max-width: 639.98px) { .aura-actionbar--edge-below-sm:not(.is-idle) { border: 0; border-top: 1px solid var(--aura-border-default); border-radius: 0; box-shadow: none; } }
|
|
2286
|
+
@media (max-width: 639.98px) and (min-height: 30.00125rem) {
|
|
2287
|
+
.aura-actionbar--edge-below-sm:not(.is-idle) { position: fixed; left: 0; right: 0; width: auto; bottom: var(--aura-bottomnav-offset, 0px); margin: 0; padding-bottom: max(0px, env(safe-area-inset-bottom, 0px) - var(--aura-bottomnav-offset, 0px)); }
|
|
2288
|
+
:root:has(.aura-actionbar--edge-below-sm:not(.is-idle)) { --aura-actionbar-space: calc(var(--aura-actionbar-height, 60px) + var(--aura-bottomnav-offset, 0px) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-actionbar-space); }
|
|
2289
|
+
:root:has(.aura-actionbar--edge-below-sm:not(.is-idle)) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-actionbar-space)); }
|
|
2290
|
+
:root:has(.aura-actionbar--edge-below-sm:not(.is-idle)):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-actionbar-space); }
|
|
2291
|
+
}
|
|
2292
|
+
@media (max-width: 767.98px) { .aura-actionbar--edge-below-md:not(.is-idle) { border: 0; border-top: 1px solid var(--aura-border-default); border-radius: 0; box-shadow: none; } }
|
|
2293
|
+
@media (max-width: 767.98px) and (min-height: 30.00125rem) {
|
|
2294
|
+
.aura-actionbar--edge-below-md:not(.is-idle) { position: fixed; left: 0; right: 0; width: auto; bottom: var(--aura-bottomnav-offset, 0px); margin: 0; padding-bottom: max(0px, env(safe-area-inset-bottom, 0px) - var(--aura-bottomnav-offset, 0px)); }
|
|
2295
|
+
:root:has(.aura-actionbar--edge-below-md:not(.is-idle)) { --aura-actionbar-space: calc(var(--aura-actionbar-height, 60px) + var(--aura-bottomnav-offset, 0px) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-actionbar-space); }
|
|
2296
|
+
:root:has(.aura-actionbar--edge-below-md:not(.is-idle)) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-actionbar-space)); }
|
|
2297
|
+
:root:has(.aura-actionbar--edge-below-md:not(.is-idle)):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-actionbar-space); }
|
|
2298
|
+
}
|
|
2270
2299
|
|
|
2271
2300
|
/* ---------- 4.20: Separator ---------- */
|
|
2272
2301
|
.aura-separator { flex: none; align-self: stretch; height: 1px; margin: var(--aura-separator-space, 0) 0; background: var(--aura-border-default); border: 0; }
|
package/dist/styles.layer.css
CHANGED
|
@@ -527,6 +527,9 @@ a.aura-icon-btn { text-decoration: none; }
|
|
|
527
527
|
.aura-field__hint, .aura-field__error { display: flex; align-items: flex-start; gap: var(--aura-space-1); margin: 0; font-size: max(12px, .75rem); line-height: 1.5; color: var(--aura-fg-secondary); }
|
|
528
528
|
.aura-field__error { color: var(--aura-fg-danger); }
|
|
529
529
|
.aura-field__error .aura-icon { margin-top: 2px; }
|
|
530
|
+
/* 5.68 (Chamber-OS 184): an `errorLive` error line waits in the page, empty, until there is an error. Out of the
|
|
531
|
+
* flow (an absolute child takes no gap) and clipped; the screen reader still has the live region. */
|
|
532
|
+
.aura-field__error:empty { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
530
533
|
/* 5.31 (Chamber-OS addendum 41): TextField/Textarea `labelAddon`, between the label and the box, in the field's gap. */
|
|
531
534
|
.aura-field__addon { min-width: 0; font-size: max(13px, .8125rem); line-height: 1.5; color: var(--aura-fg-primary); }
|
|
532
535
|
.aura-field.is-disabled .aura-field__label { color: var(--aura-fg-secondary); }
|
|
@@ -2269,6 +2272,32 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
2269
2272
|
.aura-actionbar__start:empty { display: none; }
|
|
2270
2273
|
@container aura-actionbar (min-width: 640px) { .aura-actionbar__start { order: -1; } }
|
|
2271
2274
|
@container aura-actionbar (max-width: 639.98px) { .aura-actionbar__inner.has-start > .aura-actionbar__status:not(:empty) { flex-basis: 100%; } }
|
|
2275
|
+
/* 5.69 (Chamber-OS 185): look="edge" / edgeBelow — PageHeader's edge strip (5.48): the screen's full width, on the
|
|
2276
|
+
* bottom edge or on a BottomNav, a top border only, the home-indicator inset inside it. Fixed, so it spans the screen
|
|
2277
|
+
* and not its parent; as PageHeader's bar, the page gains its height at the end (the shell's content, else the body)
|
|
2278
|
+
* and as scroll-padding — --aura-actionbar-height, measured on the client, 60px until then — so the page's end and a
|
|
2279
|
+
* focused field scroll clear of it. On a screen 30rem tall or less it is static, in the flow, as every bar (5.48/5.49). */
|
|
2280
|
+
.aura-actionbar--edge:not(.is-idle) { border: 0; border-top: 1px solid var(--aura-border-default); border-radius: 0; box-shadow: none; }
|
|
2281
|
+
@media (min-height: 30.00125rem) {
|
|
2282
|
+
.aura-actionbar--edge:not(.is-idle) { position: fixed; left: 0; right: 0; width: auto; bottom: var(--aura-bottomnav-offset, 0px); margin: 0; padding-bottom: max(0px, env(safe-area-inset-bottom, 0px) - var(--aura-bottomnav-offset, 0px)); }
|
|
2283
|
+
:root:has(.aura-actionbar--edge:not(.is-idle)) { --aura-actionbar-space: calc(var(--aura-actionbar-height, 60px) + var(--aura-bottomnav-offset, 0px) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-actionbar-space); }
|
|
2284
|
+
:root:has(.aura-actionbar--edge:not(.is-idle)) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-actionbar-space)); }
|
|
2285
|
+
:root:has(.aura-actionbar--edge:not(.is-idle)):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-actionbar-space); }
|
|
2286
|
+
}
|
|
2287
|
+
@media (max-width: 639.98px) { .aura-actionbar--edge-below-sm:not(.is-idle) { border: 0; border-top: 1px solid var(--aura-border-default); border-radius: 0; box-shadow: none; } }
|
|
2288
|
+
@media (max-width: 639.98px) and (min-height: 30.00125rem) {
|
|
2289
|
+
.aura-actionbar--edge-below-sm:not(.is-idle) { position: fixed; left: 0; right: 0; width: auto; bottom: var(--aura-bottomnav-offset, 0px); margin: 0; padding-bottom: max(0px, env(safe-area-inset-bottom, 0px) - var(--aura-bottomnav-offset, 0px)); }
|
|
2290
|
+
:root:has(.aura-actionbar--edge-below-sm:not(.is-idle)) { --aura-actionbar-space: calc(var(--aura-actionbar-height, 60px) + var(--aura-bottomnav-offset, 0px) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-actionbar-space); }
|
|
2291
|
+
:root:has(.aura-actionbar--edge-below-sm:not(.is-idle)) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-actionbar-space)); }
|
|
2292
|
+
:root:has(.aura-actionbar--edge-below-sm:not(.is-idle)):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-actionbar-space); }
|
|
2293
|
+
}
|
|
2294
|
+
@media (max-width: 767.98px) { .aura-actionbar--edge-below-md:not(.is-idle) { border: 0; border-top: 1px solid var(--aura-border-default); border-radius: 0; box-shadow: none; } }
|
|
2295
|
+
@media (max-width: 767.98px) and (min-height: 30.00125rem) {
|
|
2296
|
+
.aura-actionbar--edge-below-md:not(.is-idle) { position: fixed; left: 0; right: 0; width: auto; bottom: var(--aura-bottomnav-offset, 0px); margin: 0; padding-bottom: max(0px, env(safe-area-inset-bottom, 0px) - var(--aura-bottomnav-offset, 0px)); }
|
|
2297
|
+
:root:has(.aura-actionbar--edge-below-md:not(.is-idle)) { --aura-actionbar-space: calc(var(--aura-actionbar-height, 60px) + var(--aura-bottomnav-offset, 0px) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-actionbar-space); }
|
|
2298
|
+
:root:has(.aura-actionbar--edge-below-md:not(.is-idle)) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-actionbar-space)); }
|
|
2299
|
+
:root:has(.aura-actionbar--edge-below-md:not(.is-idle)):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-actionbar-space); }
|
|
2300
|
+
}
|
|
2272
2301
|
|
|
2273
2302
|
/* ---------- 4.20: Separator ---------- */
|
|
2274
2303
|
.aura-separator { flex: none; align-self: stretch; height: 1px; margin: var(--aura-separator-space, 0) 0; background: var(--aura-border-default); border: 0; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jirawatpyk/aura-react",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.69.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",
|