@jirawatpyk/aura-react 5.13.0 → 5.14.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 +13 -0
- package/dist/aura.bundle.js +138 -85
- package/dist/cjs/index.cjs +138 -85
- package/dist/esm/AppShell.js +69 -24
- package/dist/esm/Avatar.js +4 -32
- package/dist/esm/Button.js +4 -2
- package/dist/esm/Stat.js +2 -30
- package/dist/esm/Tabs.js +1 -1
- package/dist/esm/display.js +75 -2
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/server/index.cjs +78 -1
- package/dist/server/index.d.cts +48 -1
- package/dist/server/index.d.ts +48 -1
- package/dist/server/index.js +78 -1
- package/dist/styles.css +29 -5
- package/dist/styles.layer.css +29 -5
- package/package.json +1 -1
package/dist/server/index.d.ts
CHANGED
|
@@ -81,6 +81,15 @@ export interface CardProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "ti
|
|
|
81
81
|
/** id for the title element; the card is then labelled by it (aria-labelledby). */
|
|
82
82
|
titleId?: string | undefined;
|
|
83
83
|
}
|
|
84
|
+
export interface AvatarProps {
|
|
85
|
+
/** Accessible name; also gives the initials and a stable colour. */
|
|
86
|
+
name: string;
|
|
87
|
+
src?: string | undefined;
|
|
88
|
+
/** `sm` 24 · `md` 32 (default) · `lg` 40. */
|
|
89
|
+
size?: "sm" | "md" | "lg" | undefined;
|
|
90
|
+
status?: "online" | undefined;
|
|
91
|
+
className?: string | undefined;
|
|
92
|
+
}
|
|
84
93
|
/** ISO date string, `YYYY-MM-DD` (Gregorian — the era is display only). */
|
|
85
94
|
export type ISODate = string;
|
|
86
95
|
export interface DateDisplayOptions {
|
|
@@ -89,6 +98,35 @@ export interface DateDisplayOptions {
|
|
|
89
98
|
/** `buddhist` (พ.ศ.; default for th) or `gregory` (ค.ศ.; default for en and sv). */
|
|
90
99
|
calendar?: "buddhist" | "gregory" | undefined;
|
|
91
100
|
}
|
|
101
|
+
export interface StatChange {
|
|
102
|
+
/** Shown as written, e.g. "+12%" or "−3". */
|
|
103
|
+
value: React$1.ReactNode;
|
|
104
|
+
direction?: "up" | "down" | "flat" | undefined;
|
|
105
|
+
/** Default: up = positive, down = negative. Set it when a rise is bad (cancellations, wait time). */
|
|
106
|
+
tone?: "positive" | "negative" | "neutral" | undefined;
|
|
107
|
+
/** e.g. "vs last month". */
|
|
108
|
+
label?: React$1.ReactNode | undefined;
|
|
109
|
+
}
|
|
110
|
+
export interface StatProps {
|
|
111
|
+
/** Your router's link (e.g. `Link` from `next/link`) for this component; defaults to AuraProvider's `linkComponent`, then `<a>`. */
|
|
112
|
+
linkComponent?: React$1.ElementType | undefined;
|
|
113
|
+
label: React$1.ReactNode;
|
|
114
|
+
value?: React$1.ReactNode | undefined;
|
|
115
|
+
/** Small unit after the value ("งาน", "คน", "%"). */
|
|
116
|
+
unit?: React$1.ReactNode | undefined;
|
|
117
|
+
change?: StatChange | undefined;
|
|
118
|
+
caption?: React$1.ReactNode | undefined;
|
|
119
|
+
icon?: IconInput | undefined;
|
|
120
|
+
/** Skeleton in place of the value. */
|
|
121
|
+
loading?: boolean | undefined;
|
|
122
|
+
/** Makes the whole card a link or a button (drill-down). */
|
|
123
|
+
href?: string | undefined;
|
|
124
|
+
onClick?: (() => void) | undefined;
|
|
125
|
+
/** The label as a heading of this level (5.14), when the tile titles its section. Not with `onClick` (a heading
|
|
126
|
+
* can't sit in a button); a link is fine. Default: a plain label. */
|
|
127
|
+
headingLevel?: 2 | 3 | 4 | 5 | 6 | undefined;
|
|
128
|
+
className?: string | undefined;
|
|
129
|
+
}
|
|
92
130
|
export type Tone = "neutral" | "accent" | "success" | "warning" | "danger";
|
|
93
131
|
export interface BadgeProps extends React$1.HTMLAttributes<HTMLSpanElement> {
|
|
94
132
|
tone?: Tone | undefined;
|
|
@@ -107,7 +145,9 @@ export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElem
|
|
|
107
145
|
/** `danger` (5.13) for a failure — the data couldn't load: the danger tint, a danger-coloured icon, and a solid
|
|
108
146
|
* danger frame with `bordered`. It stays quiet; pass `role="alert"` if it must interrupt. Default `neutral`. */
|
|
109
147
|
tone?: "neutral" | "danger" | undefined;
|
|
110
|
-
|
|
148
|
+
/** The title's heading level (default 3); `false` (5.14) makes it a paragraph, for a card or list whose outline
|
|
149
|
+
* mustn't change. EmptyState has no live-region role unless you pass `role`. */
|
|
150
|
+
headingLevel?: 2 | 3 | 4 | 5 | 6 | false | undefined;
|
|
111
151
|
className?: string | undefined;
|
|
112
152
|
}
|
|
113
153
|
export interface ThemeOptions {
|
|
@@ -305,6 +345,11 @@ declare function ServerCard(props: CardProps): React$1.ReactElement;
|
|
|
305
345
|
declare function ServerStatusPill(props: StatusPillProps): React$1.ReactElement;
|
|
306
346
|
declare function ServerBadge(props: BadgeProps): React$1.ReactElement;
|
|
307
347
|
declare function ServerEmptyState(props: EmptyStateProps): React$1.ReactElement;
|
|
348
|
+
/** Stat for Server Components (5.14): no `onClick` (a button needs the client); `href` renders `linkComponent`, else `<a>`. */
|
|
349
|
+
declare function ServerStat(props: Omit<StatProps, "onClick">): React$1.ReactElement;
|
|
350
|
+
/** Avatar for Server Components (5.14): initials and colour. Falling back to the initials when an image fails needs the
|
|
351
|
+
* client, so give a server avatar a `src` you know loads, or none. */
|
|
352
|
+
declare function ServerAvatar(props: AvatarProps): React$1.ReactElement;
|
|
308
353
|
/** Makes icon names as strings work: `registerIcons(allIcons)` once at startup, with `allIcons` from
|
|
309
354
|
* `@jirawatpyk/aura-react/icons`, or only the icons you use (`registerIcons([IconUsers, IconPlus])`). In 5.x every
|
|
310
355
|
* name already works and this only says you are ready for 6.0 (it silences the notice); in 6.0 it is required. Call it in the module
|
|
@@ -315,9 +360,11 @@ export declare const Icon: React$1.ForwardRefExoticComponent<IconProps & React$1
|
|
|
315
360
|
|
|
316
361
|
export {
|
|
317
362
|
ServerAlert as Alert,
|
|
363
|
+
ServerAvatar as Avatar,
|
|
318
364
|
ServerBadge as Badge,
|
|
319
365
|
ServerCard as Card,
|
|
320
366
|
ServerEmptyState as EmptyState,
|
|
367
|
+
ServerStat as Stat,
|
|
321
368
|
ServerStatusPill as StatusPill,
|
|
322
369
|
scale as brandScale,
|
|
323
370
|
toneFor as statusTone,
|
package/dist/server/index.js
CHANGED
|
@@ -958,6 +958,7 @@ var Icon = React2.forwardRef(function Icon2(props, ref) {
|
|
|
958
958
|
var iconNames = Object.keys(map);
|
|
959
959
|
|
|
960
960
|
// src/icons.ts
|
|
961
|
+
var IconMinus = /* @__PURE__ */ defineIcon("minus", [["path", { d: "M5 12h14" }]]);
|
|
961
962
|
var IconCircleAlert = /* @__PURE__ */ defineIcon("circle-alert", [
|
|
962
963
|
["circle", { cx: "12", cy: "12", r: "10" }],
|
|
963
964
|
["line", { x1: "12", x2: "12", y1: "8", y2: "12" }],
|
|
@@ -1000,6 +1001,14 @@ var IconInbox = /* @__PURE__ */ defineIcon("inbox", [
|
|
|
1000
1001
|
{ d: "M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" }
|
|
1001
1002
|
]
|
|
1002
1003
|
]);
|
|
1004
|
+
var IconTrendingUp = /* @__PURE__ */ defineIcon("trending-up", [
|
|
1005
|
+
["path", { d: "M16 7h6v6" }],
|
|
1006
|
+
["path", { d: "m22 7-8.5 8.5-5-5L2 17" }]
|
|
1007
|
+
]);
|
|
1008
|
+
var IconTrendingDown = /* @__PURE__ */ defineIcon("trending-down", [
|
|
1009
|
+
["path", { d: "M16 17h6v-6" }],
|
|
1010
|
+
["path", { d: "m22 17-8.5-8.5-5 5L2 7" }]
|
|
1011
|
+
]);
|
|
1003
1012
|
|
|
1004
1013
|
// src/display.tsx
|
|
1005
1014
|
var h2 = React3.createElement;
|
|
@@ -1090,7 +1099,7 @@ function badgeElement(props, ref) {
|
|
|
1090
1099
|
);
|
|
1091
1100
|
}
|
|
1092
1101
|
function emptyStateElement(props, ref) {
|
|
1093
|
-
const HT = "h" + (props.headingLevel || 3);
|
|
1102
|
+
const HT = props.headingLevel === false ? "p" : "h" + (props.headingLevel || 3);
|
|
1094
1103
|
const rest = omit(props, [
|
|
1095
1104
|
"title",
|
|
1096
1105
|
"description",
|
|
@@ -1122,6 +1131,66 @@ function emptyStateElement(props, ref) {
|
|
|
1122
1131
|
props.action ? /* @__PURE__ */ React3.createElement("div", { className: "aura-empty__action" }, props.action) : null
|
|
1123
1132
|
);
|
|
1124
1133
|
}
|
|
1134
|
+
function statElement(props, ref, Link) {
|
|
1135
|
+
const ch = props.change;
|
|
1136
|
+
const dir = ch && (ch.direction || "flat");
|
|
1137
|
+
const tone2 = ch && (ch.tone || (dir === "up" ? "positive" : dir === "down" ? "negative" : "neutral"));
|
|
1138
|
+
const v = props.value;
|
|
1139
|
+
const numeric = typeof v === "number" || typeof v === "string" && /\d/.test(v) && /^[\s\d.,:+\-\u2212%()\u0E3F$\u20AC\u00A3\u00A5kKmMbB]+$/.test(v.replace(/\b[A-Z]{3}\b/g, ""));
|
|
1140
|
+
const Tag = props.href ? Link : props.onClick ? "button" : "div";
|
|
1141
|
+
const interactive = !!(props.href || props.onClick);
|
|
1142
|
+
if (props.headingLevel && Tag === "button")
|
|
1143
|
+
devWarnOnce(
|
|
1144
|
+
"stat-heading-button",
|
|
1145
|
+
"Stat `headingLevel` is ignored with `onClick`: a heading can\u2019t sit in a button. Use `href`, or put the heading outside."
|
|
1146
|
+
);
|
|
1147
|
+
const LabelTag = props.headingLevel && Tag !== "button" ? "h" + props.headingLevel : "span";
|
|
1148
|
+
const HeadTag = LabelTag === "span" ? "span" : "div";
|
|
1149
|
+
return /* @__PURE__ */ React3.createElement(
|
|
1150
|
+
Tag,
|
|
1151
|
+
{
|
|
1152
|
+
ref,
|
|
1153
|
+
className: cx("aura-stat", interactive && "is-interactive", props.loading && "is-loading", props.className),
|
|
1154
|
+
href: props.href,
|
|
1155
|
+
onClick: props.onClick,
|
|
1156
|
+
type: Tag === "button" ? "button" : void 0,
|
|
1157
|
+
"aria-busy": props.loading || void 0
|
|
1158
|
+
},
|
|
1159
|
+
/* @__PURE__ */ React3.createElement(HeadTag, { className: "aura-stat__head" }, /* @__PURE__ */ React3.createElement(LabelTag, { className: "aura-stat__label" }, props.label), props.icon ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__icon" }, /* @__PURE__ */ React3.createElement(Icon, { name: props.icon })) : null),
|
|
1160
|
+
props.loading ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__value" }, /* @__PURE__ */ React3.createElement("span", { className: "aura-skel aura-stat__skel" })) : /* @__PURE__ */ React3.createElement("span", { className: cx("aura-stat__value", numeric && "is-numeric") }, props.value, props.unit ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__unit" }, props.unit) : null),
|
|
1161
|
+
ch && !props.loading || props.caption ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__foot" }, ch && !props.loading ? /* @__PURE__ */ React3.createElement("span", { className: cx("aura-stat__change", "is-" + tone2) }, /* @__PURE__ */ React3.createElement(
|
|
1162
|
+
Icon,
|
|
1163
|
+
{
|
|
1164
|
+
name: dir === "up" ? /* @__PURE__ */ React3.createElement(IconTrendingUp, null) : dir === "down" ? /* @__PURE__ */ React3.createElement(IconTrendingDown, null) : /* @__PURE__ */ React3.createElement(IconMinus, null),
|
|
1165
|
+
size: 14
|
|
1166
|
+
}
|
|
1167
|
+
), /* @__PURE__ */ React3.createElement("span", null, ch.value)) : null, ch && ch.label && !props.loading ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__caption" }, ch.label) : null, props.caption ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__caption" }, props.caption) : null) : null
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
var AVATAR_TONES = ["progress", "ready", "neutral", "warning"];
|
|
1171
|
+
function initials(name) {
|
|
1172
|
+
const parts = String(name || "?").trim().split(/\s+/);
|
|
1173
|
+
return ((parts[0] || "?")[0] + (parts.length > 1 ? parts[parts.length - 1][0] : parts[0][1] || "")).toUpperCase();
|
|
1174
|
+
}
|
|
1175
|
+
function avatarElement(props, ref, broken, onError) {
|
|
1176
|
+
const size = props.size || "md";
|
|
1177
|
+
let hash = 0;
|
|
1178
|
+
String(props.name || "").split("").forEach(function(ch) {
|
|
1179
|
+
hash = hash * 31 + ch.charCodeAt(0) >>> 0;
|
|
1180
|
+
});
|
|
1181
|
+
const tone2 = AVATAR_TONES[hash % AVATAR_TONES.length];
|
|
1182
|
+
return /* @__PURE__ */ React3.createElement(
|
|
1183
|
+
"span",
|
|
1184
|
+
{
|
|
1185
|
+
ref,
|
|
1186
|
+
className: cx("aura-avatar", "aura-avatar--" + size, "aura-avatar--" + tone2, props.className),
|
|
1187
|
+
role: "img",
|
|
1188
|
+
"aria-label": props.name + (props.status ? ", " + props.status : "")
|
|
1189
|
+
},
|
|
1190
|
+
props.src && broken !== props.src ? /* @__PURE__ */ React3.createElement("img", { key: props.src, src: props.src, alt: "", onError }) : /* @__PURE__ */ React3.createElement("span", { "aria-hidden": true }, initials(props.name)),
|
|
1191
|
+
props.status === "online" ? /* @__PURE__ */ React3.createElement("span", { className: "aura-avatar__status", "aria-hidden": true }) : null
|
|
1192
|
+
);
|
|
1193
|
+
}
|
|
1125
1194
|
function buttonClass(opts = {}) {
|
|
1126
1195
|
return cx(
|
|
1127
1196
|
"aura-btn",
|
|
@@ -1147,13 +1216,21 @@ function ServerBadge(props) {
|
|
|
1147
1216
|
function ServerEmptyState(props) {
|
|
1148
1217
|
return emptyStateElement(props, void 0);
|
|
1149
1218
|
}
|
|
1219
|
+
function ServerStat(props) {
|
|
1220
|
+
return statElement(omit(props, ["onClick"]), void 0, props.linkComponent || "a");
|
|
1221
|
+
}
|
|
1222
|
+
function ServerAvatar(props) {
|
|
1223
|
+
return avatarElement(props, void 0, null, void 0);
|
|
1224
|
+
}
|
|
1150
1225
|
export {
|
|
1151
1226
|
ServerAlert as Alert,
|
|
1227
|
+
ServerAvatar as Avatar,
|
|
1152
1228
|
ServerBadge as Badge,
|
|
1153
1229
|
ServerCard as Card,
|
|
1154
1230
|
ServerEmptyState as EmptyState,
|
|
1155
1231
|
Icon,
|
|
1156
1232
|
STRINGS,
|
|
1233
|
+
ServerStat as Stat,
|
|
1157
1234
|
ServerStatusPill as StatusPill,
|
|
1158
1235
|
scale as brandScale,
|
|
1159
1236
|
breakpoints,
|
package/dist/styles.css
CHANGED
|
@@ -34,6 +34,16 @@ a.aura-btn { text-decoration: none; }
|
|
|
34
34
|
padding-block: var(--aura-space-2); line-height: 1.35; text-align: center; overflow-wrap: anywhere;
|
|
35
35
|
}
|
|
36
36
|
.aura-btn.is-loading { cursor: progress; }
|
|
37
|
+
/* 5.14: a button gated with aria-disabled looks unavailable but stays focusable (no pointer-events: none, so the
|
|
38
|
+
* not-allowed cursor and a tooltip still work). */
|
|
39
|
+
button.aura-btn[aria-disabled='true']:not(.is-loading) { opacity: var(--aura-disabled-opacity); cursor: not-allowed; }
|
|
40
|
+
button.aura-btn[aria-disabled='true']:active { transform: none; }
|
|
41
|
+
/* …and hovering it changes nothing: each variant keeps its resting look (the hover rules below are overridden). */
|
|
42
|
+
button.aura-btn--primary[aria-disabled='true']:hover { background: var(--aura-button-primary-bg); }
|
|
43
|
+
button.aura-btn--secondary[aria-disabled='true']:hover, button.aura-btn--ghost[aria-disabled='true']:hover,
|
|
44
|
+
button.aura-btn--danger-secondary[aria-disabled='true']:hover { background: transparent; }
|
|
45
|
+
button.aura-btn--danger[aria-disabled='true']:hover { background: var(--aura-button-danger-bg); }
|
|
46
|
+
button.aura-btn--creative[aria-disabled='true']:hover { box-shadow: var(--aura-shadow-creative); transform: none; }
|
|
37
47
|
.aura-btn.is-loading:active { transform: none; }
|
|
38
48
|
|
|
39
49
|
/* Focus — ADDED: the source defines none. Solid 2px ring, 2px offset, on every interactive element. */
|
|
@@ -868,7 +878,11 @@ a.aura-tab { text-decoration: none; }
|
|
|
868
878
|
.aura-drawer--nav .aura-drawer__head { position: absolute; top: var(--aura-space-2); right: var(--aura-space-2); padding: 0; z-index: 1; }
|
|
869
879
|
.aura-drawer__title { flex: 1; margin: 0; font-size: 16px; line-height: 1.5; font-weight: 600; }
|
|
870
880
|
.aura-drawer__desc { margin: 0; padding: 0 var(--aura-space-6); font-size: 14px; line-height: 1.7; color: var(--aura-fg-secondary); }
|
|
871
|
-
.aura-drawer__body {
|
|
881
|
+
.aura-drawer__body {
|
|
882
|
+
flex: 1; overflow-y: auto; padding: var(--aura-space-4) var(--aura-space-6); font-size: 14px; line-height: 1.7;
|
|
883
|
+
/* 5.14 (Chamber-OS 91): a field scrolled into view (focus, the phone keyboard) keeps clear of the head and foot. */
|
|
884
|
+
scroll-padding-block: var(--aura-space-4);
|
|
885
|
+
}
|
|
872
886
|
.aura-drawer--nav .aura-drawer__body { padding: 0; }
|
|
873
887
|
.aura-drawer--nav .aura-nav { width: 100%; border-right: 0; }
|
|
874
888
|
.aura-drawer__foot { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--aura-space-3); padding: var(--aura-space-4) var(--aura-space-6); border-top: 1px solid var(--aura-border-default); }
|
|
@@ -913,12 +927,18 @@ a.aura-tab { text-decoration: none; }
|
|
|
913
927
|
.aura-grid-layout.is-auto { grid-template-columns: unset; }
|
|
914
928
|
|
|
915
929
|
/* ---------- AppShell ---------- */
|
|
916
|
-
.aura-shell {
|
|
930
|
+
.aura-shell {
|
|
931
|
+
display: flex; min-height: 100vh; min-height: 100dvh; background: var(--aura-bg-canvas); color: var(--aura-fg-primary); font-family: var(--font-sans);
|
|
932
|
+
--aura-shell-bar-height: 56px; /* 5.14 (Chamber-OS 104): the top bar's height, for sticky offsets under it */
|
|
933
|
+
}
|
|
934
|
+
.aura-shell--no-bar { --aura-shell-bar-height: 0px; }
|
|
935
|
+
@media (min-width: 1024px) { .aura-shell--menu-bar { --aura-shell-bar-height: 0px; } }
|
|
917
936
|
.aura-shell__nav { position: sticky; top: 0; height: 100vh; height: 100dvh; flex: none; }
|
|
918
937
|
.aura-shell__main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
|
919
938
|
.aura-shell__bar {
|
|
920
939
|
position: sticky; top: 0; z-index: 10; display: flex; align-items: center; gap: var(--aura-space-2);
|
|
921
|
-
|
|
940
|
+
box-sizing: border-box; min-height: 56px;
|
|
941
|
+
padding: 0 var(--aura-space-6); background: var(--aura-bg-surface); border-bottom: 1px solid var(--aura-border-default);
|
|
922
942
|
}
|
|
923
943
|
/* Responsive in CSS (4.16), so the server's HTML is already right on a phone: below lg the sidebar is hidden and the
|
|
924
944
|
* menu button shows; from lg up the reverse. JavaScript only opens and closes the drawer. */
|
|
@@ -935,10 +955,11 @@ a.aura-tab { text-decoration: none; }
|
|
|
935
955
|
.aura-shell__content { flex: 1; min-width: 0; padding: var(--aura-space-6) var(--aura-space-4); }
|
|
936
956
|
/* 5.7: <main> takes focus (tabIndex -1) for skip links and "the row you acted on is gone"; a landmark gets no ring. */
|
|
937
957
|
.aura-shell__content:focus { outline: none; }
|
|
958
|
+
.aura-shell__content.is-flush { padding: 0; } /* 5.14 (Chamber-OS 97): contentPadding={false} */
|
|
938
959
|
@media (min-width: 640px) { .aura-shell__content { padding: var(--aura-space-6); } }
|
|
939
960
|
@media (min-width: 1024px) { .aura-shell__content { padding: var(--aura-space-8); } }
|
|
940
961
|
/* The shell already pads its content: a Container directly inside only caps the width. */
|
|
941
|
-
.aura-shell__content > .aura-container { padding-left: 0; padding-right: 0; }
|
|
962
|
+
.aura-shell__content:not(.is-flush) > .aura-container { padding-left: 0; padding-right: 0; }
|
|
942
963
|
|
|
943
964
|
/* Totals row (4.19): under the body, a strong top edge; sticky at the bottom of a `height` table with stickyFooter. */
|
|
944
965
|
.aura-table__total { background: var(--aura-bg-canvas); border-top: 1px solid var(--aura-border-strong); font-weight: 600; }
|
|
@@ -958,7 +979,7 @@ button.aura-stat { font: inherit; width: 100%; cursor: pointer; }
|
|
|
958
979
|
.aura-stat.is-interactive:hover { border-color: var(--aura-border-strong); }
|
|
959
980
|
.aura-stat.is-interactive:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
|
|
960
981
|
.aura-stat__head { display: flex; align-items: center; justify-content: space-between; gap: var(--aura-space-2); }
|
|
961
|
-
.aura-stat__label { font-size: 13px; font-weight: 500; color: var(--aura-fg-secondary); }
|
|
982
|
+
.aura-stat__label { margin: 0; font-size: 13px; font-weight: 500; color: var(--aura-fg-secondary); } /* 5.14: may be a heading */
|
|
962
983
|
.aura-stat__icon { display: inline-flex; color: var(--aura-fg-secondary); }
|
|
963
984
|
.aura-stat__value { display: flex; align-items: baseline; gap: var(--aura-space-1); font-size: 28px; line-height: 1.2; font-weight: 600; letter-spacing: -0.01em; min-height: 34px; }
|
|
964
985
|
.aura-stat__value.is-numeric { font-variant-numeric: tabular-nums; }
|
|
@@ -1660,6 +1681,9 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
1660
1681
|
.aura-table__td[data-card='hide'], .aura-table__head > .aura-table__th[data-card='hide'],
|
|
1661
1682
|
.aura-table__row--skeleton .aura-table__td[data-card='hide'] { display: none; }
|
|
1662
1683
|
.aura-table__td[data-card='field'] { order: var(--aura-card-order, 5); }
|
|
1684
|
+
/* 5.14 (Chamber-OS 108): in a card every field starts under its label; align: 'end' is for the grid (figures stay tabular). */
|
|
1685
|
+
.aura-table__td.is-end { text-align: start; }
|
|
1686
|
+
.aura-table__row--skeleton .aura-table__td.is-end { justify-content: flex-start; }
|
|
1663
1687
|
/* hideSelectionInCards: no row boxes, no select-all line. */
|
|
1664
1688
|
.aura-table--cards-nosel .aura-table__row > .aura-table__sel { display: none; }
|
|
1665
1689
|
.aura-table--cards-nosel .aura-table__head { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); }
|
package/dist/styles.layer.css
CHANGED
|
@@ -36,6 +36,16 @@ a.aura-btn { text-decoration: none; }
|
|
|
36
36
|
padding-block: var(--aura-space-2); line-height: 1.35; text-align: center; overflow-wrap: anywhere;
|
|
37
37
|
}
|
|
38
38
|
.aura-btn.is-loading { cursor: progress; }
|
|
39
|
+
/* 5.14: a button gated with aria-disabled looks unavailable but stays focusable (no pointer-events: none, so the
|
|
40
|
+
* not-allowed cursor and a tooltip still work). */
|
|
41
|
+
button.aura-btn[aria-disabled='true']:not(.is-loading) { opacity: var(--aura-disabled-opacity); cursor: not-allowed; }
|
|
42
|
+
button.aura-btn[aria-disabled='true']:active { transform: none; }
|
|
43
|
+
/* …and hovering it changes nothing: each variant keeps its resting look (the hover rules below are overridden). */
|
|
44
|
+
button.aura-btn--primary[aria-disabled='true']:hover { background: var(--aura-button-primary-bg); }
|
|
45
|
+
button.aura-btn--secondary[aria-disabled='true']:hover, button.aura-btn--ghost[aria-disabled='true']:hover,
|
|
46
|
+
button.aura-btn--danger-secondary[aria-disabled='true']:hover { background: transparent; }
|
|
47
|
+
button.aura-btn--danger[aria-disabled='true']:hover { background: var(--aura-button-danger-bg); }
|
|
48
|
+
button.aura-btn--creative[aria-disabled='true']:hover { box-shadow: var(--aura-shadow-creative); transform: none; }
|
|
39
49
|
.aura-btn.is-loading:active { transform: none; }
|
|
40
50
|
|
|
41
51
|
/* Focus — ADDED: the source defines none. Solid 2px ring, 2px offset, on every interactive element. */
|
|
@@ -870,7 +880,11 @@ a.aura-tab { text-decoration: none; }
|
|
|
870
880
|
.aura-drawer--nav .aura-drawer__head { position: absolute; top: var(--aura-space-2); right: var(--aura-space-2); padding: 0; z-index: 1; }
|
|
871
881
|
.aura-drawer__title { flex: 1; margin: 0; font-size: 16px; line-height: 1.5; font-weight: 600; }
|
|
872
882
|
.aura-drawer__desc { margin: 0; padding: 0 var(--aura-space-6); font-size: 14px; line-height: 1.7; color: var(--aura-fg-secondary); }
|
|
873
|
-
.aura-drawer__body {
|
|
883
|
+
.aura-drawer__body {
|
|
884
|
+
flex: 1; overflow-y: auto; padding: var(--aura-space-4) var(--aura-space-6); font-size: 14px; line-height: 1.7;
|
|
885
|
+
/* 5.14 (Chamber-OS 91): a field scrolled into view (focus, the phone keyboard) keeps clear of the head and foot. */
|
|
886
|
+
scroll-padding-block: var(--aura-space-4);
|
|
887
|
+
}
|
|
874
888
|
.aura-drawer--nav .aura-drawer__body { padding: 0; }
|
|
875
889
|
.aura-drawer--nav .aura-nav { width: 100%; border-right: 0; }
|
|
876
890
|
.aura-drawer__foot { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--aura-space-3); padding: var(--aura-space-4) var(--aura-space-6); border-top: 1px solid var(--aura-border-default); }
|
|
@@ -915,12 +929,18 @@ a.aura-tab { text-decoration: none; }
|
|
|
915
929
|
.aura-grid-layout.is-auto { grid-template-columns: unset; }
|
|
916
930
|
|
|
917
931
|
/* ---------- AppShell ---------- */
|
|
918
|
-
.aura-shell {
|
|
932
|
+
.aura-shell {
|
|
933
|
+
display: flex; min-height: 100vh; min-height: 100dvh; background: var(--aura-bg-canvas); color: var(--aura-fg-primary); font-family: var(--font-sans);
|
|
934
|
+
--aura-shell-bar-height: 56px; /* 5.14 (Chamber-OS 104): the top bar's height, for sticky offsets under it */
|
|
935
|
+
}
|
|
936
|
+
.aura-shell--no-bar { --aura-shell-bar-height: 0px; }
|
|
937
|
+
@media (min-width: 1024px) { .aura-shell--menu-bar { --aura-shell-bar-height: 0px; } }
|
|
919
938
|
.aura-shell__nav { position: sticky; top: 0; height: 100vh; height: 100dvh; flex: none; }
|
|
920
939
|
.aura-shell__main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
|
921
940
|
.aura-shell__bar {
|
|
922
941
|
position: sticky; top: 0; z-index: 10; display: flex; align-items: center; gap: var(--aura-space-2);
|
|
923
|
-
|
|
942
|
+
box-sizing: border-box; min-height: 56px;
|
|
943
|
+
padding: 0 var(--aura-space-6); background: var(--aura-bg-surface); border-bottom: 1px solid var(--aura-border-default);
|
|
924
944
|
}
|
|
925
945
|
/* Responsive in CSS (4.16), so the server's HTML is already right on a phone: below lg the sidebar is hidden and the
|
|
926
946
|
* menu button shows; from lg up the reverse. JavaScript only opens and closes the drawer. */
|
|
@@ -937,10 +957,11 @@ a.aura-tab { text-decoration: none; }
|
|
|
937
957
|
.aura-shell__content { flex: 1; min-width: 0; padding: var(--aura-space-6) var(--aura-space-4); }
|
|
938
958
|
/* 5.7: <main> takes focus (tabIndex -1) for skip links and "the row you acted on is gone"; a landmark gets no ring. */
|
|
939
959
|
.aura-shell__content:focus { outline: none; }
|
|
960
|
+
.aura-shell__content.is-flush { padding: 0; } /* 5.14 (Chamber-OS 97): contentPadding={false} */
|
|
940
961
|
@media (min-width: 640px) { .aura-shell__content { padding: var(--aura-space-6); } }
|
|
941
962
|
@media (min-width: 1024px) { .aura-shell__content { padding: var(--aura-space-8); } }
|
|
942
963
|
/* The shell already pads its content: a Container directly inside only caps the width. */
|
|
943
|
-
.aura-shell__content > .aura-container { padding-left: 0; padding-right: 0; }
|
|
964
|
+
.aura-shell__content:not(.is-flush) > .aura-container { padding-left: 0; padding-right: 0; }
|
|
944
965
|
|
|
945
966
|
/* Totals row (4.19): under the body, a strong top edge; sticky at the bottom of a `height` table with stickyFooter. */
|
|
946
967
|
.aura-table__total { background: var(--aura-bg-canvas); border-top: 1px solid var(--aura-border-strong); font-weight: 600; }
|
|
@@ -960,7 +981,7 @@ button.aura-stat { font: inherit; width: 100%; cursor: pointer; }
|
|
|
960
981
|
.aura-stat.is-interactive:hover { border-color: var(--aura-border-strong); }
|
|
961
982
|
.aura-stat.is-interactive:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
|
|
962
983
|
.aura-stat__head { display: flex; align-items: center; justify-content: space-between; gap: var(--aura-space-2); }
|
|
963
|
-
.aura-stat__label { font-size: 13px; font-weight: 500; color: var(--aura-fg-secondary); }
|
|
984
|
+
.aura-stat__label { margin: 0; font-size: 13px; font-weight: 500; color: var(--aura-fg-secondary); } /* 5.14: may be a heading */
|
|
964
985
|
.aura-stat__icon { display: inline-flex; color: var(--aura-fg-secondary); }
|
|
965
986
|
.aura-stat__value { display: flex; align-items: baseline; gap: var(--aura-space-1); font-size: 28px; line-height: 1.2; font-weight: 600; letter-spacing: -0.01em; min-height: 34px; }
|
|
966
987
|
.aura-stat__value.is-numeric { font-variant-numeric: tabular-nums; }
|
|
@@ -1662,6 +1683,9 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
1662
1683
|
.aura-table__td[data-card='hide'], .aura-table__head > .aura-table__th[data-card='hide'],
|
|
1663
1684
|
.aura-table__row--skeleton .aura-table__td[data-card='hide'] { display: none; }
|
|
1664
1685
|
.aura-table__td[data-card='field'] { order: var(--aura-card-order, 5); }
|
|
1686
|
+
/* 5.14 (Chamber-OS 108): in a card every field starts under its label; align: 'end' is for the grid (figures stay tabular). */
|
|
1687
|
+
.aura-table__td.is-end { text-align: start; }
|
|
1688
|
+
.aura-table__row--skeleton .aura-table__td.is-end { justify-content: flex-start; }
|
|
1665
1689
|
/* hideSelectionInCards: no row boxes, no select-all line. */
|
|
1666
1690
|
.aura-table--cards-nosel .aura-table__row > .aura-table__sel { display: none; }
|
|
1667
1691
|
.aura-table--cards-nosel .aura-table__head { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jirawatpyk/aura-react",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.14.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",
|