@jirawatpyk/aura-tokens 4.8.0 → 4.9.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.css CHANGED
@@ -1,4 +1,4 @@
1
- /* AURA v4.8.0 — GENERATED by scripts/build-tokens.js from tokens.json. Do not edit by hand. */
1
+ /* AURA v4.9.0 — GENERATED by scripts/build-tokens.js 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"] {
@@ -1,4 +1,4 @@
1
- /* @ds-bundle: {"format":4,"namespace":"Aura","components":[{"name":"Icon"},{"name":"Button"},{"name":"IconButton"},{"name":"Menu"},{"name":"DropdownMenu"},{"name":"Checkbox"},{"name":"StatusPill"},{"name":"TextField"},{"name":"Textarea"},{"name":"Select"},{"name":"RadioGroup"},{"name":"Switch"},{"name":"Combobox"},{"name":"DatePicker"},{"name":"DateRangePicker"},{"name":"Calendar"},{"name":"Alert"},{"name":"Toaster"},{"name":"Tooltip"},{"name":"Dialog"},{"name":"Drawer"},{"name":"DataTable"},{"name":"Card"},{"name":"Tabs"},{"name":"SideNav"},{"name":"Breadcrumb"},{"name":"Avatar"},{"name":"Stack"},{"name":"Grid"},{"name":"Container"},{"name":"AppShell"},{"name":"Surface"},{"name":"Stat"},{"name":"TimePicker"},{"name":"FileUpload"},{"name":"ColorSchemeScript"},{"name":"ColorSchemeToggle"},{"name":"Badge"},{"name":"Tag"},{"name":"Progress"},{"name":"Skeleton"},{"name":"EmptyState"},{"name":"Pagination"},{"name":"Accordion"},{"name":"Popover"}]} */
1
+ /* @ds-bundle: {"format":4,"namespace":"Aura","components":[{"name":"Icon"},{"name":"Button"},{"name":"IconButton"},{"name":"Menu"},{"name":"DropdownMenu"},{"name":"Checkbox"},{"name":"StatusPill"},{"name":"TextField"},{"name":"Textarea"},{"name":"Select"},{"name":"RadioGroup"},{"name":"Switch"},{"name":"Combobox"},{"name":"DatePicker"},{"name":"DateRangePicker"},{"name":"Calendar"},{"name":"Alert"},{"name":"Toaster"},{"name":"Tooltip"},{"name":"Dialog"},{"name":"Drawer"},{"name":"DataTable"},{"name":"Card"},{"name":"Tabs"},{"name":"SideNav"},{"name":"Breadcrumb"},{"name":"Avatar"},{"name":"Stack"},{"name":"Grid"},{"name":"Container"},{"name":"AppShell"},{"name":"Surface"},{"name":"Stat"},{"name":"TimePicker"},{"name":"FileUpload"},{"name":"ColorSchemeScript"},{"name":"ColorSchemeToggle"},{"name":"Badge"},{"name":"Tag"},{"name":"Progress"},{"name":"Skeleton"},{"name":"EmptyState"},{"name":"Pagination"},{"name":"Accordion"},{"name":"Popover"},{"name":"NumberField"},{"name":"Stepper"},{"name":"SegmentedControl"}]} */
2
2
  window.Aura = (() => {
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
@@ -79,17 +79,20 @@ window.Aura = (() => {
79
79
  Icon: () => Icon,
80
80
  IconButton: () => IconButton,
81
81
  Menu: () => Menu,
82
+ NumberField: () => NumberField,
82
83
  Pagination: () => Pagination,
83
84
  Popover: () => Popover,
84
85
  Progress: () => Progress,
85
86
  RadioGroup: () => RadioGroup,
86
87
  STRINGS: () => STRINGS,
88
+ SegmentedControl: () => SegmentedControl,
87
89
  Select: () => Select,
88
90
  SideNav: () => SideNav,
89
91
  Skeleton: () => Skeleton,
90
92
  Stack: () => Stack,
91
93
  Stat: () => Stat,
92
94
  StatusPill: () => StatusPill,
95
+ Stepper: () => Stepper,
93
96
  Surface: () => Surface,
94
97
  Switch: () => Switch,
95
98
  Tabs: () => Tabs,
@@ -624,6 +627,12 @@ window.Aura = (() => {
624
627
  return "Up to " + n2 + " files";
625
628
  },
626
629
  colorScheme: "Colour scheme",
630
+ increase: "Increase",
631
+ decrease: "Decrease",
632
+ stepDone: "completed",
633
+ stepOf: function(i, total) {
634
+ return "Step " + i + " of " + total;
635
+ },
627
636
  schemeLight: "Light",
628
637
  schemeDark: "Dark",
629
638
  schemeSystem: "System",
@@ -716,6 +725,12 @@ window.Aura = (() => {
716
725
  return "\u0E41\u0E19\u0E1A\u0E44\u0E14\u0E49\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 " + n2 + " \u0E44\u0E1F\u0E25\u0E4C";
717
726
  },
718
727
  colorScheme: "\u0E42\u0E2B\u0E21\u0E14\u0E2A\u0E35",
728
+ increase: "\u0E40\u0E1E\u0E34\u0E48\u0E21",
729
+ decrease: "\u0E25\u0E14",
730
+ stepDone: "\u0E40\u0E2A\u0E23\u0E47\u0E08\u0E41\u0E25\u0E49\u0E27",
731
+ stepOf: function(i, total) {
732
+ return "\u0E02\u0E31\u0E49\u0E19\u0E17\u0E35\u0E48 " + i + " \u0E08\u0E32\u0E01 " + total;
733
+ },
719
734
  schemeLight: "\u0E2A\u0E27\u0E48\u0E32\u0E07",
720
735
  schemeDark: "\u0E21\u0E37\u0E14",
721
736
  schemeSystem: "\u0E15\u0E32\u0E21\u0E23\u0E30\u0E1A\u0E1A",
@@ -985,257 +1000,332 @@ window.Aura = (() => {
985
1000
  return norm(k).indexOf(q) >= 0;
986
1001
  });
987
1002
  }
988
- var Combobox = React16.forwardRef(function Combobox2(props, ref) {
989
- const t = useStrings();
990
- const auto = uid(), id = props.id || auto, listId = id + "-list";
991
- const options = (props.options || []).map(toOpt);
992
- const st = useMaybeControlled(
993
- props.value,
994
- props.defaultValue == null ? null : props.defaultValue,
995
- props.onChange
996
- );
997
- const value = st[0], setValue = st[1];
998
- const selected = options.filter(function(o) {
999
- return o.value === value;
1000
- })[0] || null;
1001
- const openState = React16.useState(false), open = openState[0], setOpen = openState[1];
1002
- const qState = React16.useState(null), query = qState[0], setQuery = qState[1];
1003
- const aState = React16.useState(0), active = aState[0], setActive = aState[1];
1004
- const posState = React16.useState(null);
1005
- const inputRef = React16.useRef(null), inputMerged = useMergedRef(ref, inputRef), boxRef = React16.useRef(null), listRef = React16.useRef(null);
1006
- const mounted = useMounted();
1007
- const limit = props.limit || 200;
1008
- const filter = props.filter || defaultFilter;
1009
- let shown = props.onSearch || query == null ? options : options.filter(function(o) {
1010
- return filter(o, query);
1011
- });
1012
- const more = shown.length > limit;
1013
- shown = shown.slice(0, limit);
1014
- const activeIdx = Math.min(active, shown.length - 1);
1015
- function place() {
1016
- if (!boxRef.current) return;
1017
- const r = boxRef.current.getBoundingClientRect();
1018
- const maxH = 320, below = window.innerHeight - r.bottom - 8, up = below < 200 && r.top > below;
1019
- posState[1]({
1020
- left: r.left,
1021
- width: r.width,
1022
- top: up ? void 0 : r.bottom + 4,
1023
- bottom: up ? window.innerHeight - r.top + 4 : void 0,
1024
- maxHeight: Math.min(maxH, (up ? r.top : below) - 8)
1003
+ var Combobox = React16.forwardRef(
1004
+ function Combobox2(all, ref) {
1005
+ const props = all;
1006
+ const multi = all.multiple === true;
1007
+ const mp = all;
1008
+ const t = useStrings();
1009
+ const auto = uid(), id = props.id || auto, listId = id + "-list";
1010
+ const options = (props.options || []).map(toOpt);
1011
+ const st = useMaybeControlled(
1012
+ multi ? mp.value : props.value === void 0 ? void 0 : props.value == null ? [] : [props.value],
1013
+ multi ? mp.defaultValue || [] : props.defaultValue == null ? [] : [props.defaultValue],
1014
+ function(next) {
1015
+ if (multi) {
1016
+ if (mp.onChange) mp.onChange(next);
1017
+ } else if (props.onChange) props.onChange(next.length ? next[0] : null);
1018
+ }
1019
+ );
1020
+ const values = st[0], setValues = st[1];
1021
+ const value = values.length ? values[0] : null;
1022
+ function setValue(v) {
1023
+ setValues(v == null ? [] : [v]);
1024
+ }
1025
+ const isPicked = function(v) {
1026
+ return values.indexOf(v) >= 0;
1027
+ };
1028
+ const full = multi && mp.max != null && values.length >= mp.max;
1029
+ const selected = multi ? null : options.filter(function(o) {
1030
+ return o.value === value;
1031
+ })[0] || null;
1032
+ const picked = multi ? values.map(function(v) {
1033
+ return options.filter(function(o) {
1034
+ return o.value === v;
1035
+ })[0];
1036
+ }).filter(Boolean) : [];
1037
+ const openState = React16.useState(false), open = openState[0], setOpen = openState[1];
1038
+ const qState = React16.useState(null), query = qState[0], setQuery = qState[1];
1039
+ const aState = React16.useState(0), active = aState[0], setActive = aState[1];
1040
+ const posState = React16.useState(null);
1041
+ const inputRef = React16.useRef(null), inputMerged = useMergedRef(ref, inputRef), boxRef = React16.useRef(null), listRef = React16.useRef(null);
1042
+ const mounted = useMounted();
1043
+ const limit = props.limit || 200;
1044
+ const filter = props.filter || defaultFilter;
1045
+ let shown = props.onSearch || query == null ? options : options.filter(function(o) {
1046
+ return filter(o, query);
1025
1047
  });
1026
- }
1027
- useIsoLayoutEffect(
1028
- function() {
1029
- if (open) place();
1030
- },
1031
- [open, shown.length]
1032
- );
1033
- React16.useEffect(
1034
- function() {
1035
- if (!open) return;
1036
- function outside(e) {
1037
- if (boxRef.current && boxRef.current.contains(e.target)) return;
1038
- if (listRef.current && listRef.current.contains(e.target)) return;
1039
- close(false);
1048
+ const more = shown.length > limit;
1049
+ shown = shown.slice(0, limit);
1050
+ const activeIdx = Math.min(active, shown.length - 1);
1051
+ function place() {
1052
+ if (!boxRef.current) return;
1053
+ const r = boxRef.current.getBoundingClientRect();
1054
+ const maxH = 320, below = window.innerHeight - r.bottom - 8, up = below < 200 && r.top > below;
1055
+ posState[1]({
1056
+ left: r.left,
1057
+ width: r.width,
1058
+ top: up ? void 0 : r.bottom + 4,
1059
+ bottom: up ? window.innerHeight - r.top + 4 : void 0,
1060
+ maxHeight: Math.min(maxH, (up ? r.top : below) - 8)
1061
+ });
1062
+ }
1063
+ useIsoLayoutEffect(
1064
+ function() {
1065
+ if (open) place();
1066
+ },
1067
+ [open, shown.length]
1068
+ );
1069
+ React16.useEffect(
1070
+ function() {
1071
+ if (!open) return;
1072
+ function outside(e) {
1073
+ if (boxRef.current && boxRef.current.contains(e.target)) return;
1074
+ if (listRef.current && listRef.current.contains(e.target)) return;
1075
+ close(false);
1076
+ }
1077
+ function onScroll(e) {
1078
+ if (!listRef.current || !listRef.current.contains(e.target)) place();
1079
+ }
1080
+ document.addEventListener("pointerdown", outside, true);
1081
+ window.addEventListener("scroll", onScroll, true);
1082
+ window.addEventListener("resize", place);
1083
+ return function() {
1084
+ document.removeEventListener("pointerdown", outside, true);
1085
+ window.removeEventListener("scroll", onScroll, true);
1086
+ window.removeEventListener("resize", place);
1087
+ };
1088
+ },
1089
+ [open]
1090
+ );
1091
+ React16.useEffect(
1092
+ function() {
1093
+ if (!open || !listRef.current) return;
1094
+ const el = listRef.current.querySelector('[data-idx="' + activeIdx + '"]');
1095
+ if (el && el.scrollIntoView) el.scrollIntoView({ block: "nearest" });
1096
+ },
1097
+ [activeIdx, open]
1098
+ );
1099
+ function openList() {
1100
+ if (!open && !props.disabled && !props.readOnly) {
1101
+ setOpen(true);
1102
+ const i = selected ? shown.indexOf(selected) : 0;
1103
+ setActive(i < 0 ? 0 : i);
1040
1104
  }
1041
- function onScroll(e) {
1042
- if (!listRef.current || !listRef.current.contains(e.target)) place();
1105
+ }
1106
+ function close(restoreLabel) {
1107
+ setOpen(false);
1108
+ setQuery(null);
1109
+ }
1110
+ function choose(o) {
1111
+ if (!o || o.disabled) return;
1112
+ if (multi) {
1113
+ if (isPicked(o.value))
1114
+ setValues(
1115
+ values.filter(function(v) {
1116
+ return v !== o.value;
1117
+ })
1118
+ );
1119
+ else if (!full) setValues(values.concat([o.value]));
1120
+ setQuery(null);
1121
+ if (inputRef.current) inputRef.current.focus();
1122
+ return;
1043
1123
  }
1044
- document.addEventListener("pointerdown", outside, true);
1045
- window.addEventListener("scroll", onScroll, true);
1046
- window.addEventListener("resize", place);
1047
- return function() {
1048
- document.removeEventListener("pointerdown", outside, true);
1049
- window.removeEventListener("scroll", onScroll, true);
1050
- window.removeEventListener("resize", place);
1051
- };
1052
- },
1053
- [open]
1054
- );
1055
- React16.useEffect(
1056
- function() {
1057
- if (!open || !listRef.current) return;
1058
- const el = listRef.current.querySelector('[data-idx="' + activeIdx + '"]');
1059
- if (el && el.scrollIntoView) el.scrollIntoView({ block: "nearest" });
1060
- },
1061
- [activeIdx, open]
1062
- );
1063
- function openList() {
1064
- if (!open && !props.disabled && !props.readOnly) {
1065
- setOpen(true);
1066
- const i = selected ? shown.indexOf(selected) : 0;
1067
- setActive(i < 0 ? 0 : i);
1124
+ setValue(o.value);
1125
+ setQuery(null);
1126
+ setOpen(false);
1127
+ if (inputRef.current) inputRef.current.focus();
1068
1128
  }
1069
- }
1070
- function close(restoreLabel) {
1071
- setOpen(false);
1072
- setQuery(null);
1073
- }
1074
- function choose(o) {
1075
- if (!o || o.disabled) return;
1076
- setValue(o.value);
1077
- setQuery(null);
1078
- setOpen(false);
1079
- if (inputRef.current) inputRef.current.focus();
1080
- }
1081
- function onKeyDown(e) {
1082
- const k = e.key;
1083
- if (k === "ArrowDown") {
1084
- e.preventDefault();
1085
- if (!open) openList();
1086
- else setActive(Math.min(activeIdx + 1, shown.length - 1));
1087
- } else if (k === "ArrowUp") {
1088
- e.preventDefault();
1089
- if (!open) openList();
1090
- else setActive(Math.max(activeIdx - 1, 0));
1091
- } else if (k === "Home" && open) {
1092
- e.preventDefault();
1093
- setActive(0);
1094
- } else if (k === "End" && open) {
1095
- e.preventDefault();
1096
- setActive(shown.length - 1);
1097
- } else if (k === "Enter") {
1098
- if (open && shown[activeIdx]) {
1129
+ function onKeyDown(e) {
1130
+ const k = e.key;
1131
+ if (k === "ArrowDown") {
1099
1132
  e.preventDefault();
1100
- choose(shown[activeIdx]);
1101
- }
1102
- } else if (k === "Escape") {
1103
- if (open) {
1133
+ if (!open) openList();
1134
+ else setActive(Math.min(activeIdx + 1, shown.length - 1));
1135
+ } else if (k === "ArrowUp") {
1104
1136
  e.preventDefault();
1105
- e.stopPropagation();
1106
- close();
1107
- } else if (props.clearable !== false && value != null && query == null) {
1108
- setValue(null);
1137
+ if (!open) openList();
1138
+ else setActive(Math.max(activeIdx - 1, 0));
1139
+ } else if (k === "Home" && open) {
1140
+ e.preventDefault();
1141
+ setActive(0);
1142
+ } else if (k === "End" && open) {
1143
+ e.preventDefault();
1144
+ setActive(shown.length - 1);
1145
+ } else if (k === "Enter") {
1146
+ if (open && shown[activeIdx]) {
1147
+ e.preventDefault();
1148
+ choose(shown[activeIdx]);
1149
+ }
1150
+ } else if (k === "Escape") {
1151
+ if (open) {
1152
+ e.preventDefault();
1153
+ e.stopPropagation();
1154
+ close();
1155
+ } else if (!multi && props.clearable !== false && value != null && query == null) {
1156
+ setValue(null);
1157
+ }
1158
+ } else if (k === "Backspace" && multi && !text && values.length) {
1159
+ setValues(values.slice(0, -1));
1160
+ } else if (k === "Tab") {
1161
+ if (open) close();
1109
1162
  }
1110
- } else if (k === "Tab") {
1111
- if (open) close();
1112
1163
  }
1113
- }
1114
- const text = query != null ? query : selected ? selected.label : "";
1115
- const optId = function(i) {
1116
- return id + "-opt-" + i;
1117
- };
1118
- const list = open && mounted && posState[0] ? (0, import_react_dom2.createPortal)(
1119
- /* @__PURE__ */ React16.createElement("div", { ref: listRef, className: "aura-combo__popover", style: posState[0] }, /* @__PURE__ */ React16.createElement("ul", { id: listId, role: "listbox", "aria-label": props.label, className: "aura-combo__list" }, props.loading ? /* @__PURE__ */ React16.createElement("li", { className: "aura-combo__note", role: "presentation" }, /* @__PURE__ */ React16.createElement(Icon, { name: "loader-circle", className: "aura-spin" }), props.loadingText || t.searching) : !shown.length ? /* @__PURE__ */ React16.createElement("li", { className: "aura-combo__note", role: "presentation" }, props.emptyText || t.noMatches) : shown.map(function(o, i) {
1120
- const isSel = selected && o.value === selected.value;
1121
- return /* @__PURE__ */ React16.createElement(
1122
- "li",
1164
+ const text = query != null ? query : selected ? selected.label : "";
1165
+ const summaryId = id + "-picked";
1166
+ const optId = function(i) {
1167
+ return id + "-opt-" + i;
1168
+ };
1169
+ const list = open && mounted && posState[0] ? (0, import_react_dom2.createPortal)(
1170
+ /* @__PURE__ */ React16.createElement("div", { ref: listRef, className: "aura-combo__popover", style: posState[0] }, /* @__PURE__ */ React16.createElement(
1171
+ "ul",
1123
1172
  {
1124
- key: o.value,
1125
- id: optId(i),
1126
- role: "option",
1127
- "data-idx": i,
1128
- "aria-selected": isSel,
1129
- "aria-disabled": o.disabled || void 0,
1130
- className: cx(
1131
- "aura-combo__option",
1132
- i === activeIdx && "is-active",
1133
- isSel && "is-selected",
1134
- o.disabled && "is-disabled"
1135
- ),
1136
- onPointerDown: function(e) {
1137
- e.preventDefault();
1138
- },
1139
- onClick: function() {
1140
- choose(o);
1141
- },
1142
- onPointerMove: function() {
1143
- if (activeIdx !== i) setActive(i);
1144
- }
1173
+ id: listId,
1174
+ role: "listbox",
1175
+ "aria-label": props.label,
1176
+ "aria-multiselectable": multi || void 0,
1177
+ className: "aura-combo__list"
1145
1178
  },
1146
- o.icon ? /* @__PURE__ */ React16.createElement(Icon, { name: o.icon }) : null,
1147
- /* @__PURE__ */ React16.createElement("span", { className: "aura-combo__text" }, /* @__PURE__ */ React16.createElement("span", { className: "aura-combo__label" }, o.label), o.description ? /* @__PURE__ */ React16.createElement("span", { className: "aura-combo__desc" }, o.description) : null),
1148
- isSel ? /* @__PURE__ */ React16.createElement(Icon, { name: "check", className: "aura-combo__check" }) : null
1149
- );
1150
- }), more && !props.loading ? /* @__PURE__ */ React16.createElement("li", { className: "aura-combo__note", role: "presentation" }, t.keepTyping((props.options || []).length)) : null)),
1151
- document.body
1152
- ) : null;
1153
- return /* @__PURE__ */ React16.createElement(
1154
- Field,
1155
- {
1156
- id,
1157
- label: props.label,
1158
- hint: props.hint,
1159
- error: props.error,
1160
- required: props.required,
1161
- optional: props.optional,
1162
- disabled: props.disabled,
1163
- className: props.className
1164
- },
1165
- /* @__PURE__ */ React16.createElement("div", { ref: boxRef, className: cx("aura-input aura-combo has-icon", open && "is-open") }, /* @__PURE__ */ React16.createElement(Icon, { name: props.icon || "search", className: "aura-input__icon" }), /* @__PURE__ */ React16.createElement(
1166
- "input",
1179
+ props.loading ? /* @__PURE__ */ React16.createElement("li", { className: "aura-combo__note", role: "presentation" }, /* @__PURE__ */ React16.createElement(Icon, { name: "loader-circle", className: "aura-spin" }), props.loadingText || t.searching) : !shown.length ? /* @__PURE__ */ React16.createElement("li", { className: "aura-combo__note", role: "presentation" }, props.emptyText || t.noMatches) : shown.map(function(o, i) {
1180
+ const isSel = multi ? isPicked(o.value) : !!selected && o.value === selected.value;
1181
+ const blocked = o.disabled || multi && full && !isSel;
1182
+ return /* @__PURE__ */ React16.createElement(
1183
+ "li",
1184
+ {
1185
+ key: o.value,
1186
+ id: optId(i),
1187
+ role: "option",
1188
+ "data-idx": i,
1189
+ "aria-selected": isSel,
1190
+ "aria-disabled": blocked || void 0,
1191
+ className: cx(
1192
+ "aura-combo__option",
1193
+ i === activeIdx && "is-active",
1194
+ isSel && "is-selected",
1195
+ blocked && "is-disabled"
1196
+ ),
1197
+ onPointerDown: function(e) {
1198
+ e.preventDefault();
1199
+ },
1200
+ onClick: function() {
1201
+ if (!blocked || isSel) choose(o);
1202
+ },
1203
+ onPointerMove: function() {
1204
+ if (activeIdx !== i) setActive(i);
1205
+ }
1206
+ },
1207
+ o.icon ? /* @__PURE__ */ React16.createElement(Icon, { name: o.icon }) : null,
1208
+ /* @__PURE__ */ React16.createElement("span", { className: "aura-combo__text" }, /* @__PURE__ */ React16.createElement("span", { className: "aura-combo__label" }, o.label), o.description ? /* @__PURE__ */ React16.createElement("span", { className: "aura-combo__desc" }, o.description) : null),
1209
+ isSel ? /* @__PURE__ */ React16.createElement(Icon, { name: "check", className: "aura-combo__check" }) : null
1210
+ );
1211
+ }),
1212
+ more && !props.loading ? /* @__PURE__ */ React16.createElement("li", { className: "aura-combo__note", role: "presentation" }, t.keepTyping((props.options || []).length)) : null
1213
+ )),
1214
+ document.body
1215
+ ) : null;
1216
+ return /* @__PURE__ */ React16.createElement(
1217
+ Field,
1167
1218
  {
1168
- ref: inputMerged,
1169
1219
  id,
1170
- type: "text",
1171
- role: "combobox",
1172
- className: "aura-input__control",
1173
- autoComplete: "off",
1174
- "aria-expanded": open,
1175
- "aria-controls": listId,
1176
- "aria-autocomplete": "list",
1177
- "aria-activedescendant": open && shown[activeIdx] ? optId(activeIdx) : void 0,
1178
- "aria-invalid": props.error ? true : void 0,
1179
- "aria-describedby": props.error ? id + "-error" : props.hint ? id + "-hint" : void 0,
1180
- placeholder: props.placeholder,
1181
- disabled: props.disabled,
1182
- readOnly: props.readOnly,
1220
+ label: props.label,
1221
+ hint: props.hint,
1222
+ error: props.error,
1183
1223
  required: props.required,
1184
- name: props.name,
1185
- value: text,
1186
- onChange: function(e) {
1187
- setQuery(e.target.value);
1188
- setActive(0);
1189
- if (!open) setOpen(true);
1190
- if (props.onSearch) props.onSearch(e.target.value);
1191
- },
1192
- onClick: openList,
1193
- onKeyDown,
1194
- onBlur: function() {
1195
- setTimeout(function() {
1196
- if (listRef.current && listRef.current.contains(document.activeElement)) return;
1197
- setOpen(false);
1198
- setQuery(null);
1199
- }, 0);
1200
- }
1201
- }
1202
- ), props.clearable !== false && value != null && !props.disabled ? /* @__PURE__ */ React16.createElement(
1203
- "button",
1204
- {
1205
- type: "button",
1206
- className: "aura-combo__clear",
1207
- "aria-label": t.clear(props.label),
1208
- tabIndex: -1,
1209
- onClick: function() {
1210
- setValue(null);
1211
- setQuery(null);
1212
- if (inputRef.current) inputRef.current.focus();
1213
- }
1224
+ optional: props.optional,
1225
+ disabled: props.disabled,
1226
+ className: props.className
1214
1227
  },
1215
- /* @__PURE__ */ React16.createElement(Icon, { name: "x" })
1216
- ) : null, /* @__PURE__ */ React16.createElement(
1217
- "button",
1218
- {
1219
- type: "button",
1220
- tabIndex: -1,
1221
- "aria-hidden": true,
1222
- className: "aura-combo__toggle",
1223
- onPointerDown: function(e) {
1224
- e.preventDefault();
1225
- },
1226
- onClick: function() {
1227
- if (open) close();
1228
- else {
1229
- openList();
1230
- inputRef.current && inputRef.current.focus();
1228
+ /* @__PURE__ */ React16.createElement("div", { ref: boxRef, className: cx("aura-input aura-combo has-icon", open && "is-open", multi && "is-multi") }, /* @__PURE__ */ React16.createElement(Icon, { name: props.icon || "search", className: "aura-input__icon" }), multi && picked.length ? /* @__PURE__ */ React16.createElement("span", { className: "aura-combo__chips" }, picked.map(function(o) {
1229
+ return /* @__PURE__ */ React16.createElement("span", { key: o.value, className: "aura-combo__chip" }, /* @__PURE__ */ React16.createElement("span", { className: "aura-combo__chip-label" }, o.label), props.disabled || props.readOnly ? null : /* @__PURE__ */ React16.createElement(
1230
+ "button",
1231
+ {
1232
+ type: "button",
1233
+ tabIndex: -1,
1234
+ className: "aura-combo__chip-remove",
1235
+ "aria-label": t.remove(o.label),
1236
+ onPointerDown: function(e) {
1237
+ e.preventDefault();
1238
+ },
1239
+ onClick: function() {
1240
+ setValues(
1241
+ values.filter(function(v) {
1242
+ return v !== o.value;
1243
+ })
1244
+ );
1245
+ if (inputRef.current) inputRef.current.focus();
1246
+ }
1247
+ },
1248
+ /* @__PURE__ */ React16.createElement(Icon, { name: "x" })
1249
+ ));
1250
+ })) : null, multi ? /* @__PURE__ */ React16.createElement("span", { id: summaryId, className: "aura-sr-only" }, picked.length ? t.selectedCount(picked.length) + ": " + picked.map(function(o) {
1251
+ return o.label;
1252
+ }).join(", ") : "") : null, multi && props.name ? values.map(function(v) {
1253
+ return /* @__PURE__ */ React16.createElement("input", { key: v, type: "hidden", name: props.name, value: v });
1254
+ }) : null, /* @__PURE__ */ React16.createElement(
1255
+ "input",
1256
+ {
1257
+ ref: inputMerged,
1258
+ id,
1259
+ type: "text",
1260
+ role: "combobox",
1261
+ className: "aura-input__control",
1262
+ autoComplete: "off",
1263
+ "aria-expanded": open,
1264
+ "aria-controls": listId,
1265
+ "aria-autocomplete": "list",
1266
+ "aria-activedescendant": open && shown[activeIdx] ? optId(activeIdx) : void 0,
1267
+ "aria-invalid": props.error ? true : void 0,
1268
+ "aria-describedby": [props.error ? id + "-error" : props.hint ? id + "-hint" : "", multi && picked.length ? summaryId : ""].filter(Boolean).join(" ") || void 0,
1269
+ placeholder: multi && values.length ? void 0 : props.placeholder,
1270
+ disabled: props.disabled,
1271
+ readOnly: props.readOnly,
1272
+ required: props.required && (!multi || !values.length),
1273
+ name: multi ? void 0 : props.name,
1274
+ value: text,
1275
+ onChange: function(e) {
1276
+ setQuery(e.target.value);
1277
+ setActive(0);
1278
+ if (!open) setOpen(true);
1279
+ if (props.onSearch) props.onSearch(e.target.value);
1280
+ },
1281
+ onClick: openList,
1282
+ onKeyDown,
1283
+ onBlur: function() {
1284
+ setTimeout(function() {
1285
+ if (listRef.current && listRef.current.contains(document.activeElement)) return;
1286
+ setOpen(false);
1287
+ setQuery(null);
1288
+ }, 0);
1231
1289
  }
1232
1290
  }
1233
- },
1234
- /* @__PURE__ */ React16.createElement(Icon, { name: "chevron-down" })
1235
- )),
1236
- list
1237
- );
1238
- });
1291
+ ), props.clearable !== false && values.length && !props.disabled ? /* @__PURE__ */ React16.createElement(
1292
+ "button",
1293
+ {
1294
+ type: "button",
1295
+ className: "aura-combo__clear",
1296
+ "aria-label": t.clear(props.label),
1297
+ tabIndex: -1,
1298
+ onClick: function() {
1299
+ setValues([]);
1300
+ setQuery(null);
1301
+ if (inputRef.current) inputRef.current.focus();
1302
+ }
1303
+ },
1304
+ /* @__PURE__ */ React16.createElement(Icon, { name: "x" })
1305
+ ) : null, /* @__PURE__ */ React16.createElement(
1306
+ "button",
1307
+ {
1308
+ type: "button",
1309
+ tabIndex: -1,
1310
+ "aria-hidden": true,
1311
+ className: "aura-combo__toggle",
1312
+ onPointerDown: function(e) {
1313
+ e.preventDefault();
1314
+ },
1315
+ onClick: function() {
1316
+ if (open) close();
1317
+ else {
1318
+ openList();
1319
+ inputRef.current && inputRef.current.focus();
1320
+ }
1321
+ }
1322
+ },
1323
+ /* @__PURE__ */ React16.createElement(Icon, { name: "chevron-down" })
1324
+ )),
1325
+ list
1326
+ );
1327
+ }
1328
+ );
1239
1329
 
1240
1330
  // src/DatePicker.tsx
1241
1331
  var React17 = __toESM(require_react(), 1);
@@ -4802,5 +4892,323 @@ window.Aura = (() => {
4802
4892
  "aria-controls": open ? id : void 0
4803
4893
  }), panel);
4804
4894
  });
4895
+
4896
+ // src/NumberField.tsx
4897
+ var React48 = __toESM(require_react(), 1);
4898
+ function decimalsOf(n2) {
4899
+ const s = String(n2);
4900
+ const i = s.indexOf(".");
4901
+ return i < 0 ? 0 : s.length - i - 1;
4902
+ }
4903
+ function parse(text) {
4904
+ const s = text.replace(/[,\s ]/g, "");
4905
+ if (!/^-?(\d+\.?\d*|\.\d+)$/.test(s)) return NaN;
4906
+ return Number(s);
4907
+ }
4908
+ var NumberField = React48.forwardRef(function NumberField2(props, ref) {
4909
+ const t = useStrings();
4910
+ const auto = uid(), id = props.id || auto;
4911
+ const step = props.step || 1;
4912
+ const decimals = props.decimals != null ? props.decimals : decimalsOf(step);
4913
+ const st = useMaybeControlled(
4914
+ props.value,
4915
+ props.defaultValue == null ? null : props.defaultValue,
4916
+ props.onChange
4917
+ );
4918
+ const value = st[0], setValue = st[1];
4919
+ const draftState = React48.useState(null), draft = draftState[0], setDraft = draftState[1];
4920
+ function fmt2(n2) {
4921
+ if (n2 == null || isNaN(n2)) return "";
4922
+ return n2.toLocaleString("en", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
4923
+ }
4924
+ function fit2(n2) {
4925
+ let v = n2;
4926
+ if (props.min != null && v < props.min) v = props.min;
4927
+ if (props.max != null && v > props.max) v = props.max;
4928
+ const f = Math.pow(10, decimals);
4929
+ return Math.round(v * f) / f;
4930
+ }
4931
+ function nudge(by) {
4932
+ if (props.disabled || props.readOnly) return;
4933
+ const base = value == null ? props.min != null && props.min > 0 ? props.min - by : 0 : value;
4934
+ const next = fit2(base + by);
4935
+ setValue(next);
4936
+ setDraft(null);
4937
+ }
4938
+ function onKeyDown(e) {
4939
+ const k = e.key;
4940
+ let by = 0;
4941
+ if (k === "ArrowUp") by = step;
4942
+ else if (k === "ArrowDown") by = -step;
4943
+ else if (k === "PageUp") by = step * 10;
4944
+ else if (k === "PageDown") by = -step * 10;
4945
+ else if (k === "Home" && props.min != null) {
4946
+ e.preventDefault();
4947
+ setValue(props.min);
4948
+ setDraft(null);
4949
+ return;
4950
+ } else if (k === "End" && props.max != null) {
4951
+ e.preventDefault();
4952
+ setValue(props.max);
4953
+ setDraft(null);
4954
+ return;
4955
+ }
4956
+ if (by) {
4957
+ e.preventDefault();
4958
+ nudge(by);
4959
+ }
4960
+ }
4961
+ const atMin = value != null && props.min != null && value <= props.min;
4962
+ const atMax = value != null && props.max != null && value >= props.max;
4963
+ const affixText = function(x) {
4964
+ return typeof x === "string" || typeof x === "number" ? String(x) : "";
4965
+ };
4966
+ const valueText = value == null ? void 0 : [affixText(props.prefix), fmt2(value), affixText(props.suffix)].join(" ").trim();
4967
+ const stepper = props.stepper !== false && !props.readOnly;
4968
+ return /* @__PURE__ */ React48.createElement(
4969
+ Field,
4970
+ {
4971
+ id,
4972
+ label: props.label,
4973
+ hint: props.hint,
4974
+ error: props.error,
4975
+ required: props.required,
4976
+ optional: props.optional,
4977
+ disabled: props.disabled,
4978
+ className: props.className
4979
+ },
4980
+ /* @__PURE__ */ React48.createElement("div", { className: cx("aura-input aura-number", stepper && "has-stepper") }, props.prefix != null ? /* @__PURE__ */ React48.createElement("span", { className: "aura-number__affix", "aria-hidden": true }, props.prefix) : null, /* @__PURE__ */ React48.createElement(
4981
+ "input",
4982
+ {
4983
+ ref,
4984
+ id,
4985
+ type: "text",
4986
+ role: "spinbutton",
4987
+ inputMode: decimals > 0 || props.min != null && props.min < 0 ? "decimal" : "numeric",
4988
+ autoComplete: "off",
4989
+ className: "aura-input__control",
4990
+ name: props.name,
4991
+ placeholder: props.placeholder,
4992
+ disabled: props.disabled,
4993
+ readOnly: props.readOnly,
4994
+ required: props.required,
4995
+ "aria-valuenow": value == null ? void 0 : value,
4996
+ "aria-valuemin": props.min,
4997
+ "aria-valuemax": props.max,
4998
+ "aria-valuetext": valueText,
4999
+ "aria-invalid": props.error ? true : void 0,
5000
+ "aria-describedby": describedBy(id, props),
5001
+ value: draft != null ? draft : fmt2(value),
5002
+ onFocus: function() {
5003
+ setDraft(fmt2(value));
5004
+ },
5005
+ onChange: function(e) {
5006
+ const text = e.target.value;
5007
+ setDraft(text);
5008
+ if (!text.trim()) setValue(null);
5009
+ else {
5010
+ const n2 = parse(text);
5011
+ if (!isNaN(n2)) setValue(n2);
5012
+ }
5013
+ },
5014
+ onBlur: function(e) {
5015
+ const n2 = draft == null ? value : !draft.trim() ? null : parse(draft);
5016
+ if (n2 == null) {
5017
+ if (value != null) setValue(null);
5018
+ } else if (!isNaN(n2)) {
5019
+ const f = fit2(n2);
5020
+ if (f !== value) setValue(f);
5021
+ }
5022
+ setDraft(null);
5023
+ if (props.onBlur) props.onBlur(e);
5024
+ },
5025
+ onKeyDown
5026
+ }
5027
+ ), props.suffix != null ? /* @__PURE__ */ React48.createElement("span", { className: "aura-number__affix", "aria-hidden": true }, props.suffix) : null, stepper ? /* @__PURE__ */ React48.createElement("span", { className: "aura-number__steps" }, /* @__PURE__ */ React48.createElement(
5028
+ "button",
5029
+ {
5030
+ type: "button",
5031
+ tabIndex: -1,
5032
+ className: "aura-number__step",
5033
+ "aria-label": t.decrease,
5034
+ "aria-controls": id,
5035
+ disabled: props.disabled || atMin,
5036
+ onPointerDown: function(e) {
5037
+ e.preventDefault();
5038
+ },
5039
+ onClick: function() {
5040
+ nudge(-step);
5041
+ }
5042
+ },
5043
+ /* @__PURE__ */ React48.createElement(Icon, { name: "minus" })
5044
+ ), /* @__PURE__ */ React48.createElement(
5045
+ "button",
5046
+ {
5047
+ type: "button",
5048
+ tabIndex: -1,
5049
+ className: "aura-number__step",
5050
+ "aria-label": t.increase,
5051
+ "aria-controls": id,
5052
+ disabled: props.disabled || atMax,
5053
+ onPointerDown: function(e) {
5054
+ e.preventDefault();
5055
+ },
5056
+ onClick: function() {
5057
+ nudge(step);
5058
+ }
5059
+ },
5060
+ /* @__PURE__ */ React48.createElement(Icon, { name: "plus" })
5061
+ )) : null)
5062
+ );
5063
+ });
5064
+
5065
+ // src/Stepper.tsx
5066
+ var React49 = __toESM(require_react(), 1);
5067
+ var Stepper = React49.forwardRef(function Stepper2(props, ref) {
5068
+ const t = useStrings();
5069
+ const steps = props.steps || [];
5070
+ let at = -1;
5071
+ steps.forEach(function(s, i) {
5072
+ if (s.id === props.current) at = i;
5073
+ });
5074
+ if (at < 0) at = 0;
5075
+ const vertical = props.orientation === "vertical";
5076
+ const cur = steps[at];
5077
+ return /* @__PURE__ */ React49.createElement(
5078
+ "nav",
5079
+ {
5080
+ ref,
5081
+ "aria-label": props.label,
5082
+ className: cx("aura-stepper", vertical ? "aura-stepper--vertical" : "aura-stepper--horizontal", props.className)
5083
+ },
5084
+ /* @__PURE__ */ React49.createElement("ol", { className: "aura-stepper__list" }, steps.map(function(s, i) {
5085
+ const state = i < at ? "done" : i === at ? "current" : "upcoming";
5086
+ const marker = /* @__PURE__ */ React49.createElement("span", { className: "aura-stepper__marker", "aria-hidden": true }, state === "done" ? /* @__PURE__ */ React49.createElement(Icon, { name: "check" }) : i + 1);
5087
+ const text = /* @__PURE__ */ React49.createElement("span", { className: "aura-stepper__text" }, /* @__PURE__ */ React49.createElement("span", { className: "aura-stepper__label" }, s.label, state === "done" ? /* @__PURE__ */ React49.createElement("span", { className: "aura-sr-only" }, ", " + t.stepDone) : null), s.description ? /* @__PURE__ */ React49.createElement("span", { className: "aura-stepper__desc" }, s.description) : null);
5088
+ const clickable = state === "done" && !!props.onStepClick;
5089
+ return /* @__PURE__ */ React49.createElement(
5090
+ "li",
5091
+ {
5092
+ key: s.id,
5093
+ className: cx("aura-stepper__item", "is-" + state),
5094
+ "aria-current": state === "current" ? "step" : void 0
5095
+ },
5096
+ clickable ? /* @__PURE__ */ React49.createElement(
5097
+ "button",
5098
+ {
5099
+ type: "button",
5100
+ className: "aura-stepper__step aura-focusable",
5101
+ onClick: function() {
5102
+ props.onStepClick(s.id);
5103
+ }
5104
+ },
5105
+ marker,
5106
+ text
5107
+ ) : /* @__PURE__ */ React49.createElement("span", { className: "aura-stepper__step" }, marker, text)
5108
+ );
5109
+ })),
5110
+ !vertical && cur ? /* @__PURE__ */ React49.createElement("p", { className: "aura-stepper__compact", "aria-hidden": true }, /* @__PURE__ */ React49.createElement("span", { className: "aura-stepper__count" }, t.stepOf(at + 1, steps.length)), /* @__PURE__ */ React49.createElement("span", { className: "aura-stepper__compact-label" }, cur.label)) : null
5111
+ );
5112
+ });
5113
+
5114
+ // src/SegmentedControl.tsx
5115
+ var React50 = __toESM(require_react(), 1);
5116
+ function toOpt2(o) {
5117
+ return typeof o === "object" ? o : { value: o, label: o };
5118
+ }
5119
+ var SegmentedControl = React50.forwardRef(
5120
+ function SegmentedControl2(props, ref) {
5121
+ const options = (props.options || []).map(toOpt2);
5122
+ const firstEnabled = options.filter(function(o) {
5123
+ return !o.disabled;
5124
+ })[0];
5125
+ const st = useMaybeControlled(
5126
+ props.value,
5127
+ props.defaultValue != null ? props.defaultValue : firstEnabled ? firstEnabled.value : void 0,
5128
+ props.onChange
5129
+ );
5130
+ const value = st[0], setValue = st[1];
5131
+ const auto = uid(), id = props.id || auto;
5132
+ const refs = React50.useRef([]);
5133
+ const selIdx = options.findIndex(function(o) {
5134
+ return o.value === value;
5135
+ });
5136
+ const tabIdx = selIdx >= 0 && !options[selIdx].disabled ? selIdx : options.indexOf(firstEnabled);
5137
+ function move(from, dir) {
5138
+ const n2 = options.length;
5139
+ for (let k = 1; k <= n2; k++) {
5140
+ const i = ((from + dir * k) % n2 + n2) % n2;
5141
+ if (!options[i].disabled) {
5142
+ setValue(options[i].value);
5143
+ const el = refs.current[i];
5144
+ if (el) el.focus();
5145
+ return;
5146
+ }
5147
+ }
5148
+ }
5149
+ function onKeyDown(e, i) {
5150
+ const k = e.key;
5151
+ if (k === "ArrowRight" || k === "ArrowDown") {
5152
+ e.preventDefault();
5153
+ move(i, 1);
5154
+ } else if (k === "ArrowLeft" || k === "ArrowUp") {
5155
+ e.preventDefault();
5156
+ move(i, -1);
5157
+ } else if (k === "Home") {
5158
+ e.preventDefault();
5159
+ move(-1, 1);
5160
+ } else if (k === "End") {
5161
+ e.preventDefault();
5162
+ move(options.length, -1);
5163
+ }
5164
+ }
5165
+ return /* @__PURE__ */ React50.createElement(
5166
+ "div",
5167
+ {
5168
+ ref,
5169
+ id,
5170
+ role: "radiogroup",
5171
+ "aria-label": props.label,
5172
+ "aria-disabled": props.disabled || void 0,
5173
+ className: cx(
5174
+ "aura-segmented",
5175
+ props.size === "sm" && "aura-segmented--sm",
5176
+ props.fullWidth && "is-full",
5177
+ props.disabled && "is-disabled",
5178
+ props.className
5179
+ )
5180
+ },
5181
+ options.map(function(o, i) {
5182
+ const on = o.value === value;
5183
+ const off = props.disabled || o.disabled;
5184
+ return /* @__PURE__ */ React50.createElement(
5185
+ "button",
5186
+ {
5187
+ key: o.value,
5188
+ ref: function(el) {
5189
+ refs.current[i] = el;
5190
+ },
5191
+ type: "button",
5192
+ role: "radio",
5193
+ "aria-checked": on,
5194
+ "aria-label": o.iconOnly ? o.label : void 0,
5195
+ title: o.iconOnly ? o.label : void 0,
5196
+ tabIndex: i === tabIdx && !props.disabled ? 0 : -1,
5197
+ disabled: off,
5198
+ className: cx("aura-segmented__option", on && "is-selected", o.iconOnly && "is-icon"),
5199
+ onClick: function() {
5200
+ setValue(o.value);
5201
+ },
5202
+ onKeyDown: function(e) {
5203
+ onKeyDown(e, i);
5204
+ }
5205
+ },
5206
+ o.icon ? /* @__PURE__ */ React50.createElement(Icon, { name: o.icon }) : null,
5207
+ o.iconOnly ? null : /* @__PURE__ */ React50.createElement("span", null, o.label)
5208
+ );
5209
+ })
5210
+ );
5211
+ }
5212
+ );
4805
5213
  return __toCommonJS(index_exports);
4806
5214
  })();
@@ -944,6 +944,107 @@ button.aura-stat { font: inherit; width: 100%; cursor: pointer; }
944
944
  .aura-popover__head + .aura-popover__body { padding-top: var(--aura-space-2); }
945
945
  @media (prefers-reduced-motion: reduce) { .aura-popover { animation: none; } }
946
946
 
947
+ /* ---------- Combobox, multiple: picks as chips in the field ---------- */
948
+ .aura-combo.is-multi { flex-wrap: wrap; align-items: center; gap: var(--aura-space-1); padding: 5px calc(var(--aura-space-2) + 2 * var(--aura-control-sm)) 5px calc(var(--aura-space-3) + var(--aura-icon-sm) + var(--aura-space-2)); }
949
+ .aura-combo.is-multi .aura-input__icon { top: calc(var(--aura-input-height) / 2 - var(--aura-icon-sm) / 2 - 1px); }
950
+ .aura-combo.is-multi .aura-input__control { flex: 1 0 4ch; height: 32px; padding: 0 var(--aura-space-1); }
951
+ /* Wrapped chips grow the field: keep the icon and buttons on the first line. */
952
+ .aura-combo.is-multi .aura-combo__clear, .aura-combo.is-multi .aura-combo__toggle { top: calc((var(--aura-input-height) - 2px - var(--aura-control-sm)) / 2); }
953
+ .aura-combo__chips { display: contents; }
954
+ .aura-combo__chip {
955
+ display: inline-flex; align-items: center; gap: 2px; max-width: 100%; height: 28px; box-sizing: border-box;
956
+ padding: 0 2px 0 var(--aura-space-2); border-radius: var(--aura-radius-full);
957
+ background: var(--aura-bg-selected); color: var(--aura-fg-primary); font-size: 13px; font-weight: 500;
958
+ }
959
+ .aura-combo__chip-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 24ch; }
960
+ .aura-combo__chip-remove {
961
+ display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0;
962
+ border: 0; border-radius: var(--aura-radius-full); background: transparent; color: var(--aura-fg-secondary); cursor: pointer;
963
+ }
964
+ .aura-combo__chip-remove:hover { background: var(--aura-bg-surface-hover); color: var(--aura-fg-primary); }
965
+ .aura-combo__chip-remove .aura-icon { width: 14px; height: 14px; }
966
+
967
+ /* ---------- NumberField ---------- */
968
+ .aura-number .aura-input__control { font-variant-numeric: tabular-nums; }
969
+ .aura-number__affix { padding-left: var(--aura-space-3); color: var(--aura-fg-secondary); font-size: 14px; white-space: nowrap; }
970
+ .aura-number__affix + .aura-input__control { padding-left: var(--aura-space-2); }
971
+ .aura-input__control + .aura-number__affix { padding: 0 var(--aura-space-2) 0 0; }
972
+ .aura-number__steps { display: flex; align-self: stretch; border-left: 1px solid var(--aura-border-default); }
973
+ .aura-number__step {
974
+ display: inline-flex; align-items: center; justify-content: center; width: 36px; padding: 0;
975
+ border: 0; background: transparent; color: var(--aura-fg-secondary); cursor: pointer;
976
+ transition: background-color var(--aura-duration-fast) var(--aura-ease), color var(--aura-duration-fast) var(--aura-ease);
977
+ }
978
+ .aura-number__step + .aura-number__step { border-left: 1px solid var(--aura-border-default); }
979
+ .aura-number__step:last-child { border-radius: 0 calc(var(--aura-radius-md) - 1px) calc(var(--aura-radius-md) - 1px) 0; }
980
+ .aura-number__step:hover:not(:disabled) { background: var(--aura-bg-surface-hover); color: var(--aura-fg-primary); }
981
+ .aura-number__step:disabled { opacity: var(--aura-disabled-opacity); cursor: default; }
982
+
983
+ /* ---------- Stepper ---------- */
984
+ .aura-stepper { font-family: var(--font-sans); }
985
+ .aura-stepper__list { display: flex; list-style: none; margin: 0; padding: 0; }
986
+ .aura-stepper--vertical .aura-stepper__list { flex-direction: column; }
987
+ .aura-stepper__item { position: relative; flex: 1 1 0; min-width: 0; }
988
+ .aura-stepper__step {
989
+ display: flex; align-items: flex-start; gap: var(--aura-space-3); width: 100%; box-sizing: border-box; padding: 0 var(--aura-space-3) 0 0;
990
+ border: 0; background: none; color: inherit; font: inherit; text-align: left; border-radius: var(--aura-radius-md);
991
+ }
992
+ button.aura-stepper__step { cursor: pointer; }
993
+ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underline; }
994
+ .aura-stepper__marker {
995
+ position: relative; z-index: 1; flex: none; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; box-sizing: border-box;
996
+ border-radius: var(--aura-radius-full); border: 1px solid var(--aura-border-control); background: var(--aura-bg-surface);
997
+ color: var(--aura-fg-secondary); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums;
998
+ }
999
+ .aura-stepper__marker .aura-icon { width: 16px; height: 16px; }
1000
+ .aura-stepper__item.is-done .aura-stepper__marker { background: var(--aura-button-primary-bg); border-color: var(--aura-button-primary-bg); color: var(--aura-button-primary-fg); }
1001
+ .aura-stepper__item.is-current .aura-stepper__marker { border: 2px solid var(--aura-fg-accent); color: var(--aura-fg-accent); }
1002
+ .aura-stepper__text { display: flex; flex-direction: column; min-width: 0; padding-top: 4px; }
1003
+ .aura-stepper__label { font-size: 13px; font-weight: 500; line-height: 1.4; color: var(--aura-fg-secondary); }
1004
+ .aura-stepper__item.is-current .aura-stepper__label, .aura-stepper__item.is-done .aura-stepper__label { color: var(--aura-fg-primary); }
1005
+ .aura-stepper__item.is-current .aura-stepper__label { font-weight: 600; }
1006
+ .aura-stepper__desc { font-size: 12px; line-height: 1.5; color: var(--aura-fg-secondary); }
1007
+ /* Connector: a line from each marker to the next (labels sit under the markers), or down the left when vertical. */
1008
+ .aura-stepper--horizontal .aura-stepper__item:not(:last-child)::after {
1009
+ content: ""; position: absolute; top: 14px; left: 36px; right: var(--aura-space-2); height: 1px; background: var(--aura-border-control); pointer-events: none;
1010
+ }
1011
+ .aura-stepper--horizontal .aura-stepper__step { flex-direction: column; gap: var(--aura-space-2); }
1012
+ .aura-stepper--horizontal .aura-stepper__text { padding-top: 0; }
1013
+ .aura-stepper--horizontal .aura-stepper__item.is-done::after { background: var(--aura-button-primary-bg); }
1014
+ .aura-stepper--vertical .aura-stepper__item { flex: none; padding-bottom: var(--aura-space-5); }
1015
+ .aura-stepper--vertical .aura-stepper__item:not(:last-child)::after {
1016
+ content: ""; position: absolute; left: 14px; top: 32px; bottom: 4px; width: 1px; background: var(--aura-border-control);
1017
+ }
1018
+ .aura-stepper--vertical .aura-stepper__item.is-done::after { background: var(--aura-button-primary-bg); }
1019
+ .aura-stepper__compact { display: none; margin: var(--aura-space-2) 0 0; font-size: 13px; }
1020
+ .aura-stepper__count { color: var(--aura-fg-secondary); margin-right: var(--aura-space-2); }
1021
+ .aura-stepper__compact-label { font-weight: 600; }
1022
+
1023
+ /* ---------- SegmentedControl ---------- */
1024
+ .aura-segmented {
1025
+ display: inline-flex; gap: 2px; padding: 2px; box-sizing: border-box; max-width: 100%;
1026
+ border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-full); background: var(--aura-bg-surface-hover);
1027
+ font-family: var(--font-sans);
1028
+ }
1029
+ .aura-segmented:not(.is-full) { width: fit-content; justify-self: start; align-self: flex-start; }
1030
+ .aura-segmented.is-full { display: flex; width: 100%; }
1031
+ .aura-segmented__option {
1032
+ flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
1033
+ height: 32px; padding: 0 var(--aura-space-4); box-sizing: border-box;
1034
+ border: 0; border-radius: var(--aura-radius-full); background: transparent; color: var(--aura-fg-secondary);
1035
+ font: inherit; font-size: 13px; font-weight: 500; white-space: nowrap; cursor: pointer;
1036
+ transition: background-color var(--aura-duration-fast) var(--aura-ease), color var(--aura-duration-fast) var(--aura-ease), box-shadow var(--aura-duration-fast) var(--aura-ease);
1037
+ }
1038
+ .aura-segmented.is-full .aura-segmented__option { flex: 1 1 0; min-width: 0; }
1039
+ .aura-segmented__option.is-icon { padding: 0; width: 36px; }
1040
+ .aura-segmented__option:hover:not(:disabled):not(.is-selected) { color: var(--aura-fg-primary); }
1041
+ .aura-segmented__option.is-selected { background: var(--aura-bg-surface); color: var(--aura-fg-primary); box-shadow: var(--aura-shadow-enterprise); }
1042
+ .aura-segmented__option:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 1px; }
1043
+ .aura-segmented__option:disabled { opacity: var(--aura-disabled-opacity); cursor: default; }
1044
+ .aura-segmented--sm .aura-segmented__option { height: 24px; padding: 0 var(--aura-space-3); font-size: 12px; }
1045
+ .aura-segmented--sm .aura-segmented__option.is-icon { width: 28px; padding: 0; }
1046
+ .aura-segmented.is-disabled { opacity: var(--aura-disabled-opacity); }
1047
+
947
1048
  /* A field inside a row Stack takes the remaining width (a search box beside its button). */
948
1049
  .aura-stack > .aura-field { flex: 1 1 auto; min-width: 0; }
949
1050
 
@@ -951,10 +1052,16 @@ button.aura-stat { font: inherit; width: 100%; cursor: pointer; }
951
1052
  @media (pointer: coarse) {
952
1053
  .aura-cal { --aura-cal-cell: 40px; }
953
1054
  .aura-combo__option { min-height: 44px; }
1055
+ .aura-segmented__option, .aura-segmented--sm .aura-segmented__option { height: 40px; }
1056
+ .aura-number__step { width: 44px; }
954
1057
  }
955
1058
 
956
1059
  /* ---------- Small screens (< 640px) ---------- */
957
1060
  @media (max-width: 639.98px) {
1061
+ /* Horizontal stepper on phones: markers only (names kept for screen readers), the current step named underneath. */
1062
+ .aura-stepper--horizontal .aura-stepper__text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; padding: 0; }
1063
+ .aura-stepper--horizontal .aura-stepper__item:not(:last-child)::after { right: 8px; }
1064
+ .aura-stepper--horizontal .aura-stepper__compact { display: block; }
958
1065
  .aura-dialog-layer:not(.aura-drawer-layer) { align-items: flex-end; padding: 0; }
959
1066
  .aura-dialog { max-width: none !important; max-height: 92vh; border-radius: var(--aura-radius-2xl) var(--aura-radius-2xl) 0 0; border-bottom: 0;
960
1067
  padding-bottom: calc(var(--aura-space-6) + env(safe-area-inset-bottom)); animation-name: aura-sheet-in; }
@@ -437,6 +437,18 @@ export interface ComboboxOption {
437
437
  /** Leading icon in the list. */
438
438
  icon?: IconName;
439
439
  }
440
+ /** Combobox with `multiple`: pick any number; the picks show as removable chips in the field. */
441
+ export interface ComboboxMultipleProps extends Omit<ComboboxProps, "value" | "defaultValue" | "onChange" | "clearable"> {
442
+ multiple: true;
443
+ /** Selected option values, in the order they were picked (controlled). */
444
+ value?: string[];
445
+ defaultValue?: string[];
446
+ onChange?: (value: string[]) => void;
447
+ /** Clear-all button while anything is selected. Default true. */
448
+ clearable?: boolean;
449
+ /** Most picks allowed; further options are disabled. */
450
+ max?: number;
451
+ }
440
452
  export interface ComboboxProps extends FieldProps {
441
453
  options: Array<ComboboxOption | string>;
442
454
  /** Selected option value (controlled). */
@@ -463,6 +475,77 @@ export interface ComboboxProps extends FieldProps {
463
475
  filter?: (option: ComboboxOption, query: string) => boolean;
464
476
  className?: string;
465
477
  }
478
+ /** Number input: thousands separators, +/− buttons, arrow keys, min/max/step, prefix/suffix (฿, %). */
479
+ export interface NumberFieldProps extends FieldProps {
480
+ /** The number (controlled). `null` = empty. */
481
+ value?: number | null;
482
+ defaultValue?: number | null;
483
+ /** Called with the parsed number (or null when emptied) as the person types, and with the clamped value on blur. */
484
+ onChange?: (value: number | null) => void;
485
+ min?: number;
486
+ max?: number;
487
+ /** Arrow keys and buttons move by this. Default 1. PageUp/PageDown move 10×. */
488
+ step?: number;
489
+ /** Decimal places shown and kept. Default: 0 when step is whole, else step's decimals. */
490
+ decimals?: number;
491
+ /** Text before the number, e.g. `฿`. */
492
+ prefix?: React$1.ReactNode;
493
+ /** Text after the number, e.g. `%` or `ชิ้น`. */
494
+ suffix?: React$1.ReactNode;
495
+ /** +/− buttons beside the number. Default true. */
496
+ stepper?: boolean;
497
+ id?: string;
498
+ name?: string;
499
+ placeholder?: string;
500
+ disabled?: boolean;
501
+ readOnly?: boolean;
502
+ className?: string;
503
+ onBlur?: React$1.FocusEventHandler<HTMLInputElement>;
504
+ }
505
+ /** One step of a Stepper. */
506
+ export interface StepItem {
507
+ id: string;
508
+ label: React$1.ReactNode;
509
+ /** Short line under the label, e.g. what the step asks for. */
510
+ description?: React$1.ReactNode;
511
+ }
512
+ /** Progress through a multi-step flow (wizard, checkout, booking). */
513
+ export interface StepperProps {
514
+ steps: StepItem[];
515
+ /** id of the step the person is on. Steps before it are completed. */
516
+ current: string;
517
+ /** Accessible name of the list. Default: none (give one when the page has several). */
518
+ label?: string;
519
+ /** Makes completed steps buttons that go back to them. Upcoming steps never are. */
520
+ onStepClick?: (id: string) => void;
521
+ /** Default `horizontal`. Below `sm` a horizontal stepper shows only the current step ("Step 2 of 4"). */
522
+ orientation?: "horizontal" | "vertical";
523
+ className?: string;
524
+ }
525
+ export interface SegmentedOption {
526
+ value: string;
527
+ label: string;
528
+ icon?: IconName;
529
+ /** Show only the icon; `label` becomes its accessible name and tooltip. */
530
+ iconOnly?: boolean;
531
+ disabled?: boolean;
532
+ }
533
+ /** A row of 2–5 mutually exclusive choices that apply at once (view, period, unit). A radio group underneath. */
534
+ export interface SegmentedControlProps {
535
+ /** Accessible name of the group, e.g. "View". Required. */
536
+ label: string;
537
+ options: Array<SegmentedOption | string>;
538
+ value?: string;
539
+ defaultValue?: string;
540
+ onChange?: (value: string) => void;
541
+ /** `md` (default, 36px) or `sm` (28px) for toolbars. */
542
+ size?: "sm" | "md";
543
+ /** Stretch across the container, segments equal width. */
544
+ fullWidth?: boolean;
545
+ disabled?: boolean;
546
+ id?: string;
547
+ className?: string;
548
+ }
466
549
  /** ISO date string, `YYYY-MM-DD` (Gregorian — the era is display only). */
467
550
  export type ISODate = string;
468
551
  export interface DateDisplayOptions {
@@ -832,10 +915,16 @@ export declare const Textarea: React$1.ForwardRefExoticComponent<TextareaProps &
832
915
  export declare const Select: React$1.ForwardRefExoticComponent<SelectProps & React$1.RefAttributes<HTMLSelectElement>>;
833
916
  export declare const RadioGroup: React$1.ForwardRefExoticComponent<RadioGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
834
917
  export declare const Switch: React$1.ForwardRefExoticComponent<SwitchProps & React$1.RefAttributes<HTMLButtonElement>>;
918
+ /** One value, or with `multiple` any number (chips). Two call signatures so value/onChange are typed for each. */
919
+ export interface ComboboxComponent {
920
+ (props: ComboboxMultipleProps & React$1.RefAttributes<HTMLInputElement>): React$1.ReactElement | null;
921
+ (props: ComboboxProps & React$1.RefAttributes<HTMLInputElement>): React$1.ReactElement | null;
922
+ displayName?: string;
923
+ }
835
924
  /** The Thai-aware default filter: label, description and keywords contain the query. */
836
925
  declare function defaultFilter(option: ComboboxOption, query: string): boolean;
837
- /** Text field that filters a list as you type (ARIA 1.2 combobox). One value. */
838
- export declare const Combobox: React$1.ForwardRefExoticComponent<ComboboxProps & React$1.RefAttributes<HTMLInputElement>>;
926
+ /** Text field that filters a list as you type (ARIA 1.2 combobox). One value, or any number with `multiple`. */
927
+ export declare const Combobox: ComboboxComponent;
839
928
  /** Options for formatDate: locale/calendar plus a preset or any Intl.DateTimeFormat options. */
840
929
  export type FormatDateOptions = DateDisplayOptions & {
841
930
  format?: "short" | "long" | "numeric" | Intl.DateTimeFormatOptions;
@@ -953,6 +1042,10 @@ export interface AuraStrings {
953
1042
  fileWrongType: string;
954
1043
  tooManyFiles: (n: number | string) => string;
955
1044
  colorScheme: string;
1045
+ increase: string;
1046
+ decrease: string;
1047
+ stepDone: string;
1048
+ stepOf: (i: number, total: number) => string;
956
1049
  schemeLight: string;
957
1050
  schemeDark: string;
958
1051
  schemeSystem: string;
@@ -1031,6 +1124,12 @@ export declare const EmptyState: React$1.ForwardRefExoticComponent<EmptyStatePro
1031
1124
  export declare const Pagination: React$1.ForwardRefExoticComponent<PaginationProps & React$1.RefAttributes<HTMLElement>>;
1032
1125
  export declare const Accordion: React$1.ForwardRefExoticComponent<AccordionProps & React$1.RefAttributes<HTMLDivElement>>;
1033
1126
  export declare const Popover: React$1.ForwardRefExoticComponent<PopoverProps & React$1.RefAttributes<HTMLDivElement>>;
1127
+ /** Number input with thousands separators, +/− buttons and arrow keys (ARIA spinbutton). */
1128
+ export declare const NumberField: React$1.ForwardRefExoticComponent<NumberFieldProps & React$1.RefAttributes<HTMLInputElement>>;
1129
+ /** Progress through a multi-step flow. Completed steps can link back; the current one has aria-current="step". */
1130
+ export declare const Stepper: React$1.ForwardRefExoticComponent<StepperProps & React$1.RefAttributes<HTMLElement>>;
1131
+ /** A row of mutually exclusive choices that apply at once. A radio group: one Tab stop, arrow keys move and select. */
1132
+ export declare const SegmentedControl: React$1.ForwardRefExoticComponent<SegmentedControlProps & React$1.RefAttributes<HTMLDivElement>>;
1034
1133
 
1035
1134
  export {
1036
1135
  defaultFilter as comboboxFilter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-tokens",
3
- "version": "4.8.0",
3
+ "version": "4.9.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
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.8.0",
2
+ "version": "4.9.0",
3
3
  "meta": {
4
4
  "name": "AURA Design System",
5
5
  "tier": "3-tier",