@jirawatpyk/aura-tokens 5.9.0 → 5.10.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/aura-tailwind.css +1 -1
- package/aura-tailwind.prefixed.css +1 -1
- package/aura.css +1 -1
- package/components/aura.bundle.js +49 -19
- package/components/aura.components.css +21 -1
- package/components/index.d.ts +8 -0
- package/package.json +1 -1
- package/tokens.json +1 -1
package/aura-tailwind.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* AURA v5.
|
|
1
|
+
/* AURA v5.10.0 — Tailwind v4 theme. GENERATED by scripts/build-tokens.mts from tokens.json. Do not edit by hand.
|
|
2
2
|
* @import "tailwindcss";
|
|
3
3
|
* @import "@jirawatpyk/aura-tokens/tailwind.css";
|
|
4
4
|
* Gives bg-bg-surface, text-fg-primary, border-border-strong, p-aura-6, rounded-aura-xl, shadow-aura-overlay,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* AURA v5.
|
|
1
|
+
/* AURA v5.10.0 — Tailwind v4 theme with aura- prefixed names. GENERATED by scripts/build-tokens.mts. Do not edit by hand.
|
|
2
2
|
* For apps that already have a Tailwind theme (shadcn): nothing here redefines an existing name.
|
|
3
3
|
* @layer aura-tokens, theme, base, aura, components, utilities;
|
|
4
4
|
* @import "tailwindcss";
|
package/aura.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* AURA v5.
|
|
1
|
+
/* AURA v5.10.0 — GENERATED by scripts/build-tokens.mts from tokens.json. Do not edit by hand. */
|
|
2
2
|
/* Fonts: load aura-fonts.css (or the <link> tags in README) separately, so a blocked Google Fonts never breaks this file. */
|
|
3
3
|
|
|
4
4
|
:root, [data-theme="light"] {
|
|
@@ -1233,13 +1233,14 @@ window.Aura = (() => {
|
|
|
1233
1233
|
// src/Menu.tsx
|
|
1234
1234
|
var React8 = __toESM(require_react(), 1);
|
|
1235
1235
|
var import_react_dom = __toESM(require_react_dom(), 1);
|
|
1236
|
+
var ITEMS = '[role^="menuitem"]';
|
|
1236
1237
|
var Menu = React8.forwardRef(function Menu2(props, ref) {
|
|
1237
1238
|
const own = React8.useRef(null), merged = useMergedRef(ref, own);
|
|
1238
1239
|
const posState = React8.useState(null);
|
|
1239
1240
|
const pos = posState[0], setPos = posState[1];
|
|
1240
1241
|
const items2 = props.items || [];
|
|
1241
1242
|
const mounted = useMounted();
|
|
1242
|
-
const headerId = uid();
|
|
1243
|
+
const headerId = uid(), itemId = uid();
|
|
1243
1244
|
const hasHeader = props.header != null && props.header !== false && props.header !== "";
|
|
1244
1245
|
const Link = useLinkComponent(props.linkComponent);
|
|
1245
1246
|
useIsoLayoutEffect(
|
|
@@ -1267,8 +1268,8 @@ window.Aura = (() => {
|
|
|
1267
1268
|
hadHeader.current = hasHeader;
|
|
1268
1269
|
const a = document.activeElement;
|
|
1269
1270
|
if (own.current && (!a || a === document.body)) {
|
|
1270
|
-
const first = own.current.querySelector(
|
|
1271
|
-
|
|
1271
|
+
const first = own.current.querySelector(ITEMS);
|
|
1272
|
+
(first || own.current.querySelector('[role="menu"]') || own.current).focus();
|
|
1272
1273
|
}
|
|
1273
1274
|
},
|
|
1274
1275
|
[hasHeader]
|
|
@@ -1276,8 +1277,11 @@ window.Aura = (() => {
|
|
|
1276
1277
|
React8.useEffect(
|
|
1277
1278
|
function() {
|
|
1278
1279
|
if (!mounted) return;
|
|
1279
|
-
const first = own.current && own.current.querySelector(
|
|
1280
|
-
if (
|
|
1280
|
+
const first = own.current && own.current.querySelector(ITEMS);
|
|
1281
|
+
if (props.autoFocus !== false) {
|
|
1282
|
+
if (first) first.focus();
|
|
1283
|
+
else if (own.current) (own.current.querySelector('[role="menu"]') || own.current).focus();
|
|
1284
|
+
}
|
|
1281
1285
|
function outside(e) {
|
|
1282
1286
|
if (own.current && !own.current.contains(e.target) && !(props.anchor && props.anchor.contains(e.target)))
|
|
1283
1287
|
props.onClose(false);
|
|
@@ -1297,16 +1301,18 @@ window.Aura = (() => {
|
|
|
1297
1301
|
[mounted]
|
|
1298
1302
|
);
|
|
1299
1303
|
function onKeyDown(e) {
|
|
1300
|
-
const list2 = Array.prototype.slice.call(
|
|
1301
|
-
own.current.querySelectorAll('[role^="menuitem"]:not([disabled])')
|
|
1302
|
-
);
|
|
1304
|
+
const list2 = Array.prototype.slice.call(own.current.querySelectorAll(ITEMS));
|
|
1303
1305
|
const i = list2.indexOf(document.activeElement);
|
|
1306
|
+
if (!list2.length && e.key !== "Escape" && e.key !== "Tab") {
|
|
1307
|
+
e.stopPropagation();
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1304
1310
|
if (e.key === "ArrowDown") {
|
|
1305
1311
|
e.preventDefault();
|
|
1306
1312
|
list2[(i + 1) % list2.length].focus();
|
|
1307
1313
|
} else if (e.key === "ArrowUp") {
|
|
1308
1314
|
e.preventDefault();
|
|
1309
|
-
list2[(i - 1 + list2.length) % list2.length].focus();
|
|
1315
|
+
list2[i < 0 ? list2.length - 1 : (i - 1 + list2.length) % list2.length].focus();
|
|
1310
1316
|
} else if (e.key === "Home") {
|
|
1311
1317
|
e.preventDefault();
|
|
1312
1318
|
list2[0].focus();
|
|
@@ -1345,6 +1351,10 @@ window.Aura = (() => {
|
|
|
1345
1351
|
it.hint ? /* @__PURE__ */ React8.createElement("span", { key: "h", className: "aura-menu__hint" }, it.hint) : null
|
|
1346
1352
|
];
|
|
1347
1353
|
const cls = cx("aura-menu__item", it.tone === "danger" && "aura-menu__item--danger");
|
|
1354
|
+
const reasonId = it.disabled && it.disabledReason ? itemId + "-r" + i : void 0;
|
|
1355
|
+
if (reasonId)
|
|
1356
|
+
body[2] = /* Hidden from the name (it would be read twice); aria-describedby still reads it. */
|
|
1357
|
+
/* @__PURE__ */ React8.createElement("span", { key: "h", id: reasonId, className: "aura-menu__hint aura-menu__reason", "aria-hidden": true }, it.disabledReason);
|
|
1348
1358
|
if (it.href && !it.disabled)
|
|
1349
1359
|
return /* @__PURE__ */ React8.createElement(
|
|
1350
1360
|
Link,
|
|
@@ -1369,11 +1379,13 @@ window.Aura = (() => {
|
|
|
1369
1379
|
key: i,
|
|
1370
1380
|
type: "button",
|
|
1371
1381
|
tabIndex: -1,
|
|
1372
|
-
disabled: it.disabled,
|
|
1382
|
+
"aria-disabled": it.disabled ? true : void 0,
|
|
1383
|
+
"aria-describedby": reasonId,
|
|
1373
1384
|
role: isRadio ? "menuitemradio" : isCheck ? "menuitemcheckbox" : "menuitem",
|
|
1374
1385
|
"aria-checked": isRadio || isCheck ? !!it.checked : void 0,
|
|
1375
1386
|
className: cls,
|
|
1376
1387
|
onClick: function() {
|
|
1388
|
+
if (it.disabled) return;
|
|
1377
1389
|
if (it.onSelect) it.onSelect();
|
|
1378
1390
|
if (!it.keepOpen) props.onClose(true);
|
|
1379
1391
|
}
|
|
@@ -1402,7 +1414,19 @@ window.Aura = (() => {
|
|
|
1402
1414
|
}
|
|
1403
1415
|
},
|
|
1404
1416
|
props.header
|
|
1405
|
-
), /* @__PURE__ */ React8.createElement("div", { role: "menu", "aria-label": props.label, "aria-describedby": headerId, className: "aura-menu__list" }, list)) : /* @__PURE__ */ React8.createElement(
|
|
1417
|
+
), /* @__PURE__ */ React8.createElement("div", { role: "menu", tabIndex: -1, "aria-label": props.label, "aria-describedby": headerId, className: "aura-menu__list" }, list)) : /* @__PURE__ */ React8.createElement(
|
|
1418
|
+
"div",
|
|
1419
|
+
{
|
|
1420
|
+
ref: merged,
|
|
1421
|
+
role: "menu",
|
|
1422
|
+
tabIndex: -1,
|
|
1423
|
+
"aria-label": props.label,
|
|
1424
|
+
className: "aura-menu",
|
|
1425
|
+
onKeyDown,
|
|
1426
|
+
style
|
|
1427
|
+
},
|
|
1428
|
+
list
|
|
1429
|
+
);
|
|
1406
1430
|
return mounted ? (0, import_react_dom.createPortal)(el, document.body) : null;
|
|
1407
1431
|
});
|
|
1408
1432
|
|
|
@@ -1417,7 +1441,7 @@ window.Aura = (() => {
|
|
|
1417
1441
|
function() {
|
|
1418
1442
|
if (!anchor || !toLast.current || !menuRef.current) return;
|
|
1419
1443
|
toLast.current = false;
|
|
1420
|
-
const list = menuRef.current.querySelectorAll('[role^="menuitem"]
|
|
1444
|
+
const list = menuRef.current.querySelectorAll('[role^="menuitem"]');
|
|
1421
1445
|
if (list.length) list[list.length - 1].focus();
|
|
1422
1446
|
},
|
|
1423
1447
|
[anchor]
|
|
@@ -5876,6 +5900,12 @@ window.Aura = (() => {
|
|
|
5876
5900
|
})[0] || firstOn || items2[0];
|
|
5877
5901
|
const Link = useLinkComponent(props.linkComponent);
|
|
5878
5902
|
const manual = props.activation === "manual";
|
|
5903
|
+
const seg = props.variant === "segmented";
|
|
5904
|
+
const listCls = cx("aura-tabs__list", seg && "aura-segmented", seg && props.fullWidth && "is-full");
|
|
5905
|
+
const tabCls = function(on, extra) {
|
|
5906
|
+
return cx("aura-tab", on && "is-active", seg && "aura-segmented__option", seg && on && "is-selected", extra);
|
|
5907
|
+
};
|
|
5908
|
+
const rootCls = cx("aura-tabs", seg && "aura-tabs--segmented");
|
|
5879
5909
|
const [focusId, setFocusId] = React32.useState(null);
|
|
5880
5910
|
items2.forEach(function(t) {
|
|
5881
5911
|
const al = t.tabProps && t.tabProps["aria-label"];
|
|
@@ -5891,9 +5921,9 @@ window.Aura = (() => {
|
|
|
5891
5921
|
{
|
|
5892
5922
|
ref,
|
|
5893
5923
|
"aria-label": props.label,
|
|
5894
|
-
className: cx("aura-tabs
|
|
5924
|
+
className: cx(rootCls, "aura-tabs--links", props.className)
|
|
5895
5925
|
},
|
|
5896
|
-
/* @__PURE__ */ React32.createElement("div", { className:
|
|
5926
|
+
/* @__PURE__ */ React32.createElement("div", { className: listCls }, items2.map(function(t) {
|
|
5897
5927
|
const on = t.id === cur;
|
|
5898
5928
|
const inner = [
|
|
5899
5929
|
t.icon ? /* @__PURE__ */ React32.createElement(Icon, { key: "i", name: t.icon }) : null,
|
|
@@ -5917,7 +5947,7 @@ window.Aura = (() => {
|
|
|
5917
5947
|
{
|
|
5918
5948
|
...omit(own, ["onClick"]),
|
|
5919
5949
|
key: t.id,
|
|
5920
|
-
className: cx("
|
|
5950
|
+
className: cx(tabCls(false), "is-disabled", own.className),
|
|
5921
5951
|
"aria-disabled": true
|
|
5922
5952
|
},
|
|
5923
5953
|
inner
|
|
@@ -5927,7 +5957,7 @@ window.Aura = (() => {
|
|
|
5927
5957
|
...own,
|
|
5928
5958
|
key: t.id,
|
|
5929
5959
|
href: t.href,
|
|
5930
|
-
className:
|
|
5960
|
+
className: tabCls(on, own.className),
|
|
5931
5961
|
"aria-current": on ? "page" : void 0,
|
|
5932
5962
|
onClick: function(e) {
|
|
5933
5963
|
if (own.onClick) own.onClick(e);
|
|
@@ -5951,12 +5981,12 @@ window.Aura = (() => {
|
|
|
5951
5981
|
const stop = manual && focusId && items2.filter(function(t) {
|
|
5952
5982
|
return t.id === focusId && !t.disabled;
|
|
5953
5983
|
})[0] || current2;
|
|
5954
|
-
return /* @__PURE__ */ React32.createElement("div", { ref, className: cx(
|
|
5984
|
+
return /* @__PURE__ */ React32.createElement("div", { ref, className: cx(rootCls, props.className) }, /* @__PURE__ */ React32.createElement(
|
|
5955
5985
|
"div",
|
|
5956
5986
|
{
|
|
5957
5987
|
role: "tablist",
|
|
5958
5988
|
"aria-label": props.label,
|
|
5959
|
-
className:
|
|
5989
|
+
className: listCls,
|
|
5960
5990
|
onBlur: manual ? function(e) {
|
|
5961
5991
|
if (!e.currentTarget.contains(e.relatedTarget)) setFocusId(null);
|
|
5962
5992
|
} : void 0,
|
|
@@ -5999,7 +6029,7 @@ window.Aura = (() => {
|
|
|
5999
6029
|
ref: function(el) {
|
|
6000
6030
|
refs.current[t.id] = el;
|
|
6001
6031
|
},
|
|
6002
|
-
className:
|
|
6032
|
+
className: tabCls(on, own.className),
|
|
6003
6033
|
onFocus: manual ? function(e) {
|
|
6004
6034
|
if (own.onFocus) own.onFocus(e);
|
|
6005
6035
|
setFocusId(t.id);
|
|
@@ -226,7 +226,13 @@ a.aura-btn { text-decoration: none; }
|
|
|
226
226
|
}
|
|
227
227
|
.aura-menu__item:hover, .aura-menu__item:focus { background: var(--aura-bg-surface-hover); outline: none; }
|
|
228
228
|
.aura-menu__item:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: calc(-1 * var(--aura-focus-ring-width)); }
|
|
229
|
-
.aura-menu__item:disabled { opacity: var(--aura-disabled-opacity); cursor: default;
|
|
229
|
+
.aura-menu__item:disabled { opacity: var(--aura-disabled-opacity); cursor: default; }
|
|
230
|
+
/* 5.10: a disabled item is dimmed but focusable; its reason stays at full strength (it is the information). */
|
|
231
|
+
.aura-menu__item[aria-disabled="true"] { cursor: default; }
|
|
232
|
+
.aura-menu__item[aria-disabled="true"] > :not(.aura-menu__reason) { opacity: var(--aura-disabled-opacity); }
|
|
233
|
+
.aura-menu__reason { padding-left: var(--aura-space-4); }
|
|
234
|
+
.aura-menu__item:disabled, .aura-menu__item[aria-disabled="true"]:hover:not(:focus) { background: transparent; }
|
|
235
|
+
.aura-menu:focus, .aura-menu__list:focus { outline: none; }
|
|
230
236
|
.aura-menu__item .aura-icon { color: var(--aura-fg-secondary); }
|
|
231
237
|
.aura-menu__label { flex: 1; }
|
|
232
238
|
.aura-menu__blank { width: var(--aura-icon-sm); flex: none; }
|
|
@@ -1203,6 +1209,16 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
1203
1209
|
.aura-segmented--sm .aura-segmented__option { height: 24px; padding: 0 var(--aura-space-3); font-size: 12px; }
|
|
1204
1210
|
.aura-segmented--sm .aura-segmented__option.is-icon { width: 28px; padding: 0; }
|
|
1205
1211
|
.aura-segmented.is-disabled { opacity: var(--aura-disabled-opacity); }
|
|
1212
|
+
/* 5.10 (Chamber-OS 72): Tabs variant="segmented" — the tablist wears SegmentedControl's track and pills. The focus
|
|
1213
|
+
* ring is drawn inside the pill, so neither the scrolling list (many tabs on a phone) nor the next pill can cover it;
|
|
1214
|
+
* full-width tabs share the track but never shrink below their label (the track scrolls instead). The phone rule's
|
|
1215
|
+
* wider tab gap doesn't apply. */
|
|
1216
|
+
.aura-tabs--segmented .aura-tabs__list.aura-segmented { gap: 2px; }
|
|
1217
|
+
.aura-tabs--segmented .aura-tabs__list.aura-segmented.is-full .aura-tab { min-width: max-content; }
|
|
1218
|
+
.aura-tabs--segmented .aura-tab.aura-segmented__option { margin-bottom: 0; }
|
|
1219
|
+
.aura-tabs--segmented .aura-tab.aura-segmented__option:focus-visible { border-radius: var(--aura-radius-full); outline-offset: calc(-1 * var(--aura-focus-ring-width)); }
|
|
1220
|
+
.aura-tabs--segmented .aura-tab.aura-segmented__option:disabled,
|
|
1221
|
+
.aura-tabs--segmented .aura-tab.aura-segmented__option.is-disabled { opacity: var(--aura-disabled-opacity); cursor: not-allowed; }
|
|
1206
1222
|
|
|
1207
1223
|
/* A field inside a row Stack takes the remaining width (a search box beside its button). */
|
|
1208
1224
|
.aura-stack > .aura-field { flex: 1 1 auto; min-width: 0; }
|
|
@@ -1590,4 +1606,8 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
1590
1606
|
.aura-segmented__option.is-selected { outline: 2px solid Highlight; outline-offset: -2px; }
|
|
1591
1607
|
.aura-tab { border-bottom-color: Canvas; }
|
|
1592
1608
|
.aura-tab.is-active { border-bottom-color: Highlight; }
|
|
1609
|
+
/* 5.10: segmented tabs mark the selection with a border and focus with a dashed ring inside it, so a focused tab
|
|
1610
|
+
* and the selected one never look alike (manual activation moves focus without selecting). */
|
|
1611
|
+
.aura-tabs--segmented .aura-tab.aura-segmented__option.is-selected { outline: none; border: 2px solid Highlight; }
|
|
1612
|
+
.aura-tabs--segmented .aura-tab.aura-segmented__option:focus-visible { outline: 2px dashed CanvasText; outline-offset: -5px; }
|
|
1593
1613
|
}
|
package/components/index.d.ts
CHANGED
|
@@ -278,7 +278,10 @@ export interface MenuItem {
|
|
|
278
278
|
icon?: IconInput | undefined;
|
|
279
279
|
/** Present = a checkable item (menuitemcheckbox). */
|
|
280
280
|
checked?: boolean | undefined;
|
|
281
|
+
/** Dimmed and does nothing when chosen, but still reachable with the arrow keys and announced (5.10). */
|
|
281
282
|
disabled?: boolean | undefined;
|
|
283
|
+
/** Why it's disabled ("You can resend in 5 minutes"): shown in place of the hint and read with the item. (5.10) */
|
|
284
|
+
disabledReason?: string | undefined;
|
|
282
285
|
/** Keep the menu open after choosing (checkbox lists). */
|
|
283
286
|
keepOpen?: boolean | undefined;
|
|
284
287
|
/** Short right-aligned hint, e.g. a shortcut. */
|
|
@@ -617,6 +620,11 @@ export interface TabsProps {
|
|
|
617
620
|
/** `auto` (default): arrow keys select as they move. `manual`: arrows, Home and End only move focus; Enter, Space
|
|
618
621
|
* or a click selects — for tabs whose selection does work (loads data, starts a payment). (5.9) */
|
|
619
622
|
activation?: "auto" | "manual" | undefined;
|
|
623
|
+
/** `underline` (default) or `segmented`: the tabs as a pill track with the selected one raised, like
|
|
624
|
+
* SegmentedControl, keeping every Tabs behaviour (panels, keepMounted, activation, tabProps). (5.10, Chamber-OS 72) */
|
|
625
|
+
variant?: "underline" | "segmented" | undefined;
|
|
626
|
+
/** With `variant="segmented"`: stretch the track to the full width, tabs sharing it equally. (5.10) */
|
|
627
|
+
fullWidth?: boolean | undefined;
|
|
620
628
|
}
|
|
621
629
|
export interface NavItem {
|
|
622
630
|
id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jirawatpyk/aura-tokens",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.10.0",
|
|
4
4
|
"description": "AURA Design System — tokens (CSS variables, Tailwind preset, Figma variables), theme contrast checks and token lint.",
|
|
5
5
|
"main": "tailwind.tokens.cjs",
|
|
6
6
|
"types": "components/index.d.ts",
|
package/tokens.json
CHANGED