twico-ui 1.28.0 → 1.30.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/CHANGELOG.md +14 -0
- package/dist/index.cjs +159 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.mjs +159 -51
- package/dist/index.mjs.map +1 -1
- package/llms.txt +7 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -5650,6 +5650,10 @@ var COMBO_CSS = `
|
|
|
5650
5650
|
.twc-opt__main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
|
|
5651
5651
|
.twc-opt__label { line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
5652
5652
|
.twc-opt__desc { font-size: var(--text-xs); color: var(--color-text-muted); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
5653
|
+
/* #326: optional leading icon/swatch + trailing (right-aligned) hint on an option. */
|
|
5654
|
+
.twc-opt__icon { flex: none; display: inline-flex; align-items: center; color: var(--color-text-muted); }
|
|
5655
|
+
.twc-opt__icon svg { width: 16px; height: 16px; }
|
|
5656
|
+
.twc-opt__hint { flex: none; margin-inline-start: auto; padding-inline-start: var(--space-2); color: var(--color-text-muted); font-size: var(--text-xs); white-space: nowrap; }
|
|
5653
5657
|
/* #300: wrapOptions \u2014 let long labels/descriptions wrap onto multiple lines instead of truncating.
|
|
5654
5658
|
overflow-wrap: anywhere also breaks a single very long token so it can't overflow the popover edge. */
|
|
5655
5659
|
.twc-opt[data-wrap="true"] { align-items: flex-start; }
|
|
@@ -5717,6 +5721,7 @@ function Combobox({
|
|
|
5717
5721
|
virtualized: virtualizedProp = false,
|
|
5718
5722
|
overscan = 8,
|
|
5719
5723
|
wrapOptions = false,
|
|
5724
|
+
renderOption,
|
|
5720
5725
|
id,
|
|
5721
5726
|
className = "",
|
|
5722
5727
|
onFocus,
|
|
@@ -5724,8 +5729,8 @@ function Combobox({
|
|
|
5724
5729
|
...rest
|
|
5725
5730
|
}) {
|
|
5726
5731
|
const __twcStyles = useScopedStyles("twc-combo-styles", COMBO_CSS);
|
|
5727
|
-
if (virtualizedProp && wrapOptions) warnOnce("combobox-
|
|
5728
|
-
const virtualized = virtualizedProp && !wrapOptions;
|
|
5732
|
+
if (virtualizedProp && (wrapOptions || renderOption)) warnOnce("combobox-var-height-virtualized", "twico-ui Combobox: `wrapOptions`/`renderOption` disable `virtualized` \u2014 those rows aren't a fixed height.");
|
|
5733
|
+
const virtualized = virtualizedProp && !wrapOptions && !renderOption;
|
|
5729
5734
|
const groups = React51__default.useMemo(() => normalizeGroups(options), [options]);
|
|
5730
5735
|
const flat = React51__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
|
|
5731
5736
|
const autoId = React51__default.useId();
|
|
@@ -5896,7 +5901,7 @@ function Combobox({
|
|
|
5896
5901
|
const activeId = open && visible[active] ? optionId(active) : void 0;
|
|
5897
5902
|
const descId = `${fieldId}-desc`;
|
|
5898
5903
|
const describedBy = error || hint ? descId : void 0;
|
|
5899
|
-
const
|
|
5904
|
+
const renderRow = (o, idx) => {
|
|
5900
5905
|
const isSel = o.value === current;
|
|
5901
5906
|
return /* @__PURE__ */ jsxs(
|
|
5902
5907
|
"button",
|
|
@@ -5919,9 +5924,13 @@ function Combobox({
|
|
|
5919
5924
|
onMouseDown: (e) => e.preventDefault(),
|
|
5920
5925
|
onClick: () => commit(o.value),
|
|
5921
5926
|
children: [
|
|
5922
|
-
/* @__PURE__ */
|
|
5923
|
-
/* @__PURE__ */ jsx("span", { className: "twc-
|
|
5924
|
-
|
|
5927
|
+
renderOption ? /* @__PURE__ */ jsx("span", { className: "twc-opt__main", children: renderOption(o, { selected: isSel, active: idx === active }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5928
|
+
o.icon != null ? /* @__PURE__ */ jsx("span", { className: "twc-opt__icon", "aria-hidden": "true", children: o.icon }) : null,
|
|
5929
|
+
/* @__PURE__ */ jsxs("span", { className: "twc-opt__main", children: [
|
|
5930
|
+
/* @__PURE__ */ jsx("span", { className: "twc-opt__label", children: o.label }),
|
|
5931
|
+
o.description ? /* @__PURE__ */ jsx("span", { className: "twc-opt__desc", children: o.description }) : null
|
|
5932
|
+
] }),
|
|
5933
|
+
o.hint != null ? /* @__PURE__ */ jsx("span", { className: "twc-opt__hint", children: o.hint }) : null
|
|
5925
5934
|
] }),
|
|
5926
5935
|
isSel ? /* @__PURE__ */ jsx("span", { className: "twc-opt__check", "aria-hidden": "true", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) }) }) : null
|
|
5927
5936
|
]
|
|
@@ -5943,14 +5952,14 @@ function Combobox({
|
|
|
5943
5952
|
"Loading\u2026"
|
|
5944
5953
|
] }) : visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: emptyText }) : virtualized ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5945
5954
|
vTop > 0 ? /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { height: vTop } }) : null,
|
|
5946
|
-
vShown.map((r2) => r2.kind === "group" ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: r2.label }, `g${r2.gi}`) :
|
|
5955
|
+
vShown.map((r2) => r2.kind === "group" ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: r2.label }, `g${r2.gi}`) : renderRow(r2.o, r2.idx)),
|
|
5947
5956
|
vBottom > 0 ? /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { height: vBottom } }) : null
|
|
5948
5957
|
] }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React51__default.Fragment, { children: [
|
|
5949
5958
|
g.group ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: g.group }) : null,
|
|
5950
5959
|
g.options.map((o) => {
|
|
5951
5960
|
counter += 1;
|
|
5952
5961
|
const idx = counter;
|
|
5953
|
-
return
|
|
5962
|
+
return renderRow(o, idx);
|
|
5954
5963
|
})
|
|
5955
5964
|
] }, gi)) });
|
|
5956
5965
|
const RD = { createPortal: typeof createPortal === "function" ? createPortal : typeof window !== "undefined" && window.ReactDOM && window.ReactDOM.createPortal };
|
|
@@ -6487,6 +6496,10 @@ var SELECT_CSS = `
|
|
|
6487
6496
|
.twc-opt__main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
|
|
6488
6497
|
.twc-opt__label { line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6489
6498
|
.twc-opt__desc { font-size: var(--text-xs); color: var(--color-text-muted); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6499
|
+
/* #326: optional leading icon/swatch + trailing (right-aligned) hint on an option. */
|
|
6500
|
+
.twc-opt__icon { flex: none; display: inline-flex; align-items: center; color: var(--color-text-muted); }
|
|
6501
|
+
.twc-opt__icon svg { width: 16px; height: 16px; }
|
|
6502
|
+
.twc-opt__hint { flex: none; margin-inline-start: auto; padding-inline-start: var(--space-2); color: var(--color-text-muted); font-size: var(--text-xs); white-space: nowrap; }
|
|
6490
6503
|
.twc-opt__check { flex: none; color: var(--color-primary); display: inline-flex; }
|
|
6491
6504
|
.twc-opt__check svg { width: 16px; height: 16px; }
|
|
6492
6505
|
.twc-pop__empty { padding: 14px 12px; text-align: center; font-size: var(--text-sm); color: var(--color-text-subtle); }
|
|
@@ -6547,8 +6560,9 @@ function Select({
|
|
|
6547
6560
|
loading = false,
|
|
6548
6561
|
emptyText = "No results found",
|
|
6549
6562
|
name,
|
|
6550
|
-
virtualized = false,
|
|
6563
|
+
virtualized: virtualizedProp = false,
|
|
6551
6564
|
overscan = 8,
|
|
6565
|
+
renderOption,
|
|
6552
6566
|
id,
|
|
6553
6567
|
className = "",
|
|
6554
6568
|
onClick,
|
|
@@ -6556,6 +6570,8 @@ function Select({
|
|
|
6556
6570
|
...rest
|
|
6557
6571
|
}) {
|
|
6558
6572
|
const __twcStyles = useScopedStyles("twc-select-styles", SELECT_CSS);
|
|
6573
|
+
if (virtualizedProp && renderOption) warnOnce("select-renderoption-virtualized", "twico-ui Select: `renderOption` disables `virtualized` \u2014 custom rows aren't a fixed height.");
|
|
6574
|
+
const virtualized = virtualizedProp && !renderOption;
|
|
6559
6575
|
const bufferRef = React51__default.useRef("");
|
|
6560
6576
|
const bufferTimerRef = React51__default.useRef(null);
|
|
6561
6577
|
const groups = React51__default.useMemo(() => normalizeGroups2(options), [options]);
|
|
@@ -6761,7 +6777,7 @@ function Select({
|
|
|
6761
6777
|
const activeId = open && visible[active] ? optionId(active) : void 0;
|
|
6762
6778
|
const descId = `${fieldId}-desc`;
|
|
6763
6779
|
const describedBy = error || hint ? descId : void 0;
|
|
6764
|
-
const
|
|
6780
|
+
const renderRow = (o, idx) => {
|
|
6765
6781
|
const isSel = o.value === current;
|
|
6766
6782
|
return /* @__PURE__ */ jsxs(
|
|
6767
6783
|
"button",
|
|
@@ -6783,9 +6799,13 @@ function Select({
|
|
|
6783
6799
|
},
|
|
6784
6800
|
onClick: () => commit(o.value),
|
|
6785
6801
|
children: [
|
|
6786
|
-
/* @__PURE__ */
|
|
6787
|
-
/* @__PURE__ */ jsx("span", { className: "twc-
|
|
6788
|
-
|
|
6802
|
+
renderOption ? /* @__PURE__ */ jsx("span", { className: "twc-opt__main", children: renderOption(o, { selected: isSel, active: idx === active }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6803
|
+
o.icon != null ? /* @__PURE__ */ jsx("span", { className: "twc-opt__icon", "aria-hidden": "true", children: o.icon }) : null,
|
|
6804
|
+
/* @__PURE__ */ jsxs("span", { className: "twc-opt__main", children: [
|
|
6805
|
+
/* @__PURE__ */ jsx("span", { className: "twc-opt__label", children: o.label }),
|
|
6806
|
+
o.description ? /* @__PURE__ */ jsx("span", { className: "twc-opt__desc", children: o.description }) : null
|
|
6807
|
+
] }),
|
|
6808
|
+
o.hint != null ? /* @__PURE__ */ jsx("span", { className: "twc-opt__hint", children: o.hint }) : null
|
|
6789
6809
|
] }),
|
|
6790
6810
|
isSel ? /* @__PURE__ */ jsx("span", { className: "twc-opt__check", "aria-hidden": "true", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) }) }) : null
|
|
6791
6811
|
]
|
|
@@ -6833,14 +6853,14 @@ function Select({
|
|
|
6833
6853
|
"Loading\u2026"
|
|
6834
6854
|
] }) : visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: emptyText }) : virtualized ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6835
6855
|
vTop > 0 ? /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { height: vTop } }) : null,
|
|
6836
|
-
vShown.map((r2) => r2.kind === "group" ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: r2.label }, `g${r2.gi}`) :
|
|
6856
|
+
vShown.map((r2) => r2.kind === "group" ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: r2.label }, `g${r2.gi}`) : renderRow(r2.o, r2.idx)),
|
|
6837
6857
|
vBottom > 0 ? /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { height: vBottom } }) : null
|
|
6838
6858
|
] }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React51__default.Fragment, { children: [
|
|
6839
6859
|
g.group ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: g.group }) : null,
|
|
6840
6860
|
g.options.map((o) => {
|
|
6841
6861
|
counter += 1;
|
|
6842
6862
|
const idx = counter;
|
|
6843
|
-
return
|
|
6863
|
+
return renderRow(o, idx);
|
|
6844
6864
|
})
|
|
6845
6865
|
] }, gi)) }),
|
|
6846
6866
|
/* @__PURE__ */ jsx("div", { className: "twc-sel__sr", role: "status", "aria-live": "polite", children: loading ? "Loading\u2026" : visible.length === 0 ? emptyText : `${visible.length} result${visible.length === 1 ? "" : "s"}` })
|
|
@@ -7144,6 +7164,11 @@ var INPUT_EXTRA_CSS = `
|
|
|
7144
7164
|
.twc-input__reveal:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
7145
7165
|
.twc-input__reveal:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
7146
7166
|
.twc-input__reveal svg { width: 17px; height: 17px; }
|
|
7167
|
+
/* #328: trailing clear (X) button \u2014 mirrors the reveal toggle; sits alongside rightIcon / the password eye. */
|
|
7168
|
+
.twc-input__clear { display: inline-grid; place-items: center; width: 24px; height: 24px; padding: 0; border: none; background: transparent; color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-sm); flex: none; transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
|
|
7169
|
+
.twc-input__clear:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
7170
|
+
.twc-input__clear:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
7171
|
+
.twc-input__clear svg { width: 15px; height: 15px; }
|
|
7147
7172
|
.twc-input__addon { align-self: stretch; display: inline-flex; align-items: center; padding-inline: var(--space-3);
|
|
7148
7173
|
background: var(--color-surface-sunken); color: var(--color-text-muted); font-size: var(--text-sm);
|
|
7149
7174
|
font-weight: var(--font-semibold); white-space: nowrap; flex: none; }
|
|
@@ -7165,6 +7190,7 @@ function Input({
|
|
|
7165
7190
|
leftAddon,
|
|
7166
7191
|
rightAddon,
|
|
7167
7192
|
showCount = false,
|
|
7193
|
+
clearable = false,
|
|
7168
7194
|
type = "text",
|
|
7169
7195
|
disabled = false,
|
|
7170
7196
|
id,
|
|
@@ -7186,8 +7212,25 @@ function Input({
|
|
|
7186
7212
|
const near = showCounter && count >= Math.floor(max * 0.9);
|
|
7187
7213
|
const handleChange = (e) => {
|
|
7188
7214
|
rest.onChange?.(e);
|
|
7189
|
-
if (showCount && !countControlled) setLen(e.target.value.length);
|
|
7215
|
+
if ((showCount || clearable) && !countControlled) setLen(e.target.value.length);
|
|
7216
|
+
};
|
|
7217
|
+
const inputRef = React51__default.useRef(null);
|
|
7218
|
+
const userRef = rest.ref;
|
|
7219
|
+
const setRef = React51__default.useCallback((node) => {
|
|
7220
|
+
inputRef.current = node;
|
|
7221
|
+
if (typeof userRef === "function") userRef(node);
|
|
7222
|
+
else if (userRef && typeof userRef === "object") userRef.current = node;
|
|
7223
|
+
}, [userRef]);
|
|
7224
|
+
const clearField = () => {
|
|
7225
|
+
const el = inputRef.current;
|
|
7226
|
+
if (!el) return;
|
|
7227
|
+
const setter = typeof HTMLInputElement !== "undefined" && Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set;
|
|
7228
|
+
if (setter) setter.call(el, "");
|
|
7229
|
+
else el.value = "";
|
|
7230
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
7231
|
+
el.focus();
|
|
7190
7232
|
};
|
|
7233
|
+
const showClear = clearable && count > 0 && !disabled && !rest.readOnly;
|
|
7191
7234
|
const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
|
|
7192
7235
|
const describedBy = [error || hint ? descId : null, showCounter ? countId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
7193
7236
|
const isPassword = type === "password";
|
|
@@ -7234,11 +7277,16 @@ function Input({
|
|
|
7234
7277
|
required: required || void 0,
|
|
7235
7278
|
"aria-required": required || void 0,
|
|
7236
7279
|
...rest,
|
|
7280
|
+
ref: setRef,
|
|
7237
7281
|
onChange: handleChange,
|
|
7238
7282
|
"aria-invalid": ariaInvalid,
|
|
7239
7283
|
"aria-describedby": describedBy
|
|
7240
7284
|
}
|
|
7241
7285
|
),
|
|
7286
|
+
showClear ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-input__clear", "aria-label": "Clear", tabIndex: 0, onMouseDown: (e) => e.preventDefault(), onClick: clearField, children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
7287
|
+
/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
|
|
7288
|
+
/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
|
|
7289
|
+
] }) }) : null,
|
|
7242
7290
|
suffix,
|
|
7243
7291
|
rightAddon != null ? /* @__PURE__ */ jsx("span", { className: "twc-input__addon twc-input__addon--end", children: rightAddon }) : null
|
|
7244
7292
|
] }),
|
|
@@ -7326,6 +7374,10 @@ var MULTI_CSS = `
|
|
|
7326
7374
|
.twc-opt__main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
|
|
7327
7375
|
.twc-opt__label { line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
7328
7376
|
.twc-opt__desc { font-size: var(--text-xs); color: var(--color-text-muted); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
7377
|
+
/* #326: optional leading icon/swatch + trailing (right-aligned) hint on an option. */
|
|
7378
|
+
.twc-opt__icon { flex: none; display: inline-flex; align-items: center; color: var(--color-text-muted); }
|
|
7379
|
+
.twc-opt__icon svg { width: 16px; height: 16px; }
|
|
7380
|
+
.twc-opt__hint { flex: none; margin-inline-start: auto; padding-inline-start: var(--space-2); color: var(--color-text-muted); font-size: var(--text-xs); white-space: nowrap; }
|
|
7329
7381
|
.twc-pop__empty { padding: 14px 12px; text-align: center; font-size: var(--text-sm); color: var(--color-text-subtle); }
|
|
7330
7382
|
.twc-opt[data-disabled="true"] { opacity: 0.45; cursor: not-allowed; pointer-events: none; }
|
|
7331
7383
|
.twc-pop__loading { display: flex; align-items: center; justify-content: center; gap: var(--space-2); padding: 14px 12px; font-size: var(--text-sm); color: var(--color-text-muted); }
|
|
@@ -7387,8 +7439,9 @@ function MultiSelect({
|
|
|
7387
7439
|
maxTagCount,
|
|
7388
7440
|
filter,
|
|
7389
7441
|
onInputChange,
|
|
7390
|
-
virtualized = false,
|
|
7442
|
+
virtualized: virtualizedProp = false,
|
|
7391
7443
|
overscan = 8,
|
|
7444
|
+
renderOption,
|
|
7392
7445
|
id,
|
|
7393
7446
|
className = "",
|
|
7394
7447
|
onFocus,
|
|
@@ -7396,6 +7449,8 @@ function MultiSelect({
|
|
|
7396
7449
|
...rest
|
|
7397
7450
|
}) {
|
|
7398
7451
|
const __twcStyles = useScopedStyles("twc-ms-styles", MULTI_CSS);
|
|
7452
|
+
if (virtualizedProp && renderOption) warnOnce("multiselect-renderoption-virtualized", "twico-ui MultiSelect: `renderOption` disables `virtualized` \u2014 custom rows aren't a fixed height.");
|
|
7453
|
+
const virtualized = virtualizedProp && !renderOption;
|
|
7399
7454
|
const groups = React51__default.useMemo(() => normalizeGroups3(options), [options]);
|
|
7400
7455
|
const flat = React51__default.useMemo(() => groups.flatMap((g) => g.options), [groups]);
|
|
7401
7456
|
const autoId = React51__default.useId();
|
|
@@ -7555,7 +7610,7 @@ function MultiSelect({
|
|
|
7555
7610
|
const activeId = open && visible[active] ? optionId(active) : void 0;
|
|
7556
7611
|
const descId = `${fieldId}-desc`;
|
|
7557
7612
|
const describedBy = error || hint ? descId : void 0;
|
|
7558
|
-
const
|
|
7613
|
+
const renderRow = (o, idx) => {
|
|
7559
7614
|
const isSel = selected.includes(o.value);
|
|
7560
7615
|
const optDisabled = isOptDisabled(o);
|
|
7561
7616
|
return /* @__PURE__ */ jsxs(
|
|
@@ -7579,9 +7634,13 @@ function MultiSelect({
|
|
|
7579
7634
|
onClick: () => toggle(o.value),
|
|
7580
7635
|
children: [
|
|
7581
7636
|
/* @__PURE__ */ jsx("span", { className: "twc-opt__box", "aria-hidden": "true", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) }) }),
|
|
7582
|
-
/* @__PURE__ */
|
|
7583
|
-
/* @__PURE__ */ jsx("span", { className: "twc-
|
|
7584
|
-
|
|
7637
|
+
renderOption ? /* @__PURE__ */ jsx("span", { className: "twc-opt__main", children: renderOption(o, { selected: isSel, active: idx === active }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7638
|
+
o.icon != null ? /* @__PURE__ */ jsx("span", { className: "twc-opt__icon", "aria-hidden": "true", children: o.icon }) : null,
|
|
7639
|
+
/* @__PURE__ */ jsxs("span", { className: "twc-opt__main", children: [
|
|
7640
|
+
/* @__PURE__ */ jsx("span", { className: "twc-opt__label", children: o.label }),
|
|
7641
|
+
o.description ? /* @__PURE__ */ jsx("span", { className: "twc-opt__desc", children: o.description }) : null
|
|
7642
|
+
] }),
|
|
7643
|
+
o.hint != null ? /* @__PURE__ */ jsx("span", { className: "twc-opt__hint", children: o.hint }) : null
|
|
7585
7644
|
] })
|
|
7586
7645
|
]
|
|
7587
7646
|
},
|
|
@@ -7611,14 +7670,14 @@ function MultiSelect({
|
|
|
7611
7670
|
"Loading\u2026"
|
|
7612
7671
|
] }) : visible.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-pop__empty", children: emptyText }) : virtualized ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7613
7672
|
vTop > 0 ? /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { height: vTop } }) : null,
|
|
7614
|
-
vShown.map((r2) => r2.kind === "group" ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: r2.label }, `g${r2.gi}`) :
|
|
7673
|
+
vShown.map((r2) => r2.kind === "group" ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: r2.label }, `g${r2.gi}`) : renderRow(r2.o, r2.idx)),
|
|
7615
7674
|
vBottom > 0 ? /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { height: vBottom } }) : null
|
|
7616
7675
|
] }) : fGroups.map((g, gi) => /* @__PURE__ */ jsxs(React51__default.Fragment, { children: [
|
|
7617
7676
|
g.group ? /* @__PURE__ */ jsx("div", { className: "twc-pop__group", children: g.group }) : null,
|
|
7618
7677
|
g.options.map((o) => {
|
|
7619
7678
|
counter += 1;
|
|
7620
7679
|
const idx = counter;
|
|
7621
|
-
return
|
|
7680
|
+
return renderRow(o, idx);
|
|
7622
7681
|
})
|
|
7623
7682
|
] }, gi))
|
|
7624
7683
|
}
|
|
@@ -8202,6 +8261,11 @@ var DT_CSS = `
|
|
|
8202
8261
|
font-size: var(--text-sm); color: var(--color-text); width: 150px; }
|
|
8203
8262
|
.twc-dt__search input:focus, .twc-dt__search input:focus-visible { outline: none; box-shadow: none; }
|
|
8204
8263
|
.twc-dt__search input::placeholder { color: var(--color-text-subtle); }
|
|
8264
|
+
/* #327: trailing clear (X) for the built-in search inputs (quick-search + column-menu search). */
|
|
8265
|
+
.twc-dt__search-clear { border: none; background: transparent; color: var(--color-text-subtle); cursor: pointer; display: inline-grid; place-items: center; width: 20px; height: 20px; padding: 0; border-radius: var(--radius-sm); flex: none; }
|
|
8266
|
+
.twc-dt__search-clear:hover { color: var(--color-text); background: var(--color-surface-sunken); }
|
|
8267
|
+
.twc-dt__search-clear:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
8268
|
+
.twc-dt__search-clear svg { width: 14px; height: 14px; }
|
|
8205
8269
|
.twc-dt__tlabel { display: inline; }
|
|
8206
8270
|
/* Narrow grid: collapse the toolbar to icon-only buttons (labels survive as
|
|
8207
8271
|
hover tooltips via data-tip) and let the search flex so nothing wraps. */
|
|
@@ -9162,6 +9226,8 @@ function Datatable({
|
|
|
9162
9226
|
onCellClick,
|
|
9163
9227
|
onActiveCellChange,
|
|
9164
9228
|
onCellSelectionChange,
|
|
9229
|
+
activeRowId,
|
|
9230
|
+
scrollActiveRowIntoView = true,
|
|
9165
9231
|
enableClipboard = false,
|
|
9166
9232
|
onCellsCopy,
|
|
9167
9233
|
onCellsPaste,
|
|
@@ -9294,6 +9360,8 @@ function Datatable({
|
|
|
9294
9360
|
};
|
|
9295
9361
|
const [selected, setSelected] = React51__default.useState(() => /* @__PURE__ */ new Set());
|
|
9296
9362
|
const [activeRow, setActiveRow] = React51__default.useState(null);
|
|
9363
|
+
const activeRowControlled = activeRowId !== void 0;
|
|
9364
|
+
const activeRowVal = activeRowControlled ? activeRowId : activeRow;
|
|
9297
9365
|
const [activeCell, setActiveCell] = React51__default.useState(null);
|
|
9298
9366
|
const [anchorCell, setAnchorCell] = React51__default.useState(null);
|
|
9299
9367
|
const gridId = React51__default.useId();
|
|
@@ -9566,6 +9634,8 @@ function Datatable({
|
|
|
9566
9634
|
const colMenuRef = React51__default.useRef(null);
|
|
9567
9635
|
const rowMenuRef = React51__default.useRef(null);
|
|
9568
9636
|
const exportMenuRef = React51__default.useRef(null);
|
|
9637
|
+
const quickSearchRef = React51__default.useRef(null);
|
|
9638
|
+
const colSearchRef = React51__default.useRef(null);
|
|
9569
9639
|
function focusFirstItem(container) {
|
|
9570
9640
|
if (!container) return;
|
|
9571
9641
|
const first = container.querySelector('[role="menuitem"]:not([disabled])');
|
|
@@ -10281,7 +10351,7 @@ function Datatable({
|
|
|
10281
10351
|
if (selectionMode === "none") return;
|
|
10282
10352
|
if (e.target.closest("button, a, input, select, .twc-dt__check, .twc-dt__editor-wrap")) return;
|
|
10283
10353
|
if (selectionMode === "row") {
|
|
10284
|
-
setActiveRow(k);
|
|
10354
|
+
if (!activeRowControlled) setActiveRow(k);
|
|
10285
10355
|
onRowClick?.(row, k);
|
|
10286
10356
|
onActiveCellChange?.(null);
|
|
10287
10357
|
}
|
|
@@ -10360,8 +10430,9 @@ function Datatable({
|
|
|
10360
10430
|
}
|
|
10361
10431
|
if (selectionMode === "row") {
|
|
10362
10432
|
e.preventDefault();
|
|
10363
|
-
|
|
10364
|
-
|
|
10433
|
+
const rk = keyOf(leafRows[r2], r2);
|
|
10434
|
+
if (!activeRowControlled) setActiveRow(rk);
|
|
10435
|
+
onRowClick?.(leafRows[r2], rk);
|
|
10365
10436
|
return;
|
|
10366
10437
|
}
|
|
10367
10438
|
handled = false;
|
|
@@ -10402,6 +10473,11 @@ function Datatable({
|
|
|
10402
10473
|
prevRowSelSigRef.current = sig;
|
|
10403
10474
|
cb(selKeys, selectedRows);
|
|
10404
10475
|
}, [selKeys, selectedRows]);
|
|
10476
|
+
React51__default.useEffect(() => {
|
|
10477
|
+
if (!activeRowControlled || !scrollActiveRowIntoView || activeRowId == null) return;
|
|
10478
|
+
const el = gridRef.current && gridRef.current.querySelector('.twc-dt__row[data-active="true"]');
|
|
10479
|
+
if (el && el.scrollIntoView) el.scrollIntoView({ block: "nearest" });
|
|
10480
|
+
}, [activeRowId, activeRowControlled, scrollActiveRowIntoView]);
|
|
10405
10481
|
function clearSelection() {
|
|
10406
10482
|
setSelected(/* @__PURE__ */ new Set());
|
|
10407
10483
|
}
|
|
@@ -11119,7 +11195,7 @@ function Datatable({
|
|
|
11119
11195
|
function renderLeaf(row, ri, pinSide, midIdx) {
|
|
11120
11196
|
const k = keyOf(row, ri);
|
|
11121
11197
|
const sel = selected.has(k);
|
|
11122
|
-
const rowActive = selectionMode === "row" &&
|
|
11198
|
+
const rowActive = selectionMode === "row" && activeRowVal === k;
|
|
11123
11199
|
const stickyStyle = pinSide === "top" ? { position: "sticky", top: headH, zIndex: 5 } : pinSide === "bottom" ? { position: "sticky", bottom: 0, zIndex: 5 } : void 0;
|
|
11124
11200
|
const h = rowHeights[k];
|
|
11125
11201
|
const rowStyle = { ...stickyStyle || {}, ...h ? { height: h } : {} };
|
|
@@ -11574,7 +11650,11 @@ function Datatable({
|
|
|
11574
11650
|
] }) : null,
|
|
11575
11651
|
searchable ? /* @__PURE__ */ jsxs("div", { className: "twc-dt__search", children: [
|
|
11576
11652
|
/* @__PURE__ */ jsx(Svg, { d: I.search }),
|
|
11577
|
-
/* @__PURE__ */ jsx("input", { placeholder: "Search\u2026", "aria-label": "Search rows", value: quick, onChange: (e) => commitQuick(e.target.value) })
|
|
11653
|
+
/* @__PURE__ */ jsx("input", { ref: quickSearchRef, placeholder: "Search\u2026", "aria-label": "Search rows", value: quick, onChange: (e) => commitQuick(e.target.value) }),
|
|
11654
|
+
quick ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-dt__search-clear", "aria-label": "Clear search", onMouseDown: (e) => e.preventDefault(), onClick: () => {
|
|
11655
|
+
commitQuick("");
|
|
11656
|
+
quickSearchRef.current?.focus();
|
|
11657
|
+
}, children: /* @__PURE__ */ jsx(Svg, { d: I.x }) }) : null
|
|
11578
11658
|
] }) : null
|
|
11579
11659
|
] }),
|
|
11580
11660
|
!pivotActive && activeGroupBy.length ? /* @__PURE__ */ jsxs("div", { className: "twc-dt__groupbar", children: [
|
|
@@ -12167,7 +12247,11 @@ function Datatable({
|
|
|
12167
12247
|
] }),
|
|
12168
12248
|
/* @__PURE__ */ jsxs("div", { className: "twc-dt__col-search", children: [
|
|
12169
12249
|
/* @__PURE__ */ jsx(Svg, { d: I.search }),
|
|
12170
|
-
/* @__PURE__ */ jsx("input", { autoFocus: true, placeholder: "Find column\u2026", "aria-label": "Find column", value: colQuery, onChange: (e) => setColQuery(e.target.value) })
|
|
12250
|
+
/* @__PURE__ */ jsx("input", { ref: colSearchRef, autoFocus: true, placeholder: "Find column\u2026", "aria-label": "Find column", value: colQuery, onChange: (e) => setColQuery(e.target.value) }),
|
|
12251
|
+
colQuery ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-dt__search-clear", "aria-label": "Clear column search", onMouseDown: (e) => e.preventDefault(), onClick: () => {
|
|
12252
|
+
setColQuery("");
|
|
12253
|
+
colSearchRef.current?.focus();
|
|
12254
|
+
}, children: /* @__PURE__ */ jsx(Svg, { d: I.x }) }) : null
|
|
12171
12255
|
] }),
|
|
12172
12256
|
/* @__PURE__ */ jsxs("div", { className: "twc-dt__col-list", children: [
|
|
12173
12257
|
rowNumMatch ? /* @__PURE__ */ jsxs("div", { className: "twc-dt__col-row", onClick: () => setShowRowNum((v) => !v), children: [
|
|
@@ -12537,6 +12621,7 @@ function Datatable({
|
|
|
12537
12621
|
Input,
|
|
12538
12622
|
{
|
|
12539
12623
|
size: "sm",
|
|
12624
|
+
clearable: true,
|
|
12540
12625
|
type: filterTypeOf(col) === "number" ? "number" : "text",
|
|
12541
12626
|
placeholder: "Value",
|
|
12542
12627
|
value: f.value,
|
|
@@ -17625,6 +17710,12 @@ var TEXTAREA_CSS = `
|
|
|
17625
17710
|
.twc-textarea__el:disabled { background: var(--color-surface-sunken); opacity: 0.7; cursor: not-allowed; }
|
|
17626
17711
|
.twc-textarea__el[data-readonly] { background: var(--color-surface-sunken); }
|
|
17627
17712
|
.twc-textarea__el[data-autosize="true"] { resize: none; overflow: hidden; }
|
|
17713
|
+
/* #328: clearable (X). Wrap positions the button top-inline-end so it dodges the bottom-right resize handle. */
|
|
17714
|
+
.twc-textarea__wrap { position: relative; display: block; }
|
|
17715
|
+
.twc-textarea__clear { position: absolute; top: 6px; inset-inline-end: 8px; display: inline-grid; place-items: center; width: 22px; height: 22px; padding: 0; border: none; background: var(--color-surface); color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-sm); transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
|
|
17716
|
+
.twc-textarea__clear:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
17717
|
+
.twc-textarea__clear:focus-visible { outline: none; box-shadow: var(--ring); }
|
|
17718
|
+
.twc-textarea__clear svg { width: 15px; height: 15px; }
|
|
17628
17719
|
.twc-field__footer { display: flex; align-items: center; gap: var(--space-2); }
|
|
17629
17720
|
.twc-field__count { margin-inline-start: auto; font-size: var(--text-xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; flex: none; }
|
|
17630
17721
|
.twc-field__count[data-danger="true"] { color: var(--color-danger-subtle-fg); }
|
|
@@ -17641,6 +17732,7 @@ var Textarea = React51__default.forwardRef(function Textarea2({
|
|
|
17641
17732
|
minRows,
|
|
17642
17733
|
maxRows,
|
|
17643
17734
|
showCount = false,
|
|
17735
|
+
clearable = false,
|
|
17644
17736
|
disabled = false,
|
|
17645
17737
|
id,
|
|
17646
17738
|
className = "",
|
|
@@ -17687,8 +17779,18 @@ var Textarea = React51__default.forwardRef(function Textarea2({
|
|
|
17687
17779
|
};
|
|
17688
17780
|
const handleChange = (e) => {
|
|
17689
17781
|
rest.onChange?.(e);
|
|
17690
|
-
if (showCount && !countControlled) setLen(e.target.value.length);
|
|
17782
|
+
if ((showCount || clearable) && !countControlled) setLen(e.target.value.length);
|
|
17783
|
+
};
|
|
17784
|
+
const clearField = () => {
|
|
17785
|
+
const el = innerRef.current;
|
|
17786
|
+
if (!el) return;
|
|
17787
|
+
const setter = typeof HTMLTextAreaElement !== "undefined" && Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set;
|
|
17788
|
+
if (setter) setter.call(el, "");
|
|
17789
|
+
else el.value = "";
|
|
17790
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
17791
|
+
el.focus();
|
|
17691
17792
|
};
|
|
17793
|
+
const showClear = clearable && count > 0 && !disabled && !rest.readOnly;
|
|
17692
17794
|
const ariaInvalid = invalid ? true : rest["aria-invalid"] ?? void 0;
|
|
17693
17795
|
const describedBy = [error || hint ? descId : null, showCounter ? countId : null, rest["aria-describedby"]].filter(Boolean).join(" ") || void 0;
|
|
17694
17796
|
return /* @__PURE__ */ jsxs("div", { className: `twc-field ${className}`, children: [
|
|
@@ -17697,27 +17799,33 @@ var Textarea = React51__default.forwardRef(function Textarea2({
|
|
|
17697
17799
|
label,
|
|
17698
17800
|
required ? /* @__PURE__ */ jsx("span", { className: "twc-field__req", children: "*" }) : null
|
|
17699
17801
|
] }) : null,
|
|
17700
|
-
/* @__PURE__ */
|
|
17701
|
-
|
|
17702
|
-
|
|
17703
|
-
|
|
17704
|
-
|
|
17705
|
-
|
|
17706
|
-
|
|
17707
|
-
|
|
17708
|
-
|
|
17709
|
-
|
|
17710
|
-
|
|
17711
|
-
|
|
17712
|
-
|
|
17713
|
-
|
|
17714
|
-
|
|
17715
|
-
|
|
17716
|
-
|
|
17717
|
-
|
|
17718
|
-
|
|
17719
|
-
|
|
17720
|
-
|
|
17802
|
+
/* @__PURE__ */ jsxs("div", { className: "twc-textarea__wrap", children: [
|
|
17803
|
+
/* @__PURE__ */ jsx(
|
|
17804
|
+
"textarea",
|
|
17805
|
+
{
|
|
17806
|
+
ref: setRef,
|
|
17807
|
+
id: fieldId,
|
|
17808
|
+
className: "twc-textarea__el",
|
|
17809
|
+
"data-size": size,
|
|
17810
|
+
"data-tone": tone,
|
|
17811
|
+
"data-autosize": autosize || void 0,
|
|
17812
|
+
"data-readonly": rest.readOnly || void 0,
|
|
17813
|
+
rows: autosize ? minRows ?? rows : rows,
|
|
17814
|
+
disabled,
|
|
17815
|
+
required: required || void 0,
|
|
17816
|
+
"aria-required": required || void 0,
|
|
17817
|
+
...rest,
|
|
17818
|
+
onInput: handleInput,
|
|
17819
|
+
onChange: handleChange,
|
|
17820
|
+
"aria-invalid": ariaInvalid,
|
|
17821
|
+
"aria-describedby": describedBy
|
|
17822
|
+
}
|
|
17823
|
+
),
|
|
17824
|
+
showClear ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-textarea__clear", "aria-label": "Clear", tabIndex: 0, onMouseDown: (e) => e.preventDefault(), onClick: clearField, children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
17825
|
+
/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
|
|
17826
|
+
/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
|
|
17827
|
+
] }) }) : null
|
|
17828
|
+
] }),
|
|
17721
17829
|
error || hint || showCounter ? /* @__PURE__ */ jsxs("div", { className: "twc-field__footer", children: [
|
|
17722
17830
|
error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : hint ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__hint", children: hint }) : null,
|
|
17723
17831
|
showCounter ? /* @__PURE__ */ jsxs("span", { id: countId, className: "twc-field__count", "data-danger": near || void 0, "aria-live": "polite", children: [
|